CC323x看门狗定时器与SD主机控制器实战配置指南

1. 项目概述与核心价值

在嵌入式系统开发这条路上摸爬滚打了十几年,我处理过无数因“死机”导致的现场故障。从工业产线到智能家居设备,一个看似微小的软件跑飞或外部干扰,都可能导致整个系统“罢工”,轻则数据丢失,重则引发安全事故。这时候,看门狗定时器就成了嵌入式工程师手中最可靠的那道“保险丝”。它不生产代码,也不处理业务逻辑,它的唯一使命就是在系统“迷失”时,果断地拉下复位开关,让一切重归正轨。

今天,我们就以德州仪器SimpleLink™ Wi-Fi® CC323x系列这款在物联网领域大放异彩的MCU为例,深入拆解其内置的看门狗定时器模块。这不仅仅是一篇寄存器手册的翻译,我会结合多年实战中踩过的坑、总结的技巧,带你从原理到配置,从常规使用到异常恢复,彻底掌握如何让WDT成为你系统稳定运行的“守护神”。同时,我们也会探讨其SD主机控制器的配置与使用,这是连接外部存储、实现数据落地的关键桥梁。无论你是刚接触CC32xx的新手,还是想优化现有设计的老鸟,这篇文章都能提供可直接“抄作业”的配置指南和避坑心得。

2. 看门狗定时器深度解析与实战配置

2.1 WDT核心工作机制:你的系统“心跳监护仪”

可以把WDT想象成一个严格的“心跳监护仪”。系统正常运行时,软件必须定期(在计数器减到零之前)去“喂狗”,即重置计数器。这个动作证明了“我还活着,意识清醒”。一旦软件因死循环、堆栈溢出或外部设备无响应而“卡死”,无法按时喂狗,监护仪就会报警(触发中断)甚至采取强制措施(系统复位)。

CC32xx的WDT模块核心是一个32位递减计数器,由80 MHz的系统时钟驱动。其工作流程精妙地设计为两级防护:

  1. 首次超时:计数器从加载值递减至0,触发一个可屏蔽的中断。这给了系统一个“自救”的机会,中断服务程序可以尝试记录错误、保存关键数据或进行局部恢复。
  2. 二次超时:如果中断未被及时清除(意味着第一次故障未能修复),计数器会自动重载并再次开始递减。若在第二次计数期间中断仍未清除,则WDT会拉低系统的复位信号,强制整个MCU重启,这是最彻底的恢复手段。

这种“先警告,后复位”的机制,在应对复杂故障时非常有用。例如,某个非关键任务死锁,触发第一次中断后,看门狗中断服务程序可以尝试终止该任务并重启它,从而避免波及整个系统的复位。

2.2 关键寄存器详解与配置策略

手册列出了多个寄存器,但实战中我们重点关注以下几个。理解它们每一位的含义,是精准配置的前提。

#### 2.2.1 WDTLOAD:设定“心跳”间隔

这是看门狗的“生命值”设定寄存器。你写入的值决定了从“喂狗”到“超时”的周期。

  • 地址偏移:0x0
  • 复位值:0xFFFFFFFF
  • 作用:写入后,该值会立即加载到32位递减计数器中,并开始计数。特别注意:如果写入0,会立即产生超时中断。这不是常规操作,但可用于测试或紧急触发。

如何计算超时时间?公式很简单:超时时间(秒) = (WDTLOAD值 + 1) / 系统时钟频率(Hz)。 例如,系统时钟为80 MHz (80,000,000 Hz),若希望超时时间为1秒:WDTLOAD = 超时时间 * 时钟频率 - 1 = 1 * 80,000,000 - 1 = 79,999,999 (0x4C4B3FF)。 在实际项目中,我通常会将超时时间设定在主循环执行周期的3-5倍。比如主循环确保100ms执行一次,那么WDT超时可设为300-500ms。这样既能及时检测到卡死,又不会因任务偶尔的轻微延迟而误触发。

#### 2.2.2 WDTCTL:控制核心逻辑

这是看门狗的大脑,控制着中断和复位的使能。

  • 地址偏移:0x8
  • 复位值:0x80000000
  • 关键位域
    • 位0 INTEN:中断使能。这是最关键的一位。写入1使能WDT中断,同时也就使能了整个看门狗定时器。一旦置位,只有硬件复位才能将其清零。这意味着,只要你开启了看门狗,就必须负起定期喂狗的责任,没有“软件关闭”的后路可走,这从硬件上确保了安全性。
    • 位2 INTTYPE:中断类型。在CC32xx中固定为0,表示标准中断。

