☰
FreeRTOS Tickless Idle低功耗模式:原理、移植与避坑指南
2026/10/16 18:59:47 网站建设 项目流程

1. 从一次电池续航翻车说起:Tickless 到底在解决什么问题

做过嵌入式低功耗产品的人大概都有过这种经历:硬件选型阶段拍着胸脯跟团队保证"这颗MCU待机电流只有几微安,两节五号电池撑一年没问题",结果板子回来一跑,实测待机电流比手册标称值高了两三个数量级,电池撑不过两周。我第一次遇到这个问题的时候,排查了整整三天,从LDO的静态电流查到上拉电阻的漏电流,最后把示波器探头挂到电流采样电阻两端,才看到那个规律性的尖峰——每1毫秒准时来一次,宽度几十微秒,峰值几十毫安。

这个尖峰就是**系统节拍中断(SysTick)**在作祟。FreeRTOS默认配置下,内核依靠一个周期性的硬件定时器产生节拍中断,每次中断都要唤醒CPU、执行调度器逻辑、处理延时链表,然后再回到低功耗模式。哪怕系统里一个任务都没准备好运行,这个节拍也不会停。对于电池供电的设备来说,这相当于雇了一个保安,每毫秒都要把整栋楼的所有灯打开检查一遍,检查完再关掉——灯是关了,但电已经耗掉了。

Tickless Idle 模式就是为解决这个问题而生的。它的核心思路非常朴素:既然系统空闲时不需要那么频繁地"点名",那就干脆把节拍中断关掉,让CPU睡一个长长的觉,等到下一个任务真正需要被唤醒的时候再醒过来。这个"睡多久"由内核根据延时链表里最近的一个到期时间动态计算,睡醒之后再把系统时间补齐,对上层任务来说,时间线是连续的,感知不到中间曾经"停摆"过。

这篇文章适合两类人看:一类是正在做低功耗产品、被续航指标卡住的嵌入式工程师;另一类是已经开了configUSE_TICKLESS_IDLE但发现功耗没降下来、甚至系统行为变得诡异的开发者。我会从内核机制讲到移植实操,把那些手册里不会写、但实际调试中一定会遇到的坑一个个拆开讲。全文基于Cortex-M平台和FreeRTOS的常见移植实践展开,其他架构思路相通,具体寄存器操作需要对照对应芯片的手册。

2. 节拍中断的功耗账:为什么"少醒几次"能省下大量电

2.1 一次节拍中断的真实成本

很多人对节拍中断的功耗成本没有直观概念,觉得"不就是一次中断嘛,能费多少电"。我们把账算细一点。假设MCU运行在48MHz,内核电压3.3V,运行模式电流约10mA,睡眠模式电流约20微安,唤醒时间(从睡眠到稳定运行)约5微秒。

一次节拍中断的完整过程包括:定时器溢出触发中断、CPU从睡眠唤醒、压栈、执行SysTick中断服务程序、调用xTaskIncrementTick()、检查延时链表、可能的上下文切换、返回、重新进入睡眠。保守估计整个中断处理耗时约10微秒,其中CPU处于运行状态的时间约8微秒。

那么单次中断消耗的电荷约为:10mA × 8μs = 80nC。如果节拍频率是1000Hz,每秒就是1000次,每秒消耗电荷80μC,折合平均电流80μA。这个数字意味着什么?意味着你的MCU本来睡眠电流只有20μA,加上节拍中断的开销,实际平均电流变成了100μA,功耗直接翻了五倍。如果产品要求平均电流控制在50μA以内,光节拍中断这一项就已经超标了。

注意:这里的80μA是简化估算,实际值取决于中断处理时长、唤醒时间、是否有其他外设中断等因素。但数量级是对的,节拍中断在低功耗场景下往往是最大的"隐形耗电大户"。

2.2 Tickless 的核心逻辑:把N次短睡合并成一次长睡

Tickless Idle的工作机制可以用一句话概括:在系统空闲时,计算下一个任务到期还有多少个节拍,如果这个数量超过某个阈值,就关掉节拍中断,让MCU进入低功耗模式睡那么长时间,醒来后再把这段时间补进系统节拍计数。

