深入解析Stellaris LM3S1968休眠模块与Flash控制器实战
1. 项目概述与核心价值
在嵌入式系统开发,尤其是电池供电或对功耗有严苛要求的物联网、便携式设备中,如何让微控制器(MCU)在“睡着”时依然能感知时间流逝,并在关键时刻“醒来”执行任务,是一门必修的功课。这背后,实时时钟(RTC)模块和与之紧密配合的休眠(Hibernation)机制扮演着核心角色。同时,作为程序与数据的“家”,Flash存储器的可靠编程与安全保护,直接关系到产品的稳定性和知识产权安全。
今天,我们就以TI的经典Cortex-M3内核微控制器——Stellaris LM3S1968为例,深入其休眠模块与Flash控制器的寄存器级细节。你手头的数据手册片段,就像一张精密的电路图,标注了每个关键“阀门”和“开关”的位置。但手册通常只告诉你“是什么”,而我会结合多年的实战经验,为你拆解“为什么”要这么设计,以及在实际项目中“如何”安全、高效地操作这些寄存器,避开那些数据手册里不会写的“坑”。
无论你是正在评估这颗芯片的架构师,还是埋头调试低功耗功能的工程师,这篇文章都将带你超越简单的寄存器读写,从系统设计的角度,理解如何将RTC定时唤醒、Flash安全保护这些特性,组合成一个可靠、低功耗的嵌入式产品方案。我们会从休眠模块的RTC计数器、匹配机制、控制逻辑,一直讲到Flash的编程流程、保护策略及其永久性配置,确保你能获得可直接用于项目开发的干货。
2. 休眠模块深度解析:从RTC到低功耗唤醒
Stellaris LM3S1968的休眠模块是一个相对独立的电源域,其核心是一个32位的RTC计数器,可以在主电源(VDD)断开、仅由备用电池(VBAT)供电的情况下持续运行。这是实现超低功耗待机的硬件基础。
2.1 RTC计数器与匹配寄存器:精准定时唤醒的基石
休眠模块的RTC系统由几个关键寄存器构成,它们共同协作,实现了时间的计量和事件的触发。
2.1.1 HIBRTCC:只读的时光之尺
HIBRTCC寄存器是RTC计数器的当前值窗口,它是一个只读(RO)寄存器,地址偏移为0x000。这意味着你无法直接写入这个寄存器来修改时间。其复位值为0x0000.0000。
核心理解:为什么设计成只读?这是为了保证计数器值的连续性和不可篡改性。RTC作为系统的时间基准,其值必须单调递增。如果允许软件随意写入,可能导致时间跳变或回退,破坏依赖于时间顺序的逻辑(如日志时间戳、定时任务调度)。软件对计数器初始值的设置,需要通过另一个寄存器——
HIBRTCLD(加载寄存器)来完成。
2.1.2 HIBRTCM0/HIBRTCM1:唤醒事件的“闹钟”
HIBRTCM0和HIBRTCM1是两个32位的读/写(R/W)匹配寄存器,地址偏移分别为0x004和0x008。它们的复位值都是0xFFFF.FFFF。
- 功能:你可以将它们理解为两个“闹钟”。当只读的
HIBRTCC计数器值增长到与HIBRTCM0或HIBRTCM1中设定的值相等时,就会产生一个“匹配事件”。 - 应用场景:
- 单次定时唤醒:设置
HIBRTCM0为一个未来时间点,使能RTC唤醒(HIBCTL.RTCWEN),进入休眠。当计数器到达该值时,MCU被唤醒。 - 周期性任务:在唤醒后的中断服务程序里,读取当前的
HIBRTCC值,加上一个固定的间隔(例如,1秒对应的计数值),再写入HIBRTCM0,即可实现周期性的定时唤醒。 - 双事件调度:可以利用两个匹配寄存器实现更复杂的调度,例如,用
RTCM0设定每日定时,用RTCM1设定一个更短间隔的看门狗式唤醒进行检查。
- 单次定时唤醒:设置
2.1.3 HIBRTCLD:给RTC计数器“上发条”
HIBRTCLD是RTC加载寄存器,地址偏移0x00C,可读可写,复位值0xFFFF.FFFF。
- 操作机制:这是设置RTC初始值或进行时间校正的唯一入口。向
HIBRTCLD写入一个值,这个值并不会立即生效到HIBRTCC。根据数据手册,写入操作会将这个值“加载”到RTC计数器。通常,硬件会在下一个RTC时钟沿或某个同步事件后,将HIBRTCLD的值传递到HIBRTCC。务必查阅更详细的时序图或参考代码来确认你所用芯片的具体加载时机。 - 注意事项:
- 操作顺序:在初始化RTC时,常见的步骤是:先通过
HIBRTCLD设置初始时间,然后等待加载完成(可能需要检查某个状态位或简单延时),再使能RTC计数器(HIBCTL.RTCEN)。 - 时间基准:RTC计数器的时钟源通常是32.768kHz的外部晶振。你需要根据这个频率,将实际的时间(秒、毫秒)转换为需要写入的计数值。例如,要实现10秒后唤醒,写入
HIBRTCM0的值应为当前HIBRTCC值 + 32768 * 10。
- 操作顺序:在初始化RTC时,常见的步骤是:先通过
2.2 休眠控制与中断管理:精细化的电源管理
HIBCTL(休眠控制寄存器)是整个休眠模块的“大脑”,地址偏移0x010。它的每一个位都控制着休眠模块的关键行为。
2.2.1 关键控制位详解
CLK32EN(位6) - 时钟使能:这是休眠模块的“总开关”。必须将此位置1,才能使能32.768kHz时钟电路,进而使用RTC和休眠功能。数据手册特别强调,如果使用晶体,在设置此位后,软件应等待至少20ms,让晶体起振并稳定。忽略这个延时是导致RTC不工作或不准的常见原因。RTCEN(位0) - RTC计数器使能:此位置1后,HIBRTCC计数器才开始递增。通常应在CLK32EN使能并等待稳定后,再设置此位。RTCWEN(位3) - RTC唤醒使能:当此位为1时,RTCM0或RTCM1的匹配事件可以触发芯片从休眠模式唤醒。这是实现定时唤醒的关键。PINWEN(位4) - 外部WAKE引脚使能:使能后,外部信号(如按键)触发WAKE引脚事件也能唤醒芯片。这为基于事件的唤醒提供了途径。LOWBATEN(位5) - 低电压监测使能:使能后,模块会监测备用电池电压VBAT。当VBAT低于阈值VLOWBAT时,会产生低电中断,防止因电池耗尽导致数据丢失。在关键数据存储应用中,应使能此功能。HIBREQ(位1) - 休眠请求:软件将此位置1,是请求进入休眠模式的最后一步。硬件在完成必要的序列后,会清除此位。在唤醒后,此位为0。CLKSEL(位2) - 时钟选择:选择RTC的时钟源分频。对于标准的32.768kHz晶振,应选择“原始输出”(Raw Output,即CLKSEL=1)。如果使用4.194304MHz的晶体,则需要选择128分频输出(CLKSEL=0),以获得32.768kHz的时钟。选错时钟源会导致RTC计时速度错误。
2.2.2 中断系统的协同工作
休眠模块的中断管理通过一组寄存器完成:HIBIM(中断屏蔽)、HIBRIS(原始中断状态)、HIBMIS(屏蔽后中断状态)、HIBIC(中断清除)。
- 中断源:包括RTC匹配0/1(
RTCALT0/1)、低电压(LOWBAT)、外部唤醒(EXTW)。 - 工作流程:
- 使能中断:在
HIBIM寄存器中,将对应中断位设为1(取消屏蔽)。 - 中断产生:当事件发生时,
HIBRIS中对应的原始状态位被硬件置1。如果该中断在HIBIM中未被屏蔽,则HIBMIS中的对应位也会置1,并向NVIC(嵌套向量中断控制器)发出中断请求。 - 中断服务:CPU响应中断,进入中断服务程序(ISR)。
- 清除中断:在ISR中,必须向
HIBIC寄存器的对应位写入1,以清除中断标志。这是写1清除(W1C)的典型操作。注意,读取HIBIC返回值是不确定的,所以只写不读。
- 使能中断:在
- 实战技巧:
- 在进入休眠前,建议先清除所有可能挂起的中断标志(向
HIBIC写入相应值),避免一进入休眠就被残留的中断立即唤醒。 - 在唤醒后的初始化代码中,也应检查并清除中断标志,确保系统状态干净。
- 在进入休眠前,建议先清除所有可能挂起的中断标志(向
2.3 HIBDATA:休眠状态下的“记忆体”
HIBDATA是一个位于0x030到0x12C地址范围的、64个32位字的存储区。它的特殊之处在于,只要备用电池(VBAT)存在,即使在主电源(VDD)完全断开的情况下,这里面的数据也不会丢失。
- 用途:这是为低功耗设计量身定做的“便签本”。你可以在进入深度休眠前,将关键的运行状态、配置参数、待处理的数据指针等保存到
HIBDATA中。当芯片被RTC或外部事件唤醒后,第一件事就是从HIBDATA中恢复这些上下文信息,从而让程序知道“睡着之前我在做什么”,实现无缝的状态恢复。 - 操作:像访问普通SRAM一样,通过指针或内存地址直接读写即可。无需特殊的解锁序列。
- 注意事项:虽然它不丢数据,但其容量有限(256字节)。需要精心设计存储结构,存放最核心的恢复信息。
3. Flash存储器编程与保护机制实战
LM3S1968内部集成了256KB的Flash用于存储程序代码,以及64KB的SRAM。Flash编程接口设计得相对友好,但深入理解其机制和“保护”特性,对于产品化至关重要。
3.1 Flash编程三部曲:FMA, FMD, FMC
对Flash进行写(编程)或擦除操作,严格遵循一个固定的流程,核心是三个寄存器:FMA(地址)、FMD(数据)、FMC(控制命令)。
3.1.1 编程一个32位字
这是最常用的操作,用于更新某个变量或修补部分代码。
- 写数据:将你想要写入Flash的32位数据,写入
FMD寄存器。 - 写地址:将目标Flash地址(必须是4字节对齐的,即地址的低2位为0)写入
FMA寄存器。 - 发命令:向
FMC寄存器写入值0xA442.0001。这个值由两部分构成:0xA442是Flash写入密钥(Write Key),用于防止误操作;0x0001是WRITE命令位。 - 等待完成:轮询
FMC寄存器,直到其中的WRITE位(或ERASE/MERASE位)被硬件自动清除。在此期间,CPU会暂停对Flash的访问,因此如果中断服务程序或关键代码位于Flash中,执行会被挂起。这就是为什么手册建议,如果需要在Flash操作期间执行代码,必须将这部分代码拷贝到SRAM中运行。
3.1.2 擦除一个1KB页
Flash只能将位从1变为0(编程),或从0变为1(擦除)。擦除是以页(Page)为最小单位的,LM3S1968的页大小为1KB。
- 写页地址:将目标擦除页的起始地址(必须是1KB对齐的,即地址的低10位为0)写入
FMA寄存器。 - 发命令:向
FMC寄存器写入值0xA442.0002(ERASE命令)。 - 等待完成:轮询
FMC寄存器直到ERASE位清零。
3.1.3 整片擦除(Mass Erase)
此操作会擦除整个主Flash阵列,使用需极其谨慎。
- 发命令:直接向
FMC寄存器写入值0xA442.0004(MERASE命令)。 - 等待完成:轮询
FMC寄存器直到MERASE位清零。
重要经验:
- 时序配置(USECRL):Flash控制器需要知道系统时钟频率来生成内部时序。在系统时钟频率改变后,必须向
USECRL寄存器写入(频率MHz - 1)的值。例如,系统运行在50MHz,就写入49(0x31)。上电默认值通常支持最大频率,但降频后若不更新,Flash操作可能失败。- 中断处理:Flash操作期间会产生中断(编程完成、访问违例)。可以通过
FCIM寄存器使能这些中断,并在FCMISC中清除标志位。对于时间不敏感的操作,轮询FMC是更简单可靠的方式。
3.2 Flash保护策略:从代码安全到防误写
Flash保护是产品固件安全的防火墙。LM3S1968以2KB为块(Block)单位提供保护,由两组寄存器控制:FMPREn(读使能)和FMPPEn(编程/擦除使能)。
3.2.1 保护策略组合
| 保护模式 | FMPREn (读使能) | FMPPEn (编程使能) | 含义与应用场景 |
|---|---|---|---|
| 执行仅保护 | 0 | 0 | 该块只能被CPU取指执行,不能被任何方式读取数据,也不能被写入或擦除。用于保护核心算法、加密密钥等敏感代码,防止通过调试器或内存读取指令窃取。 |
| 写保护 | 0 | 1 | 该块可以被写入、擦除、执行,但不能读取。此组合不常用,可能用于某些特殊的自修改代码场景。 |
| 只读保护 | 1 | 0 | 该块可以被读取、执行,但不能被写入或擦除。用于保护已固化的引导程序(Bootloader)、出厂校准数据、版本信息等,防止被应用程序意外或恶意修改。 |
| 无保护 | 1 | 1 | 完全开放访问。这是出厂默认状态。 |
3.2.2 “执行仅保护”的陷阱与应对
这是最强保护,但也最容易踩坑。问题在于常量数据(Literal Data)。编译器通常会把代码中的常量(如const table[] = {…})放在代码段(.text)中。当CPU执行LDR指令从Flash加载这些常量时,它发起的是数据读取请求。如果该常量所在的2KB块被设为“执行仅保护”,这次数据读取会被总线阻塞,导致程序跑飞。
解决方案:
- 链接器脚本隔离:这是最推荐的方法。修改链接脚本(如
.ld文件),将所有的常量数据(通常是.rodata段)集中放置到一个或几个单独的、标记为“只读保护”(FMPREn=1)的Flash块中。确保代码段(.text)和常量数据段被分配到不同的保护块。 - 编译器选项:某些编译器支持将常量池(Literal Pool)放置在独立的段中。需要研究具体编译器的文档。
- 手动管理(汇编):在汇编层面,可以将常量数据明确放在特定区域。
3.2.3 保护寄存器的“提交”机制
FMPREn和FMPPEn寄存器本身也存储在Flash的一个特殊区域(非主阵列)。它们的修改有一个“提交(Commit)”机制,防止误操作:
- 临时修改:你可以直接写这些寄存器,将某一位从1改为0。此时保护策略立即生效,但仅限于本次上电周期。
- 永久生效:如果你确认修改正确,需要向
FMC寄存器写入0xA442.0008(COMT命令),并将对应的FMA地址设置为特定值(例如,提交FMPRE0时,FMA=0x0000.0000)。这个操作会将当前寄存器值永久烧写到非易失性存储中。 - 不可逆性:一旦提交,保护位从1变为0的操作就不可逆转!芯片复位、断电都不会恢复。只有从0变为1的操作是不可能的(Flash特性)。因此,在提交前,务必在临时状态下充分测试你的代码,确保“执行仅保护”的块里没有需要读取的常量。
3.3 用户寄存器与调试接口的永久禁用
除了保护寄存器,Flash区还有一组用户可编程的非易失性寄存器,如USER_REG0/1和至关重要的USER_DBG。
USER_DBG寄存器:其DBG0和DBG1位控制着JTAG/SWD调试接口的永久开关。- 警告:将调试接口永久禁用(锁死)是一项不可逆的操作!一旦禁用,你将无法再通过调试器连接芯片、下载程序或进行调试。只有在产品最终量产、且确定未来不需要再通过调试接口更新固件时,才考虑此操作。
- 安全措施:通常,会保留一个通过串口或其他通信接口的引导程序(Bootloader)作为后续固件更新的唯一通道。在禁用调试接口前,必须确保这个引导程序100%可靠,并且其所在的Flash块已被设置为“只读保护”。
USER_REG0/1等:这些是留给用户存储唯一ID、生产日期、硬件版本等信息的空间。它们的编程和提交机制与保护寄存器类似,通过FMA指定地址、FMD提供数据、FMC发送COMMIT命令来完成。
4. 低功耗系统设计实战与问题排查
理解了各个模块后,我们将其组合起来,看一个典型的低功耗应用场景如何实现,并梳理常见问题。
4.1 典型低功耗工作流设计
假设我们设计一个环境传感器,每10分钟采集一次数据并通过无线发送,其余时间深度休眠。
初始化阶段:
- 配置系统时钟,设置
USECRL。 - 初始化休眠模块:使能
CLK32EN,等待20ms+,使能RTCEN。 - 通过
HIBRTCLD设置RTC初始时间(如设为0)。 - 计算10分钟对应的RTC计数值(
10 * 60 * 32768 = 19,660,800)。将当前HIBRTCC值(可读)加上该值,写入HIBRTCM0。 - 使能RTC匹配唤醒中断(
HIBIM.RTCALT0 = 1)和RTC唤醒功能(HIBCTL.RTCWEN = 1)。 - 将必要的唤醒后恢复信息(如传感器通道、上次发送序号)保存到
HIBDATA区域。 - 配置I/O口状态,将未使用的引脚设为模拟输入以降低功耗,关闭外设时钟。
- 配置系统时钟,设置
进入休眠:
- 设置
HIBCTL.HIBREQ = 1。 - 执行一条
WFI(等待中断)指令。芯片进入休眠模式,主电源域可能关闭,仅由VBAT维持休眠模块和RTC运行。
- 设置
唤醒与恢复:
- RTC匹配事件触发,芯片上电复位或从休眠状态恢复。
- 程序从复位向量或唤醒中断入口开始执行。
- 首先,从
HIBDATA中读取并恢复关键状态信息。 - 然后,重新初始化系统时钟、必要的外设(如无线模块)。
- 执行采集和发送任务。
- 任务完成后,重新计算下一个唤醒时间点,更新
HIBRTCM0,清除中断标志(HIBIC.RTCALT0 = 1),然后跳转回步骤2,再次进入休眠。
4.2 常见问题与排查技巧实录
以下是我在项目中实际遇到过的典型问题及解决方法:
问题1:RTC计时不准,唤醒时间漂移。
- 可能原因a:时钟源配置错误。检查
HIBCTL.CLKSEL位,确认其设置与板上实际焊接的晶振频率匹配(32.768kHz选1,4.194304MHz选0)。 - 可能原因b:晶振未起振或不稳定。确保在设置
CLK32EN后,有足够的延时(>20ms)。检查晶振两端是否接有正确的负载电容(通常10-22pF),PCB布局应使晶振靠近芯片,走线短。 - 可能原因c:VBAT电源不稳定。在休眠期间,RTC由VBAT供电。如果VBAT电源纹波大或电压过低,可能导致RTC工作异常。测量VBAT引脚电压,确保其在数据手册规定范围内(通常2.0V-3.6V),并并联一个大的储能电容(如10uF-100uF)。
问题2:无法进入休眠,或休眠后电流依然很大。
- 排查步骤:
- 查外设:确认所有不需要在休眠中工作的外设时钟都已关闭(通过对应的RCGC寄存器)。
- 查I/O:将未使用的GPIO配置为模拟输入模式。输出高电平或低电平的引脚如果外部接有上拉/下拉电阻,会产生漏电流。
- 查唤醒源:检查所有可能的唤醒源是否被意外触发。例如,使能了外部WAKE引脚(
PINWEN)但该引脚浮空,可能因噪声误触发。使能了低电压中断(LOWBATEN)但VBAT电压在阈值附近波动。在进入休眠前,读取并清除HIBRIS中的所有中断标志。 - 查代码流程:确认执行
WFI前,HIBREQ位已被成功置1。单步调试检查相关寄存器值。
问题3:Flash编程失败,程序“卡死”。
- 可能原因a:时钟频率未更新。系统降频运行(例如从50MHz降到16MHz)后,忘记更新
USECRL寄存器。Flash控制器仍按高速时钟的时序工作,导致访问超时失败。务必在时钟配置函数中,在频率改变后立即更新USECRL。 - 可能原因b:地址未对齐。写操作地址必须是4字节对齐(低2位为0),擦除操作地址必须是1KB对齐(低10位为0)。不对齐的地址会导致操作未定义。
- 可能原因c:目标区域被保护。尝试编程或擦除一个
FMPPEn位为0(写保护)的Flash块,操作会被硬件阻止。检查目标地址所属块的保护状态。 - 可能原因d:操作期间发生中断。如果Flash操作耗时较长,且中断服务程序位于正在被操作的Flash区域,会导致CPU取指失败。解决方法是将Flash操作相关的代码(特别是轮询等待循环)和可能被调用的中断服务程序,全部链接到SRAM中执行。
问题4:设置了“执行仅保护”后,程序运行异常。
- 几乎可以断定是常量数据访问违例。使用调试器(如果还没锁死)或通过串口打印,定位程序崩溃的地址。检查该地址附近的代码,看是否有访问大型常量数组、字符串字面量等操作。使用
objdump或readelf工具分析编译后的二进制文件,查看.rodata段被链接到了哪个地址范围,确认该范围是否被错误地设置了“执行仅保护”。
问题5:误操作锁死了调试接口。
- 预防重于治疗:在开发阶段,绝对不要提交对
USER_DBG寄存器的修改。可以在代码中,将对USER_DBG的写操作和COMMIT命令用宏包裹起来,并默认定义为空,只在量产构建时通过编译选项开启。 - 如果已锁死:如果芯片没有其他引导加载程序,那么这颗芯片将无法再通过SWD/JTAG更新程序,基本等于硬件报废。这就是为什么量产前必须进行严格的流程评审。
5. 寄存器操作代码示例与封装建议
直接操作寄存器地址容易出错且可读性差。良好的做法是使用结构体映射和函数封装。
// 1. 寄存器结构体定义 (示例,需根据完整手册补充) typedef struct { __IO uint32_t HIBRTCC; // 0x000 __IO uint32_t HIBRTCM0; // 0x004 __IO uint32_t HIBRTCM1; // 0x008 __IO uint32_t HIBRTCLD; // 0x00C __IO uint32_t HIBCTL; // 0x010 __IO uint32_t HIBIM; // 0x014 __IO uint32_t HIBRIS; // 0x018 __IO uint32_t HIBMIS; // 0x01C __IO uint32_t HIBIC; // 0x020 __IO uint32_t HIBRTCT; // 0x024 uint32_t RESERVED0[(0x030-0x028)/4]; __IO uint32_t HIBDATA[64]; // 0x030 - 0x12C } HIBERNATION_TypeDef; #define HIBERNATION_BASE (0x400FC000UL) #define HIBERNATION ((HIBERNATION_TypeDef *) HIBERNATION_BASE) // 2. 关键操作函数封装 void HIB_InitWith32kCrystal(void) { // 使能休眠模块时钟(假设系统控制中有时钟使能位,此处简化) SYSCTL->RCGC0 |= SYSCTL_RCGC0_HIBERNATION; // 使能32kHz时钟,选择外部晶振 HIBERNATION->HIBCTL = (HIBERNATION->HIBCTL & ~HIBCTL_CLKSEL_MASK) | HIBCTL_CLK32EN; // 关键:等待晶振稳定 DelayMs(25); // 留有余量 // 使能RTC计数器 HIBERNATION->HIBCTL |= HIBCTL_RTCEN; } void HIB_SetWakeupAfterSeconds(uint32_t seconds) { uint32_t current_count; uint32_t target_count; // 读取当前计数器值 current_count = HIBERNATION->HIBRTCC; // 计算目标计数值 (假设32.768kHz时钟) target_count = current_count + (seconds * 32768); // 设置匹配寄存器0 HIBERNATION->HIBRTCM0 = target_count; // 使能RTC匹配唤醒 HIBERNATION->HIBCTL |= HIBCTL_RTCWEN; // 使能RTC匹配中断(如果需要) HIBERNATION->HIBIM |= HIBIM_RTCALT0; } void HIB_EnterHibernation(void) { // 保存状态到HIBDATA (示例) HIBERNATION->HIBDATA[0] = system_state; // 清除可能挂起的中断标志 HIBERNATION->HIBIC = HIBIC_RTCALT0 | HIBIC_EXTW | HIBIC_LOWBAT; // 请求进入休眠 HIBERNATION->HIBCTL |= HIBCTL_HIBREQ; // 等待进入休眠(实际执行WFI指令) __WFI(); // 唤醒后,代码会从这里继续执行 system_state = HIBERNATION->HIBDATA[0]; // 恢复状态 }封装建议:
- 分层:底层提供寄存器位定义和基本操作函数(如
HIB_Enable(),HIB_SetMatch())。上层提供应用级函数(如HIB_SleepForMinutes(10))。 - 错误处理:函数应返回操作状态(成功/失败),并在可能的情况下检查参数有效性(如地址对齐)。
- 临界区保护:对Flash的写/擦除操作可能是耗时且不可打断的,考虑在函数内禁用全局中断,操作完成后再恢复。
- 文档:在函数注释中明确说明前置条件(如时钟已配置)、副作用(如可能禁用中断)和重要限制(如地址对齐要求)。
通过这种从原理到寄存器,再到代码封装和实战经验的全方位剖析,你应该对如何在Stellaris LM3S1968上构建一个健壮的低功耗应用有了清晰的认识。记住,低功耗设计和Flash安全无小事,每一个细节的疏忽都可能导致产品在现场出现难以调试的问题。多测试,多验证,尤其是在提交任何永久性保护设置之前。