#### 2.2.3 WDTICR & WDTRIS:中断状态管理

  • WDTICR:中断清除寄存器。任何写入操作都会清除当前的中断标志,并自动从WDTLOAD寄存器重载计数器值。这是“喂狗”的标准操作之一。
  • WDTRIS:原始中断状态寄存器。即使中断在控制器中被屏蔽,也可以通过轮询此寄存器位0来判断是否发生超时,用于深度调试。

#### 2.2.4 WDTLOCK:配置锁与解锁

这是防止软件跑飞后意外修改WDT配置的硬件锁。

  • 地址偏移:0xC00
  • 解锁密码:0x1ACC_E551。向该寄存器写入此特定值,才能解锁并对其他寄存器进行写操作。
  • 锁定:写入任何非解锁密码的值,都会立即(约2个时钟周期后)锁定所有寄存器(WDTTEST除外)。
  • 读取:读操作不返回值,而是返回锁状态:0=未锁定,1=已锁定。

> 实战技巧:何时上锁?我的习惯是在系统初始化阶段,配置完WDTLOAD、WDTCTL等寄存器后,立即写入一个非解锁值(例如0)来锁定配置。这可以防止后续异常的程序流(如数组越界写)篡改看门狗设置,确保安全机制本身不被破坏。在需要更新超时时间等罕见情况下,再临时解锁、修改、重新上锁。

2.3 完整配置流程与代码实现

理解了寄存器,我们来看如何一步步在代码中激活看门狗。以下流程基于TI的驱动库,但原理适用于任何直接操作寄存器的场景。

#### 2.3.1 初始化与使能步骤

  1. 使能外设时钟:WDT模块的时钟默认可能关闭,需通过PRCM模块开启。
    // 假设使用TI驱动库 PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK);
  2. 软复位WDT模块:确保从一个已知状态开始。
    PRCMPeripheralReset(PRCM_WDT);
  3. 解锁配置:写入魔法数字。
    HWREG(WDT_BASE + WDT_O_LOCK) = 0x1ACCE551;
  4. 配置加载值:根据所需超时时间计算并写入。
    // 设置约1秒超时 (80MHz时钟) uint32_t timeoutValue = 80000000 - 1; // 1秒 HWREG(WDT_BASE + WDT_O_LOAD) = timeoutValue;
  5. 配置控制寄存器:使能中断(同时也使能了WDT)。
    // 读取当前值,设置INTEN位,并保持其他位不变 uint32_t regValue = HWREG(WDT_BASE + WDT_O_CTL); regValue |= WDT_CTL_INTEN; // 使能中断 HWREG(WDT_BASE + WDT_O_CTL) = regValue;
  6. 锁定配置:防止意外修改。
    HWREG(WDT_BASE + WDT_O_LOCK) = 0x0; // 写入任意非解锁值即可上锁
  7. 注册中断服务程序:准备好处理第一次超时。
    WatchdogIntRegister(WDT_BASE, WatchdogIntHandler); WatchdogIntEnable(WDT_BASE, WDT_INT_TIMEOUT); // 使能超时中断 IntEnable(INT_WATCHDOG); // 使能CPU级中断

#### 2.3.2 “喂狗”服务程序喂狗必须在主循环或一个确保定期执行的任务中完成。

