参考转自 https://www.sekorm.com/news/9339.htmlhtml
EFR32MG自己具备五种低功耗工做模式:网络
EM0:Active状态,此时CPU活动、外设活动,功耗最高,最低65uA/MHz。函数
EM1:IDLE状态,此时,CPU中止,外设活动,功耗和所使用的外设有关,通常能够认为此时3mA~5mA左右的功耗。ui
EM2:Deepsleep状态,此时,部分LFXO或LFRCO、ULFRCO低速时钟的外设活动,RAM保存,标称此时电流为1.5uA。加密
EM3:Stop状态,此时高速时钟HFXO或HFRCO、LFRCO、LFXO均会被关掉,ULFRCO活动,采用ULFRCO的外设仍然能够运行,可选的RAM保存,如RTCC/WDOG/CROTIMER。调试
EM4H:冬眠状态,从该状态开始,RAM的保存将受到限制,最多经过RTCC外设的RAM区保存128字节的RAM数据。所以,该状态唤醒将会将系统复位。在该状态下,可使用Cryotimer和指定的GPIO唤醒。orm
EM4S:关闭状态,在该状态下,全部外设基本都关掉,RAM所有丢失,能够经过基于ULFRCO的Cryotimer或指定的GPIO唤醒,唤醒后系统复位。htm
在EmberZNet协议栈中,使用到了EM0 、EM一、EM2和EM4H模式,主要的休眠工做在idle-sleep-soc.c line21的void emberAfPluginIdleSleepTickCallback(void)函数中处理。接口
流程以下:事件
1.要关闭全局中断,保证睡眠的处理不被中断打断和篡改。
2.是否能够进入休眠,判断条件是
1)开发者是否指定保持唤醒状态不休眠。
2)开发者是否指定未加入网络时不休眠。
3)是否有串口正在发送数据,此时不能休眠。
4)是够有任务等待执行,若是有则不能休眠,要处理就绪的任务,包括用户任务和协议栈任务。
若是这些均所有经过,那至少能够进入IDLE状态了。
3.若是断定能够休眠,对于Sleepy End Device来讲,因为RADIO在休眠时是不能够打开的,所以,还须要进行进一步判断是否能够关闭Radio,进入休憩模式,判断依据是查询是否有高优先级的协议栈任务须要运行,目前定义是4个任务具备高优先级:
1)RADIO数据发送任务。
2)RADIO数据接收任务。
3)RADIO外设正在使用。
4)RF4CE网络忙。(一种Zigbee遥控标准协议)
若是有以上任务正在执行,则系统仍是不能休眠。
4.若是没有stack高优先级任务在执行,系统就能够安心休眠,首先,须要计算休眠的时间,休眠时间指从如今开始到执行下一个事件发生的时间,以[1/1024]秒为单位,若是计算出来能够休眠的时间小于5ms(系统默认,可修改),那也不能够进入Deepsleep状态,由于进入Deepsleep须要关外设、关协议栈,唤醒后须要开外设、开协议栈,这些动做完成也须要几毫秒的时间,功耗核算下来进入Deepsleep没有任何意义。这种状况下系统会默认进入个EM1 IDLE状态就能够了。若是休眠时间大于5ms,那系统就着手进入deepsleep。再次唤醒时,会给出已经睡眠了多久,用以作调试使用。
注意一点是,不管系统进入IDLE或Deepsleep状态,都会在睡眠以前把中断所有再从新打开,用做唤醒源,但操做是封装在睡眠函数中未开源,咱们不要再去手动添加。
接下来,若是咱们想要使用EM4--系统最低功耗的模式,那咱们须要再进行一点复杂的处理。
首先,EM4唤醒就会复位,所以,在进入EM4以前,要保存Parent Info,也就是父节点的IEEE地址和NodeID,这个不要咱们去作,系统会自动添加,在断定是否进入EM4时,默认会进行bool emberParentTokenSet(void)判断是否该操做已经完成,若是未完成则不能进入EM4。同时,须要用户在bool emberAfOKToGoToEM4Callback()函数中返回true,系统才能够确认进入EM4,在进入EM4以前,系统会使用RTCC保存16字节的与当前网络通讯加密有关的数据,包括发送数据的FrameCounter、接收数据的FrameCounter、发送数据的LinkKeyFrameCounter、接收数据的LinkKeyFrameCounter,再次唤醒时会自动读取。从EM4唤醒后,系统会获取复位缘由,若是是EM4形成的,则会进入void emberAfCameBackFromEM4Callback()函数中,进行EM4的参数回读工做。
可是,使用EM4仍是须要作不少工做,由于若是直接使用EM4,会形成周期性的任务事件没有办法执行,每次进入EM4会丢失以前的任务信息,好比Sleepy End Device的Short poll、Long Poll事件没法正常执行。建议是在进入EM4以前就先作好此类工做,bool emberAfOKToGoToEM4Callback()是很是适合的接口。
EM4目前进入机制中协议栈有些地方须要修改,除在ISC文件中选择EM4 plugin外。须要增长EMBER_AF_PLUGIN_EM四、EMBER_ENABLE_EM4定义,重复的定义问题能够去掉$Prj_name.h中的相同定义。在micro.c文件line380 void setEm4WakeupTimer(uint32_t duration)中的 cryotimerInit.period = closestPowerOfTwo(duration);计算周期不正确,请参考手册配置。另外,在child.h文件line 334
#define emberOkToGoToLowPowerMode() (!emberCurrentStackTasks() && emberParentTokenSet())
修改成
#define emberOkToGoToLowPowerMode() (!emberCurrentStackTasks() && !emberParentTokenSet())