举个例子。假设节拍频率1000Hz,当前系统空闲,延时链表里最近的一个任务还有500个节拍(即500毫秒)才到期。默认模式下,这500毫秒里会发生500次节拍中断,每次都要唤醒CPU。而Tickless模式下,内核会:

  1. 计算出可以睡眠的节拍数:500
  2. 判断500是否大于configEXPECTED_IDLE_TIME_BEFORE_SLEEP(通常设为2或更大)
  3. 如果是,调用移植层提供的vPortSuppressTicksAndSleep(500)函数
  4. 在该函数里,配置一个低功耗定时器在500毫秒后唤醒,然后让CPU进入深度睡眠
  5. 500毫秒后,低功耗定时器唤醒CPU,函数返回实际睡眠的节拍数
  6. 内核调用vTaskStepTick()把这段时间补进节拍计数

整个过程只唤醒了一次,而不是500次。省下来的就是499次中断处理的开销。按照前面的估算,这相当于把500毫秒内的平均电流从100μA降到了接近纯睡眠电流的水平。

2.3 省电效果的量级判断:什么时候值得开

Tickless不是万能的,它的收益取决于空闲时间占总时间的比例和单次中断开销与睡眠电流的比值。我总结了一个粗略的判断标准:

场景特征是否建议开Tickless原因
系统大部分时间在等事件,任务周期≥10ms强烈建议空闲窗口大,合并收益明显
任务周期在1ms左右,CPU负载中等建议仍有合并空间,但收益打折
CPU几乎满负载运行,空闲窗口<1ms不建议睡眠时间太短,唤醒开销可能超过收益
有高频外设中断(如每100μs一次)谨慎外设中断会频繁唤醒,Tickless效果被稀释
电池供电、要求平均电流<100μA必须开不开基本达不到指标

这里有个容易被忽略的点:Tickless的收益不是线性的。当空闲窗口从1ms增加到10ms时,省电效果提升很明显;但从100ms增加到1秒,提升就有限了,因为此时节拍中断的占比已经很低。所以不要指望开了Tickless就能把功耗降到理论最低,它解决的是"高频短睡"的问题,不是"深度睡眠"的问题。深度睡眠的电流取决于你选的睡眠模式和关闭了哪些外设,那是另一个话题。

3. 内核是怎么知道该睡多久的:延时链表与时间补偿机制

3.1 延时链表的排序特性是Tickless的前提

FreeRTOS的延时链表pxDelayedTaskList有一个关键特性:它是按到期时间排序的。当任务调用vTaskDelay()或带超时的阻塞函数时,内核会根据到期时间把它插入到链表的正确位置,保证链表头部的任务是最早到期的。

这个排序特性让Tickless的实现变得简单:内核只需要看链表头部的xItemValue,就知道下一个任务什么时候到期。如果链表为空,说明没有任何任务在等待延时,那就可以一直睡到下一个外部中断到来。

具体来说,在xTaskIncrementTick()被调用之前,prvIdleTask(空闲任务)会检查当前是否有任务就绪。如果没有,就调用portSUPPRESS_TICKS_AND_SLEEP()宏,这个宏最终会展开成移植层的vPortSuppressTicksAndSleep()函数。传入的参数是"下一个任务到期还有多少个节拍",这个值由xNextTaskUnblockTime变量提供。

3.2 时间补偿:醒来后怎么"补账"

睡眠期间节拍中断是关闭的,系统节拍计数器xTickCount不会自动增加。醒来之后,内核需要把睡眠期间"欠"的节拍补上,否则所有延时都会变长,系统时间会漂移。

补偿的过程分两步:

第一步,移植层的vPortSuppressTicksAndSleep()函数在唤醒后,计算出实际睡眠了多少个节拍,然后调用vTaskStepTick(实际睡眠节拍数)。这个函数会把xTickCount增加相应的值,同时检查延时链表,把已经到期的任务移到就绪链表。

第二步,如果睡眠期间有任务到期,vTaskStepTick()会触发调度器检查,确保到期任务能及时运行。

这里有个细节值得注意:vTaskStepTick()内部有一个断言,要求传入的节拍数不能超过xNextTaskUnblockTime - xTickCount。这是为了防止补偿过头,把还没到期的任务错误地唤醒。移植层在计算实际睡眠时间时,必须确保这个值准确,否则会触发断言或者导致任务提前运行。