void main(void) { // ... 系统初始化,包括WDT初始化 while(1) { // ... 主循环业务逻辑 // 定期“喂狗”,重置计数器 WatchdogIntClear(WDT_BASE); // 写入WDTICR,清除中断并重���计数器 // 或者使用:HWREG(WDT_BASE + WDT_O_ICR) = 0x1; } }

#### 2.3.3 中断服务程序示例当第一次超时发生时,会进入此中断。这里应进行最精简的错误处理。

void WatchdogIntHandler(void) { // 1. 清除中断标志(非常重要,否则会持续进入中断) uint32_t intStatus = WatchdogIntStatus(WDT_BASE, true); WatchdogIntClear(WDT_BASE, intStatus); // 2. 紧急错误处理 // - 记录错误到非易失性存储器(如Flash的特定扇区) // - 设置系统错误标志 // - 尝试恢复关键服务(如关闭无线模块) // 注意:此处操作必须极其快速,因为第二次超时计时已经开始! // 绝对避免在此处进行复杂计算、延时或可能阻塞的操作。 // 3. 如果判断为可恢复错误,可以不做额外操作,主循环中的喂狗会恢复正常。 // 如果判断为严重错误,可以主动触发软件复位,或等待第二次超时硬件复位。 // PRCMSystemReset(); // 主动复位 }

3. 系统看门狗的特殊考量与恢复序列

CC32xx作为一个集成Wi-Fi的SoC,其内部结构比普通MCU更复杂。手册中特别强调了“MCU看门狗控制器使用注意事项”,这是很多开发者容易忽略却至关重要的部分。

3.1 问题本质:域间复位不同步

在CC323x系列中,当系统看门狗触发复位时,其行为是:MCU域和网络处理器域被复位,但WLAN域(MAC和基带)并未复位。这就导致了一个问题:系统恢复时,MCU和NWP同时退出复位,而正常的软件启动流程要求MCU完全启动后,再去初始化并启动NWP。这种恢复顺序与正常启动顺序不一致,可能导致WLAN子系统状态混乱,无法完成一次“干净”的全局复位。

3.2 官方解决方案:强制休眠唤醒

为此,TI给出了明确的解决方案。如果你的应用运行在CC3220等需要此处理的型号上,必须在检测到看门狗复位后,执行以下恢复序列:

  1. 检测复位源:系统启动后,首先读取GPRCM:APPS_RESET_CAUSE[7:0]寄存器(物理地址 0x4402 D00C)。如果该寄存器值为0x05,则表明上次复位是由看门狗超时引起的。
  2. 执行强制休眠:一旦确认为看门狗复位,应用程序应立即请求PRCM进入完整的休眠模式,并设置一个内部RTC定时器(例如10ms后唤醒)。
  3. 唤醒后正常启动:从休眠中唤醒后,整个芯片经历了完整的电源周期清理,所有域都处于初始状态。此时,再像冷启动一样,执行标准的初始化流程(包括MCU、NWP、WLAN的初始化)。

> 避坑指南:为什么是10ms?这个10ms的休眠时间并非随意设定。它必须足够长,以确保芯片内部所有电容放电完毕,各电源域完全关闭再上电,从而达到彻底清理状态的目的。时间太短可能清理不彻底,太长则影响恢复速度。TI在CC3200上推荐10ms,这是一个经过验证的可靠值。对于CC3220及后续型号,这一步骤已由MCU ROM引导程序自动完成,但了解其原理对于调试复杂问题仍有帮助。

3.3 恢复序列代码框架

void SysResetRecoveryHandler(void) { uint32_t resetCause = HWREG(0x4402D00C); // 读取复位原因寄存器 if ((resetCause & 0xFF) == 0x05) { // 判断是否为WDT复位 // 1. 保存必要的崩溃上下文信息(如果有) saveCrashContext(); // 2. 配置RTC在10ms后唤醒 PRCMHibernateIntervalSet(330); // 假设32kHz时钟,330 ticks ≈ 10ms PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR); // 3. 进入休眠 PRCMEnterHibernate(); // 代码执行将在此暂停,直到RTC唤醒 // 4. 唤醒后,不会回到这里,而是从复位向量重新开始。 // 因此,需要在main()函数最开始调用本函数进行检查。 } } int main(void) { // 第一步:检查并处理看门狗复位恢复 SysResetRecoveryHandler(); // 第二步:正常的系统初始化 // ... (初始化外设、创建任务等) while(1) { // ... 主循环 } }

4. SD主机控制器接口配置与应用

SD卡因其体积小、容量大、价格低廉,成为嵌入式系统扩展存储的首选。CC32xx内置的SD主机控制器,为我们提供了直接连接SD卡的能力。

4.1 SD主机控制器功能概述

该控制器实现了SD物理层协议,减轻了MCU的负担。它的核心特性包括:

  • 协议支持:完全兼容SD存储卡规范v2.0,支持标准容量卡和高容量卡。
  • 接口模式:支持1位SD总线模式。
  • 内置缓冲区:拥有1KB的缓冲区(512字节发送FIFO + 512字节接收FIFO),用于数据吞吐。
  • DMA支持:提供独立的TX和RX DMA通道,可实现高效的数据搬运,解放CPU。
  • 可编程时钟:最大支持24 MHz的卡时钟频率。

4.2 硬件连接与引脚复用

CC32xx通过三个主要信号线与SD卡连接:

  1. CLK:时钟信号,由主机控制器输出至SD卡。
  2. CMD:命令/响应线,双向。用于发送命令和接收响应。
  3. DATA:数据线,双向。用于数据传输。

在硬件设计上,CC32xx内部集成了收发器,因此通常可以直接连接SD卡座,无需外部电平转换芯片,这简化了PCB设计。在软件上,首要步骤就是正确配置引脚复用功能,将对应MCU引脚设置为SD主机模式。

4.3 初始化与基础配置流程

使用TI的外设库可以大大简化操作。以下是基本的初始化序列:

#include "ti/drivers/SD.h" #include "ti/drivers/pin/PINCC32XX.h" // 1. 使能SD主机控制器时钟 PRCMPeripheralClkEnable(PRCM_SDHOST, PRCM_RUN_MODE_CLK); // 2. 配置引脚复用(以CC3235S LaunchPad为例,具体引脚查数据手册) PIN_Config sdPinTable[] = { BOARD_SD_HOST_CLK_PIN | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* CLK */ BOARD_SD_HOST_CMD_PIN | PIN_INPUT_EN | PIN_PULLUP, /* CMD */ BOARD_SD_HOST_DAT0_PIN | PIN_INPUT_EN | PIN_PULLUP, /* DAT0 */ PIN_TERMINATE }; PIN_Handle sdPinHandle = PIN_open(&sdPinState, sdPinTable); // 3. 软复位并初始化主机控制器 PRCMPeripheralReset(PRCM_SDHOST); SDHostInit(SDHOST_BASE); // 4. 设置SD卡时钟频率 // 参数:控制器基地址,SD主机输入时钟频率(Hz),期望的SD卡时钟频率(Hz) SDHostSetExpClk(SDHOST_BASE, PRCMPeripheralClockGet(PRCM_SDHOST), 15000000); // 设置为15MHz

4.4 SD卡检测、初始化与读写实战

SD协议有一套标准的初始化序列,用于识别卡类型(SDSC v1, SDSC v2, SDHC/SDXC)并获取其相对地址。

#### 4.4.1 发送命令的通用函数这是与SD卡通信的基础,几乎所有操作都基于此。

int32_t SD_SendCmd(uint32_t ulBase, uint32_t ulCmd, uint32_t ulArg) { uint32_t ulStatus; // 清除所有中断状态 SDHostIntClear(ulBase, 0xFFFFFFFF); // 发送命令和参数 if (SDHostCmdSend(ulBase, ulCmd, ulArg) != 0) { return -1; // 发送失败 } // 等待命令完成或发生错误 do { ulStatus = SDHostIntStatus(ulBase); ulStatus &= (SDHOST_INT_CC | SDHOST_INT_ERRI); // 关注命令完成或错误中断 } while (!ulStatus); // 检查是否出错 if (ulStatus & SDHOST_INT_ERRI) { SDHostCmdReset(ulBase); // 复位命令线 return -2; // 命令执行错误 } return 0; // 成功 }

#### 4.4.2 卡初始化流程精讲初始化是一个命令-响应的对话过程,目的是让卡进入就绪状态并识别其身份。

SD_Handle sdHandle; SD_Params sdParams; SD_Params_init(&sdParams); sdParams.bitRate = 15000000; // 15 Mbps // 打开SD驱动实例 sdHandle = SD_open(BOARD_SD_HOST_INSTANCE, &sdParams); if (sdHandle == NULL) { // 处理错误:可能是物理连接问题、卡不支持、或时钟频率不合适 while(1); } // 初始化卡(驱动内部会完成CMD0, CMD8, ACMD41, CMD2, CMD3等一系列标准序列) if (SD_initialize(sdHandle) != SD_STATUS_SUCCESS) { // 初始化失败:可能是卡损坏、格式不被支持(如exFAT需额外处理) SD_close(sdHandle); while(1); }

驱动库封装了复杂的初始化序列,但了解其内部步骤对调试至关重要:

  1. CMD0 (GO_IDLE_STATE):使卡进入空闲状态。
  2. CMD8 (SEND_IF_COND):检查卡是否支持SDHC/SDXC(电压范围、检查模式)。
  3. ACMD41 (SD_SEND_OP_COND):发送操作条件,激活卡,并获取OCR寄存器信息,确认卡是否就绪以及是否支持高容量。
  4. CMD2 (ALL_SEND_CID):获取卡的唯一CID号。
  5. CMD3 (SEND_RELATIVE_ADDR):为卡分配一个相对地址,用于后续寻址。

#### 4.4.3 单块与多块读写操作初始化成功后,就可以进行数据读写。SD协议支持单块(CMD17/24)和多块(CMD18/25)读写。

// 1. 单块读取示例 (读取第1024个块,块大小通常为512字节) uint8_t readBuffer[512]; SD_read(sdHandle, readBuffer, 1024, 1); // 从块地址1024开始,读1个块 // 2. 多块写入示例 (写入连续10个块) uint8_t writeBuffer[512 * 10]; // ... 填充writeBuffer数据 ... SD_write(sdHandle, writeBuffer, 2048, 10); // 从块地址2048开始,写10个块 // 3. 使用DMA进行高效数据传输(驱动库通常自动管理) // 在SD_Params中可以选择传输模式,驱动会优先使用DMA sdParams.transferMode = SD_MODE_DMA; // 或 SD_MODE_POLLING, SD_MODE_BLOCKING

> 性能优化与实测心得根据手册提供的测试数据,使用24 MHz卡时钟,在16GB Class 4 SDHC卡上,读取速度可达约9.4 Mbps,写入速度约为2.97 Mbps。写入速度远低于读取,这符合SD卡的特性。提升写入性能的关键

  • 使用多块写入命令:相比多次单块写入,一次多块写入能减少命令开销。
  • 启用DMA:将CPU从数据搬运中解放出来。
  • 合理设置块大小:尽量使用较大的块(如32KB、64KB)进行读写,减少寻址和协议开销。
  • 注意卡兼容性:手册提到某些品牌(如测试中的Kingston卡)可能需要特殊的初始化序列。在实际项目中,务必用你计划使用的卡型号进行充分测试。

5. 常见问题排查与调试技巧实录

即使按照手册和指南操作,在实际开发中依然会遇到各种问题。下面是我总结的一些典型问题及其排查思路。

5.1 看门狗定时器常见问题

问题1:看门狗频繁误复位,但软件逻辑看似正常。

  • 可能原因:喂狗间隔设置得太短,主循环或关键任务执行时间偶尔超过看门狗超时周期。
  • 排查步骤
    1. 测量最坏情况执行时间:使用GPIO翻转或分析工具,测量主循环或喂狗任务在最繁忙、中断最多的情况下的最长执行时间。
    2. 合理设置超时:将看门狗超时时间设置为“最坏情况执行时间”的2-3倍以上,留足余量。
    3. 检查中断服务程序:确保WDT中断服务程序执行时间极短,避免在ISR中喂狗,否则可能掩盖主循环卡死的问题。
  • 我的经验:在一个无线数据采集项目中,我们曾发现当Wi-Fi断线重连时,网络处理任务会临时占用大量CPU时间,导致主循环延迟。最终通过将看门狗超时从500ms调整到2s,并优化重连算法解决了问题。

问题2:看门狗复位后,系统仍然无法正常启动。

  • 可能原因:未正确处理看门狗复位恢复序列(针对CC3220等需要此步骤的型号),导致WLAN子系统状态异常。
  • 排查步骤
    1. main()函数最开始,读取并打印复位原因寄存器值。
    2. 确认是否为看门狗复位(值0x05)。
    3. 如果确认是,检查是否执行了强制休眠-唤醒流程。如果没有,补上该逻辑。
    4. 检查休眠时间是否足够(推荐10ms以上)。
  • 我的经验:曾遇到设备在强干扰环境下频繁看门狗复位,但偶尔复位后Wi-Fi再也无法连接。正是通过添加复位原因检测和强制休眠恢复序列,彻底解决了此问题。

问题3:调试时,单步执行导致看门狗触发。

  • 可能原因:在调试模式下,CPU暂停运行,但看门狗计数器仍在递减。
  • 解决方案:利用WDTTEST寄存器的STALL位。在初始化看门狗后,解锁并设置此位为1。
    // 解锁WDT配置 HWREG(WDT_BASE + WDT_O_LOCK) = 0x1ACCE551; // 设置STALL位,使调试暂停时WDT也暂停 HWREG(WDT_BASE + WDT_O_TEST) |= WDT_TEST_STALL_EN; // 重新锁定 HWREG(WDT_BASE + WDT_O_LOCK) = 0x0;
    这样,当通过调试器暂停CPU时,看门狗也会暂停计数,方便调试。

5.2 SD主机控制器常见问题

问题1:SD卡初始化失败,返回“无卡”或“初始化错误”。

  • 排查清单
    1. 物理连接:检查SD卡座是否接触良好,CLK、CMD、DAT0三条线是否连接正确,上拉电阻(通常10kΩ-100kΩ)是否已焊接。CMD和DAT线必须上拉
    2. 电源:测量SD卡供电电压是否在2.7-3.6V范围内,且上电时序平稳。瞬间大电流可能导致电压跌落。
    3. 时钟频率:初始化阶段应使用较低频率(如400kHz或1MHz),成功后再切换到更高频率。尝试降低SDHostSetExpClk的初始频率。
    4. 引脚配置:确认引脚复用配置正确,特别是CLK引脚是否已配置为输出模式。
    5. 卡兼容性:尝试换一张不同品牌、不同容量的SD卡(优先使用SanDisk, Transcend等兼容性好的品牌)。有些卡对初始化时序要求严格。

问题2:读写SD卡过程中数据错误或CRC错误。

  • 可能原因
    1. 时序问题:卡时钟频率过高或不稳定。尝试降低操作频率。
    2. 信号完整性问题:PCB走线过长、过细,或靠近噪声源,导致信号畸变。确保SD信号线走线尽量短,并包地处理。
    3. 电源噪声:SD卡工作时电流变化大,电源纹波可能影响其内部逻辑。在SD卡VCC引脚附近放置一个10uF和一个0.1uF的电容进行去耦。
    4. 文件系统层错误:可能是底层读写函数返回成功,但文件系统逻辑出错。尝试使用SD_format函数(谨慎!会清空数据)重新格式化卡为FAT32格式。
  • 调试技巧:使用逻辑分析仪抓取CLK、CMD、DAT0波形,对照SD物理层协议手册,检查命令响应和数据传输的时序和信号质量。

问题3:多块写入时,写入速度远低于预期。

  • 优化方向
    1. 检查卡性能:确认使用的SD卡速度等级(Class 10, UHS-I等)。低速卡是性能瓶颈。
    2. 启用DMA:确保SD驱动配置为DMA模式,而不是轮询模式。
    3. 增大传输块大小:避免以512字节为单位频繁读写。一次性读写4KB、8KB甚至更大的数据块能显著提升吞吐量。
    4. 减少文件系统开销:如果使用FATFS等文件系统,频繁的f_openf_close会带来额外开销。保持文件打开状态进行连续写入。
    5. 检查中断优先级:确保SD主机控制��的中断优先级足够高,避免因被其他中断长时间阻塞而导致DMA传输延迟。

5.3 综合问题排查表

现象可能原因排查步骤解决方案
系统不定期复位1. WDT超时
2. 电源不稳
3. 堆栈溢出
1. 检查复位原因寄存器
2. 测量电源纹波
3. 检查喂狗代码位置和周期
1. 调整WDT超时时间,优化代码
2. 加强电源滤波
3. 增大堆栈,检查递归函数
SD卡无法识别1. 硬件连接问题
2. 初始化时钟太快
3. 卡损坏或不兼容
1. 检查连线、上拉电阻
2. 降低初始时钟频率至400kHz
3. 更换SD卡测试
1. 修复硬件
2. 修改代码,分步提速
3. 选用兼容性好的卡
SD卡读写数据错误1. 信号完整性差
2. 文件系统损坏
3. 操作频率过高
1. 用逻辑分析仪看波形
2. 尝试格式化
3. 降低读写时钟频率
1. 优化PCB布局布线
2. 修复文件系统或格式化
3. 使用更稳定的频率
看门狗在调试时触发调试器暂停CPU,WDT未暂停检查WDTTEST寄存器STALL位在初始化代码中使能WDT调试暂停功能

嵌入式开发是细节的艺术,看门狗和SD卡接口这两个基础模块,恰恰是系统稳定性和可靠性的基石。希望这篇融合了原理、代码和实战经验的详解,能帮助你在CC32xx平台上构建出更健壮、更可靠的产品。记住,多思考“为什么这样设计”,多动手实测,遇到问题善用仪器分析,你的工程能力就会在这些细节的打磨中不断提升。