CC2540/CC2541进入PM3深度休眠的条件及其休眠机制的剖析
学习BLE已有一段时间,从开始时的一片空白到现在的略有领悟。下面来讲讲鄙人学习BLE中的一些领悟。
用BLE的人都知道,BLE的最大亮点是低功耗,实现低功耗的主要方式就是CC2540/CC2541的休眠机制。
休眠的模式主要分为PM2和PM3两种模式(另一种PM1模式,是用于低于3ms时间的休眠,几乎不用)。唤醒方式主要分为ST睡眠定时器唤醒和外部中断唤醒。唤醒方式和休眠模式的对应关系为:PM2模式是由ST睡眠定时器唤醒,PM3模式是有外部中断唤醒。
许多开发者都想在不用BLE的时候让其进入最低功耗模式:PM3模式,但是在debug程序的时候,发现CC2540工程里的休眠函数都是进入PM2模式的,无法让其自己进入PM3模式。于是,有许多人就想直接编程电源寄存器,让其强行进入PM3。这样的方法是可以达到进入PM3模式,但如果你没有处理好休眠前的现场保护和唤醒后的恢复工作,是会出现溢出,唤醒后程序跑飞的危险,这样反而不会降低功耗的,吃力不讨好。
其实,TI的休眠处理函数已经处理得很好了,只要你掌握了它的休眠机制,你照样可以对其调配自如。下面是我总结的一些浅见。
一、CC2540 or CC2541进入PM3深度休眠的条件
①osal_timeout = 0;
②llTimeout = 0;
只要同时满足上面两个条件,BLE就会自己进入PM3模式,此时,所有内部电路都关闭,只有外部中断和复位电路可以工作,因此,功耗最低,且可通过外部中断对其唤醒。当中的一个不为0,都将进入PM2模式。
下面肯定会有人问上面这两个条件是什么,osal_timeout就是各层的定时事件的某个事件的超时时间,llTimeout是link layer最底层,也就是RF控制器层的定时事件的超时时间。只要其中的一个不等于0,就说明有定时事件存在,需要定时来处理这些事件,因此就需要定时来唤醒芯片来执行这些事件,所以芯片就不能进入PM3(PM3只能是外部中断唤醒),只能进入PM2模式。
所以,也就是说,要想进入PM3模式,就必须清空所有的定时事件,当不存在任何的定时事件时,即osal_timeoout和llTimeout都会为0,这样就直接导致进入PM3模式。清理定时事件,就是深度休眠的前处理。如此,使得整个BLE有良好的鲁棒性。下面从代码的角度来剖析BLE的休眠机制。
二、BLE的休眠函数
下面就是休眠处理函数的源码,里面timeout就是要设置休眠定时器的时间,这个值来自于osal_timeout或者是llTimeout,那个值小,就说明那个事件更紧急,则由小的来赋给timeout设置休眠定时器,执行定时任务。当timeout = 0时,说明没有定时任务了,就可进入PM3深度休眠了。
llTimeout是通过LL_TimeToNextRfEvent( &sleepTimer, &llTimeout )来得到底层的定时事件,LL_TimeToNextRfEvent( &sleepTimer, &llTimeout )函数是link layer的不开源的代码,因此看不到里面的细节,但是可以肯定的是,llTimeout是和RF定时控制事件相关。一般蓝牙广播、连接、初始化,此llTImeout的值就不会为零,当没有广播、断开连接可以使得llTImeout为零。
osal_timeout一般为应用层的定时事件,由osal_start_timeEX(task_id, event, timeout)设定的定时,只要用相应的osal_stop_timeEX( task_id, event )终止所有的事件,就可以使得osal_timeout为零。
void halSleep( uint32 osal_timeout )
{uint32 timeout;uint32 llTimeout;uint32 sleepTimer;// max allowed sleep time in msif (osal_timeout > MAX_SLEEP_TIMEOUT){osal_timeout = MAX_SLEEP_TIMEOUT;}// get LL timeout value already converted to 32kHz ticksLL_TimeToNextRfEvent( &sleepTimer, &llTimeout );// check if no OSAL timeout// Note: If the next wake event is due to an OSAL timeout, then wakeForRF// will already be FALSE, and the call to LL_TimeToNExtRfEvent will// already have taken a snapshot of the Sleep Timer.if (osal_timeout == 0){// use common variabletimeout = llTimeout;// check if there's time before the next radio event// Note: Since the OSAL timeout is zero, then if the radio timeout is// not zero, the next wake (if one) will be due to the radio event.wakeForRF = (timeout != 0) ? TRUE : FALSE;}else // OSAL timeout is non-zero{// convet OSAL timeout to sleep time// Note: Could be early by one 32kHz timer tick due to rounding.timeout = HAL_SLEEP_MS_TO_32KHZ( osal_timeout );// so check time to radio event is non-zero, and if so, use shorter valueif ((llTimeout != 0) && (llTimeout < timeout)){// use common variabletimeout = llTimeout;// the next ST wake time is due to radiowakeForRF = TRUE;}else // OSAL timeout will be used to wake{// so take a snapshot of the sleep timer for sleep based on OSAL timeoutsleepTimer = halSleepReadTimer();// the next ST wake time is not due to radiowakeForRF = FALSE;}}// HAL_SLEEP_PM3 is entered only if the timeout is zerohalPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER;// check if sleep should be enteredif ( (timeout > PM_MIN_SLEEP_TIME) || (timeout == 0) ){halIntState_t ien0, ien1, ien2;HAL_ASSERT( HAL_INTERRUPTS_ARE_ENABLED() );HAL_DISABLE_INTERRUPTS();// check if radio allows sleep, and if so, preps system for shutdownif ( LL_PowerOffReq(halPwrMgtMode) == LL_SLEEP_REQUEST_ALLOWED ){
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))// get peripherals ready for sleepHalKeyEnterSleep();
#endif // ((defined HAL_KEY) && (HAL_KEY == TRUE))#ifdef HAL_SLEEP_DEBUG_LEDHAL_TURN_OFF_LED3();
#else// use this to turn LEDs off during sleepHalLedEnterSleep();
#endif // HAL_SLEEP_DEBUG_LED// enable sleep timer interruptif (timeout != 0){// check if the time to next wake event is greater than max sleep timeif (timeout > MAX_SLEEP_TIME ){// it is, so limit to max allowed sleep time (~510s)halSleepSetTimer( sleepTimer, MAX_SLEEP_TIME );}else // not more than allowed sleep time{// so set sleep time to actual amounthalSleepSetTimer( sleepTimer, timeout );}}// prep CC254x power modeHAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode);// save interrupt enable registers and disable all interruptsHAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2);HAL_ENABLE_INTERRUPTS();// set CC254x power mode; interrupts are disabled after this function// Note: Any ISR that could wake the device from sleep needs to use// CLEAR_SLEEP_MODE(), which will clear the halSleepPconValue flag// used to enter sleep mode, thereby preventing the device from// missing this interrupt.HAL_SLEEP_SET_POWER_MODE();// check if ST interrupt pending, and if not, clear wakeForRF flag// Note: This is needed in case we are not woken by the sleep timer but// by for example a key press. In this case, the flag has to be// cleared as we are not just before a radio event.// Note: There is the possiblity that we may wake from an interrupt just// before the sleep timer would have woken us just before a radio// event, in which case power will be wasted as we will probably// enter this routine one or more times before the radio event.// However, this is presumably unusual, and isn't expected to have// much impact on average power consumption.if ( (wakeForRF == TRUE) && !(IRCON & 0x80) ){wakeForRF = FALSE;}// restore interrupt enable registersHAL_SLEEP_IE_RESTORE(ien0, ien1, ien2);// power on the LL; blocks until completion// Note: This is done here to ensure the 32MHz XOSC has stablized, in// case it is needed (e.g. the ADC is used by the joystick).LL_PowerOnReq( (halPwrMgtMode == CC2540_PM3), wakeForRF );#ifdef HAL_SLEEP_DEBUG_LEDHAL_TURN_ON_LED3();
#else //!HAL_SLEEP_DEBUG_LED// use this to turn LEDs back on after sleepHalLedExitSleep();
#endif // HAL_SLEEP_DEBUG_LED#if ((defined HAL_KEY) && (HAL_KEY == TRUE))// handle peripherals(void)HalKeyExitSleep();
#endif // ((defined HAL_KEY) && (HAL_KEY == TRUE))}HAL_ENABLE_INTERRUPTS();}
从上面的代码认真分析,就可以掌握BLE的休眠机制。BLE的所有事件都是间断的,而每个事件间的间歇就是定时休眠的时候。例如,广播可以是每个100ms广播一次,而这100ms就进入了PM2休眠的时间;连接的时候,传输数据是10ms或者100ms连接一次传输,数据的传输也是间断的,这个间歇也是PM2的定时休眠时间。BLE正是因为这种休眠机制而做到了很低的功耗,与传统蓝牙的连续传输相比,功耗降低了许多。
以上粗略地总结了TI源码下PM3深度休眠的条件和简单讲述了BLE的休眠机制,本人菜鸟,此文可能存在错误的理解,斗胆发此文,权当和大家交流学习经验,望吐槽。。。
CC2540/CC2541进入PM3深度休眠的条件及其休眠机制的剖析相关推荐
- CC2540/CC2541/CC254x之OSAL操作系统抽象层
测试环境 协议栈版本:BLE-CC254x-1.4.0 开发环境IAR版本:IAR 8.20 硬件设备:CC2540/CC2541开发板 示例测试Demo工程:simpleBLEPeripheral工 ...
- CC2540/CC2541的基本操作
CC2540/CC2541的基本操作 1)操作LED //初始化 P0SEL &= ~0x01;//设置为普通IO口 P0DIR |= 0x01;//设置成输出模式 //LED控制 P0_0 ...
- 蓝牙4.0BLE 手机控制 cc2540 CC2541 的串口透传功能已实现
蓝牙4.0BLE 手机控制 cc2540 CC2541 的串口透传功能已实现 虽然蓝牙4.0 BLE芯片CC2540 是单芯片(即用户可以对它进行芯片级代码编写), 是8051增强型主控, 带蓝牙4. ...
- cc2540 cc2541 开发板资料更新日志
经过多次PCB打样和全面调试.已经完毕了cc2540 cc2541的开发板的批量贴片.硬件告一段落, 接下来是全面完好软件方面的工作.眼下已经针对没有开发经验的用户编写完毕0基础基础实验代码和教程.接 ...
- 图文深度解析Linux内存碎片整理实现机制以及源码
图文深度解析Linux内存碎片整理实现机制以及源码. 物理内存是以页为单位进行管理的,每个内存页大小默认是4K(大页除外).申请物理内存时,一般都是按顺序分配的,但释放内存的行为是随机的.随着系统运行 ...
- 易基因|深度综述:表观遗传机制在慢性疼痛中的作用(DNA甲基化+组蛋白修饰+非编码RNA)
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因. 2022年8月22日,德国海德堡大学Daniela Mauceri在<Cells>杂志发表了"Role of Ep ...
- 深度学习框架的内存优化机制
深度学习框架的内存优化机制 https://www.cnblogs.com/DicksonJYL/p/9576896.html 这篇博文简单介绍下深度学习框架的内存优化方式,主要参考资料1,也就是MX ...
- 计算机休眠是意思,电脑休眠是什么意思(电脑休眠和睡眠的区别)
电脑如果长时间不操作的话,就会进入休眠或者睡眠状态,睡眠的话通常晃动鼠标或者键盘就可以唤醒了,而休眠尝尝需要点按一下开机键,那么休眠和睡眠有什么区别呢? windows系统中,有这样几种电源模式,关机 ...
- 【李宏毅机器学习2021】Task04 深度学习介绍和反向传播机制
[李宏毅机器学习2021]本系列是针对datawhale<李宏毅机器学习-2022 10月>的学习笔记.本次是对深度学习介绍和反向传播机制的学习总结.本节针对上节课内容,对batch.梯度 ...
最新文章
- 【翻译】SQL Server索引进阶:第七级,过滤的索引
- jquery一个控件绑定多个事件
- CF176E Archaeology(set用法提示)
- android键盘移动光标,在Android键盘上完成键
- MyBatis复习(十):注解开发
- 对996最客观的描述,一叶知秋
- html登录页面的校验控件,HTML5一款有趣智能的密码输入界面控件
- c语言中反余切三角函数,三角函数(反双曲)正弦,余弦,正切,余切,正割,余割在线计算器_三贝计算网_23bei.com...
- PADS(4)——PADS Logic原理图设计技巧
- 新闻APP受到各界关注 趣头条 大众看点 等新闻
- 360修复服务器漏洞,360安全漏洞不需要修复怎么设置
- 服务交付服务规范十要素
- c语言 函数参数传递 值传递,c语言中函数参数的三种传递方式——值传递、指针传递、引用传递...
- xx公司网站建设方案
- 经典俄罗斯方块游戏使用手册
- 流感传染(C程序设计进阶第2周)
- 公园智慧路灯:上海曹杨公园智慧灯杆项目案例分享
- NEU健康上报脚本解析教程
- word论文排版插件_用这个Word插件,瞬间完成一键排版
- 男性找女朋友最低会要求什么学历?
热门文章
- TX2手动安装cudnn
- 帮我用python做三国杀
- c# mysql executescalar为什么返回值是空_当没有结果返回时处理ExecuteScalar()
- 3D竖版射击游戏Icarus-X
- MySQL 复制(四:复制原理)
- ROOT学习——跟随鼠标位置动态显示TH2切片(DynamicSlice.C)
- 2022年全球市场光学透明胶片总体规模、主要生产商、主要地区、产品和应用细分研究报告
- Mask_Rcnn_tf2在2080显卡上训练遇见的问题
- 强推!《PyTorch中文手册》来了
- C++ 一些http操作函数