3.3 低功耗定时器的选择:为什么不能用SysTick自己

SysTick是Cortex-M内核自带的定时器,它的时钟源通常来自内核时钟或外部参考时钟。在深度睡眠模式下,内核时钟往往会被关闭,SysTick也就停了,没法用来唤醒CPU。所以Tickless必须依赖一个在低功耗模式下仍然运行的定时器。

常见的候选包括:

  • RTC(实时时钟):大多数MCU都有,功耗极低,但分辨率通常只有秒级或亚秒级,适合长睡眠
  • LPTIM(低功耗定时器):专门为低功耗设计的定时器,分辨率可达微秒级,是Tickless的理想选择
  • 低功耗通用定时器:某些MCU的通用定时器在睡眠模式下仍可运行,但功耗可能比LPTIM高

选择哪个定时器,取决于你的睡眠时长和精度要求。如果睡眠时间通常在秒级以上,RTC就够了;如果需要毫秒级精度,就得用LPTIM。我在一个项目里用过RTC做Tickless,结果发现当睡眠时间小于1秒时,RTC的分辨率不够,导致实际睡眠时间比预期长,任务响应变慢。后来换成LPTIM才解决。

提示:不是所有MCU的低功耗定时器都能在最低功耗模式下运行。选型时要仔细看手册里的"低功耗模式下的外设可用性"表格,确认你打算用的定时器在目标睡眠模式下是否还在工作。

4. 移植实操:从零配置一个可用的Tickless

4.1 FreeRTOSConfig.h里的关键开关

开启Tickless的第一步是修改配置文件。以下是必须设置的宏:

#define configUSE_TICKLESS_IDLE 1 #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 // 某些移植下需要关闭

configUSE_TICKLESS_IDLE设为1表示启用Tickless Idle模式。configEXPECTED_IDLE_TIME_BEFORE_SLEEP定义了"至少空闲多少个节拍才值得进入Tickless",默认值是2。这个值不能设得太小,否则频繁进出低功耗模式的切换开销会抵消省电收益;也不能太大,否则短空闲窗口被浪费。

我的经验是:如果节拍频率是1000Hz,这个值设为2到5比较合适;如果节拍频率是100Hz,设为1到2即可。具体值需要根据实测的唤醒开销来调整。

另外,某些移植版本在Tickless模式下需要关闭configUSE_PORT_OPTIMISED_TASK_SELECTION,因为该特性依赖特定的指令序列,可能与低功耗模式的进入/退出流程冲突。这个不是绝对的,要看具体移植层的实现。

4.2 实现vPortSuppressTicksAndSleep函数

这是移植的核心工作。FreeRTOS的官方移植通常提供了一个弱定义的vPortSuppressTicksAndSleep(),你需要根据自己的硬件重写它。函数的基本骨架如下:

void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime) { uint32_t ulReloadValue, ulCompleteTickPeriods; TickType_t xModifiableIdleTime; /* 1. 计算低功耗定时器的重载值 */ ulReloadValue = ...; // 根据xExpectedIdleTime计算 /* 2. 停止SysTick,配置低功耗定时器 */ portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; prvConfigureLowPowerTimer(ulReloadValue); /* 3. 进入临界区,检查是否有任务就绪 */ vPortEnterCritical(); if (eTaskConfirmSleepModeStatus() != eAbortSleep) { /* 4. 进入低功耗模式 */ xModifiableIdleTime = xExpectedIdleTime; configPRE_SLEEP_PROCESSING(xModifiableIdleTime); if (xModifiableIdleTime > 0) { __WFI(); // 等待中断 } configPOST_SLEEP_PROCESSING(xExpectedIdleTime); /* 5. 停止低功耗定时器,计算实际睡眠时间 */ prvStopLowPowerTimer(); ulCompleteTickPeriods = ...; /* 6. 补偿节拍 */ vTaskStepTick(ulCompleteTickPeriods); } vPortExitCritical(); /* 7. 恢复SysTick */ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; }

这个骨架里有几个关键点需要展开说。

第一,eTaskConfirmSleepModeStatus()的作用。在进入临界区之后、真正睡眠之前,必须再检查一次是否有任务已经就绪。因为从计算睡眠时间到进入临界区之间,可能有中断发生并唤醒了某个任务。如果此时还有任务就绪,就应该放弃睡眠,直接返回。这个函数返回eAbortSleep表示不能睡,返回eNoTasksWaitingTimeout或eStandardSleep表示可以睡。

第二,configPRE_SLEEP_PROCESSING和configPOST_SLEEP_PROCESSING宏。这两个宏是给用户留的钩子,用来在睡眠前后做一些板级操作,比如关闭外设时钟、切换电源域、配置唤醒引脚等。如果你的板子有额外的低功耗控制寄存器,就在这里操作。

第三,实际睡眠时间的计算。低功耗定时器唤醒后,需要读取它的当前计数值,反推出实际睡眠了多少时间。这里要注意定时器的计数方向(向上还是向下)和时钟频率。计算出的节拍数要传给vTaskStepTick(),且不能超过预期值。

4.3 低功耗定时器的配置细节

以常见的LPTIM为例,配置步骤大致如下:

static void prvConfigureLowPowerTimer(uint32_t ulReloadValue) { /* 使能LPTIM时钟 */ RCC->APB1ENR |= RCC_APB1ENR_LPTIM1EN; /* 选择时钟源,通常用LSI或LSE */ RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0; // 选择LSI /* 配置LPTIM为单次模式,内部时钟源 */ LPTIM1->CFGR = LPTIM_CFGR_PRESC_0 | LPTIM_CFGR_TRIGEN_0; /* 设置重载值 */ LPTIM1->ARR = ulReloadValue; LPTIM1->CMP = ulReloadValue; /* 使能中断 */ LPTIM1->IER |= LPTIM_IER_ARRMIE; NVIC_EnableIRQ(LPTIM1_IRQn); /* 启动定时器 */ LPTIM1->CR |= LPTIM_CR_ENABLE; LPTIM1->CR |= LPTIM_CR_SNGSTRT; }

这段代码里,时钟源的选择很关键。LSI(内部低速时钟)的精度通常在±5%左右,LSE(外部低速晶振)可以做到±20ppm。如果你的应用对时间精度要求高,比如需要精确的通信超时,建议用LSE。但LSE需要外部晶振,增加BOM成本。我一般在对时间精度不敏感的场景用LSI,省一个晶振。

重载值的计算要注意溢出问题。LPTIM通常是16位定时器,最大计数值65535。如果预期睡眠时间对应的计数值超过这个范围,就需要降低定时器时钟频率或者分段睡眠。我在一个项目里遇到过这个问题:节拍频率1000Hz,预期睡眠10秒,对应10000个节拍,LPTIM时钟1kHz时重载值就是10000,没超;但如果睡眠60秒,重载值60000,接近上限,再长就溢出了。解决办法是把LPTIM的预分频调大,或者用RTC做长睡眠。

4.4 唤醒后的时间补偿与边界处理

唤醒后的补偿逻辑是Tickless里最容易出错的地方。核心是要准确计算"实际睡了多少个节拍",然后调用vTaskStepTick()。计算方式取决于定时器的工作模式:

  • 如果是单次向下计数模式,实际睡眠时间 = 重载值 - 当前计数值
  • 如果是单次向上计数模式,实际睡眠时间 = 当前计数值
  • 如果是周期计数模式,需要结合溢出次数计算

计算出的时间要转换成节拍数。转换公式是:节拍数 = 定时器计数差值 / (定时器时钟频率 / 节拍频率)。这里要注意整数除法的截断误差,如果每次睡眠都截断一点,累积起来会导致系统时间明显偏慢。我的做法是保留余数,下次计算时加上。

还有一个边界情况:如果唤醒不是因为低功耗定时器到期,而是因为外部中断(比如按键按下),那么实际睡眠时间可能小于预期。此时vTaskStepTick()传入的值应该小于预期值,剩余的时间由恢复后的SysTick继续计时。这个逻辑在骨架代码里通过"读取定时器当前值"自然处理了,但前提是定时器在外部中断唤醒后仍然在计数,且你能正确读取它的值。

5. 那些手册不会告诉你的坑:实测中遇到的五个典型问题

5.1 坑一:开了Tickless功耗反而更高

这是最反直觉的问题。我遇到过两次,原因各不相同。

第一次是因为低功耗定时器的时钟源没关。LPTIM配置好之后,即使不启动,它的时钟源(比如LSI)也在运行,消耗额外电流。解决方法是每次睡眠结束后,把LPTIM的时钟使能位关掉,下次睡眠前再打开。这个操作增加了一点切换开销,但省下的时钟功耗更可观。

第二次是因为GPIO状态没配置。睡眠前没有把未使用的GPIO设为模拟输入或输出低电平,导致某些引脚处于浮空状态,输入缓冲器产生漏电流。这个问题在睡眠电流只有几微安的时候特别明显,一个浮空引脚可能就贡献几十微安。解决方法是写一个configPRE_SLEEP_PROCESSING钩子,把所有未使用引脚设为模拟模式。

5.2 坑二:任务延时变长了

有开发者反馈,开了Tickless之后,vTaskDelay(100)实际延时变成了120毫秒甚至更长。这个问题通常出在时间补偿计算错误上。

最常见的原因是低功耗定时器的实际时钟频率与代码里假设的不一致。比如代码里按32.768kHz计算,但实际用的是LSI,频率在30kHz到40kHz之间波动。这样算出来的睡眠时间就会偏长或偏短。解决办法是用一个已知的参考时间(比如RTC的秒中断)来校准LSI频率,或者直接用LSE。

另一个原因是补偿时截断误差累积。前面提到过,如果每次睡眠都截断余数,累积起来就会导致时间偏慢。解决方法是把余数保存到一个静态变量里,下次计算时加上。

5.3 坑三:进入睡眠后无法唤醒

这个问题通常发生在调试阶段,表现为程序卡死在__WFI()指令之后。原因可能有几个:

  • 中断优先级配置错误:低功耗定时器的中断优先级如果低于configMAX_SYSCALL_INTERRUPT_PRIORITY,在临界区内无法唤醒CPU。需要确保唤醒中断的优先级足够高。
  • 睡眠模式选得太深:某些低功耗模式下,只有特定引脚或外设能唤醒。如果选的唤醒源在该模式下不可用,就永远醒不过来。需要对照手册确认。
  • 中断标志没清除:如果低功耗定时器的中断标志在进入睡眠前没有清除,中断会立即触发,导致__WFI()直接返回,看起来像是"没睡"。但如果是标志没清除导致中断被屏蔽,就可能真的睡死。

提示:调试Tickless时,建议先用一个GPIO引脚在睡眠前后翻转,用示波器观察实际睡眠时间。这比在IDE里单步调试可靠得多,因为单步调试会破坏低功耗模式。

5.4 坑四:与tickless相关的断言失败

FreeRTOS在vTaskStepTick()里有一个断言:configASSERT(xTicksToStep <= xNextTaskUnblockTime - xTickCount)。如果补偿的节拍数超过了下一个任务的到期时间,就会触发断言。

这个问题的根源通常是睡眠时间计算偏大。比如预期睡100个节拍,但实际计算出来是105个,多出来的5个节拍就会导致断言失败。解决办法是在计算实际睡眠时间时,加一个上限检查:如果计算值超过预期值,就截断到预期值。虽然这样会导致时间略微偏慢,但比触发断言好。

另一个可能的原因是在睡眠期间有任务被创建或唤醒,导致xNextTaskUnblockTime变小。这种情况需要在eTaskConfirmSleepModeStatus()里正确处理,确保睡眠前没有新任务就绪。

5.5 坑五:调试器连接时Tickless不工作

这个问题困扰过很多人。现象是:用调试器连着板子跑,Tickless看起来正常;一旦断开调试器,功耗就降不下来。

原因是调试器会阻止MCU进入深度睡眠。Cortex-M内核有一个调试控制寄存器,当调试器连接时,会设置某个位来禁止低功耗模式,以便调试器能随时访问内核。断开调试器后,这个位应该被清除,但如果代码里没有正确处理,可能残留。

解决办法是在进入低功耗模式前,检查并清除调试相关的控制位。具体寄存器名称因芯片而异,通常在DBGMCU模块里。另外,测试功耗时一定要断开调试器,用独立的电流表测量,不要依赖调试器供电。

6. 把Tickless用好的几个进阶思路

6.1 动态调整configEXPECTED_IDLE_TIME_BEFORE_SLEEP

这个宏在编译时确定,但你可以通过修改移植层代码,让它根据当前系统负载动态变化。比如在系统空闲时间长的时候,降低阈值,让更多短空闲窗口也能进入Tickless;在系统繁忙时,提高阈值,避免频繁切换。

实现方式是在vPortSuppressTicksAndSleep()里加一个判断:如果xExpectedIdleTime小于某个动态阈值,就直接返回,不进入睡眠。动态阈值可以根据最近一段时间的平均空闲时间来计算。

6.2 结合tickless与无节拍模式

FreeRTOS还有一个configUSE_TICKLESS_IDLE设为2的选项,叫"无节拍模式"(Tickless without a periodic tick)。在这个模式下,节拍中断完全关闭,系统时间完全依靠低功耗定时器和任务到期时间来推进。这种模式省电效果更好,但实现复杂度更高,对移植层的要求也更严格。

我目前只在少数几个对功耗要求极致的项目里用过模式2,效果确实比模式1好,但调试难度也大很多。如果你的团队没有足够的低功耗调试经验,建议先用模式1,稳定之后再考虑升级。

6.3 用RTOS感知的调试工具验证行为

Tickless模式下,系统的时序行为和默认模式不同,用传统的断点调试很难观察。建议使用RTOS感知的调试插件(比如某些IDE自带的FreeRTOS视图),可以看到任务状态、延时链表、节拍计数等运行时信息。另外,在关键路径上加一些GPIO翻转,用逻辑分析仪抓波形,是验证Tickless行为最直接的方法。

我通常会在vPortSuppressTicksAndSleep()的入口和出口各翻转一个GPIO,这样就能在逻辑分析仪上看到每次睡眠的时长和频率。结合电流探头的波形,可以直观地看到睡眠期间的电流下降和唤醒时的电流尖峰。

6.4 注意与低功耗外设的协同

Tickless只负责CPU的睡眠,外设的功耗需要单独管理。比如UART在睡眠期间如果还使能着,它的时钟和引脚缓冲器会持续耗电。正确的做法是在configPRE_SLEEP_PROCESSING里关闭不必要的外设时钟,在configPOST_SLEEP_PROCESSING里恢复。

但要注意,有些外设需要在睡眠期间保持工作,比如用于唤醒的LPTIM、RTC、外部中断控制器。这些不能关。所以需要一个"睡眠期间外设白名单",只关闭不在白名单里的外设。

另外,DMA传输在睡眠期间的行为也要考虑。如果DMA正在搬运数据,CPU睡眠可能导致DMA时钟被关,传输中断。解决办法是在进入睡眠前检查DMA状态,如果有传输在进行,就推迟睡眠或者等传输完成。

7. 一个完整的配置检查清单

最后整理一份我在项目里实际使用的检查清单,每次开Tickless之前过一遍,能避开大部分低级问题:

检查项确认内容常见错误
配置文件configUSE_TICKLESS_IDLE设为1忘记设或设成0
空闲阈值configEXPECTED_IDLE_TIME_BEFORE_SLEEP合理设成1导致频繁切换
低功耗定时器时钟源在目标睡眠模式下可用用了停摆的定时器
中断优先级唤醒中断优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级太低无法唤醒
GPIO状态未使用引脚设为模拟模式浮空引脚漏电
外设时钟睡眠前关闭不必要外设UART等持续耗电
调试器测试功耗时断开调试器调试器阻止睡眠
时间补偿实际睡眠节拍数不超过预期值断言失败
余数处理截断误差累积处理系统时间漂移
唤醒源确认所有可能的唤醒源都能正常工作睡死

这份清单不是万能的,但覆盖了我在实际项目中遇到过的绝大多数问题。每次新项目开Tickless,我都会对着它逐项检查,能省下不少调试时间。

Tickless Idle是FreeRTOS里少数几个"开了就能明显看到效果"的配置项之一,但它对移植层的要求也比其他配置高。我的建议是:先在开发板上把基本功能跑通,用示波器和电流表确认省电效果,然后再逐步加入外设管理和动态阈值这些进阶特性。不要一上来就追求极致功耗,那样很容易在调试上耗掉大量时间。低功耗优化是一个迭代的过程,先让系统稳定运行,再一点点抠电流,这样风险最低。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询