前言¶
本文档详细描述了WS53V100 的系统低功耗模式及应用开发指导,同时提供了常见问题的处理方法。
与本文档对应的产品版本如下。
本文档主要适用于以下工程师:
技术支持工程师
软件开发工程师
在本文中可能出现下列标志,它们所代表的含义如下。
概述¶
低功耗配置前提条件¶
WS53芯片包含A核和C核两个核:C核负责Wi-Fi、蓝牙和星闪的底层数据收发;A核负责网络数据协议、外设驱动和应用处理。上电默认两个核均使能了深睡模式。芯片上电C核在无Wi-Fi、蓝牙数据处理时隙时进入深睡,C核在Wi-Fi、蓝牙数据需要A核协议层处理时,C核唤醒A核。A核只有执行Idle任务,并且idle空闲时间超过配置值(默认配置20ms),才会进入深睡。在A核和C核均处于深睡时,WS53芯片整体进入深睡。A核深睡模式下,可以被UART RX、GPIO中断、RTC中断(操作系统idle到期)和看门狗唤醒。UART RX唤醒之后,软件上会让系统等待至少1s才进入深睡。
系统IDLE任务优先级最低,只有其它业务任务挂起或者阻塞时,系统才能进入IDLE任务。IDLE任务的空闲时间受其它高优先级任务阻塞时间和定时器影响,所以业务需要设计好相关任务和定时器,防止系统无法进入IDLE任务或者IDLE空闲时间过短影响功耗。在IDLE任务会对睡眠条件进行管理:

如果业务希望执行IDLE任务时不进入睡眠模式,可以关闭低功耗入口或者可以通过投否决票实现。
说明: 注册给操作系统的低功耗入口函数:static void idle_task_process(void) 低功耗管理功能函数:void uapi_pm_enter_sleep(void)
低功耗入口函数:static void idle_task_process(void)
添加睡眠否决票:errcode_t uapi_pm_add_sleep_veto(pm_veto_id_t veto_id)
移除睡眠否决票:errcode_t uapi_pm_remove_sleep_veto(pm_veto_id_t veto_id)
如果只是希望从投票时间开始一段时间不能进入睡眠,也可以调用接口:
errcode_t uapi_pm_add_sleep_veto_with_timeout(pm_veto_id_t veto_id, uint32_t timeout_ms)
系统低功耗模式说明¶
WS53V100支持3种系统低功耗模式(如表1所示),用户可根据实际应用场景选用对应的低功耗策略(默认使用深睡模式)。
表 1 低功耗模式说明
超深睡模式¶
概述¶
超深睡模式下仅保留IO唤醒相关模块供电,AGPIO配置及其复用关系不丢失,所有IO管脚驱动能力和PULL UP/DOWN配置不丢失,其他模块均下电,内存信息不保留,外设配置恢复到初始状态,Wi-Fi、星闪、蓝牙连接均断开。超深睡模式由用户调用超深睡函数接口后直接进入超深睡模式,超深睡接口调用之后,在之前所有配置为输入中断模式的AGPIO都能触发系统从超深睡模式唤醒。
接口说明¶
表 1 超深睡模式接口说明
应用示例¶
超深睡模式一般用于按键唤醒、主从设备长时间待机唤醒等极低功耗要求的场景。
超深睡配置:
/* 设置管脚APGIO3为GPIO模式 */
uapi_pin_set_mode(S_AGPIO3, PIN_MODE_0);
/* 设置GPIO为输入模式 */
uapi_gpio_set_dir(S_AGPIO3,, GPIO_DIRECTION_INPUT);
/* 设置GPIO为下降沿中断唤醒模式 */
uapi_gpio_set_isr_mode(S_AGPIO3,, GPIO_INTERRUPT_FALLING_EDGE);
/* 进入超深睡模式 */
uapi_pm_enter_udsleep();
超深睡唤醒之后,系统重启,软件可以查询获取唤醒GPIO号:
int32_t pm_port_get_udsleep_wakeup_src(const uint8_t agpio_array[], uint8_t agpio_cnt, bool wakeup[])
agpio_array为查询的GPIO标号,wakeup将对唤醒的GPIO位置标记为TRUE.
注意事项¶
超深睡之前,只要有AGPIO配置了中断模式,如果该管脚被触发,都能把系统从超深睡唤醒。
深睡模式¶
概述¶
WS53在idle空闲任务系统判断没有即将执行的业务则可以进入深睡模式,默认使用该模式。该模式可以通过深睡唤醒源唤醒,深睡唤醒源包括GPIO、系统tick(RTC)等。系统休眠时间采用tickless机制,避免每个系统tick都被唤醒。
模组作为STA,设置深睡模式后,系统空闲时会自动进入休眠,默认休眠时间取决于系统空闲状态、所关联AP的DTIM及Beacon周期、BLE和SLE连接状态等。只有系统低功耗、业务(WiFi、星闪蓝牙)低功耗均打开的时候才能进入深睡模式。
说明: DTIM (Delivery Traffic Indication Message):AP发送广播/组播数据包的频率。 BI(Beacon period):AP beacon帧发送间隔。 用户无需特别配置,BLE/SLE默认开启深睡策略;在BLE/SLE业务空闲5ms及以上时间时,投票允许进入深睡,不择投票禁止深睡。
接口说明¶
说明:
用户无需特别配置,软件默认开启深睡,通过uapi_pm_add_sleep_veto/uapi_pm_remove_sleep_veto实现否决投票和否决投票移除,采用一票否决机制,只要有一个模块禁止休眠,则系统不能进入系统低功耗模式。
进入深睡前,如果已经开启了Wi-Fi/BLE/SLE业务,需要Wi-Fi/BLE/SLE模块全部进入浅睡,整系统才会进入深睡。即只有在uapi_lpc_set_type和uapi_wifi_set_pm_switch同时打开才能进入深睡。
使能/去使能Wi-Fi协议低功耗,原接口wifi_sta_set_pm不建议使用,推荐使用新接口uapi_wifi_set_pm_switch
表 1 深睡模式接口说明
用户投票使用,否决进入休眠状态。用户可通过增加pm_veto_id_t枚举实现否决投票,每个ID仅对应一个否决票。如果有业务投票反对进入深睡,系统将无法进入深睡模式。 |
|
|
|
说明: uapi_wifi_set_pm_switch不支持在中断上下文调用。
外设下电恢复:在低功耗处理流程中,由于外设模块在深睡过程中会掉电,深睡前软件对外设进行状态和配置保存,深睡唤醒以后软件在进行恢复操作。
表 2 外设下电和恢复说明
说明: 上述外设低功耗处理流程在文件pm_sleep_porting.c中处理。
应用示例¶
示例代码
用户可以配置GPIO为输入中断模式来唤醒系统,同时也可以使用接口uapi_pm_register_dev_ops定制在睡眠唤醒前后的业务处理。
GPIO唤醒的示例代码:
static errcode_t lpc_gpio_sample_suspend(uintptr_t arg)
{
unused(arg);
g_lpc_gpio_suspend++;
return 0;
}
static errcode_t lpc_gpio_sample_reume(uintptr_t arg)
{
unused(arg);
g_lpc_gpio_resume++;
return 0;
}
static pm_dev_ops_t g_lpc_gpio_ops = {
.suspend = lpc_gpio_sample_suspend,
.resume = lpc_gpio_sample_reume,
};
static void lpc_gpio_wakeup_callback(pin_t pin, uintptr_t param)
{
unused(pin);
unused(param);
/* 用户投票反对A核休眠,保护业务代码,避免业务代码运行中,A核进入低功耗 */
uapi_pm_add_sleep_veto(PM_USER0_VETO_ID);
g_lpc_gpio_isr++;
/* 用户同意A核休眠,如果所有子业务均同意休眠,A核进入低功耗 */
uapi_pm_remove_sleep_veto(PM_USER0_VETO_ID);
printf("lpc gpio test count isr:%u, suspend:%u, resume:%u\r\n",
g_lpc_gpio_isr, g_lpc_gpio_suspend, g_lpc_gpio_resume);
}
static int lpc_gpio_task(void *data)
{
unused(data);
/* 设置GPIO模式 */
uapi_pin_set_mode(LPC_WAKEUP_GPIO, PIN_MODE_0);
/* 注册进入低功耗supend和退出低功耗resume接口,可选 */
uapi_pm_register_dev_ops(PM_DEV_USER1, &g_lpc_gpio_ops);
/* 设置为输入模式 */
uapi_gpio_set_dir(LPC_WAKEUP_GPIO, GPIO_DIRECTION_INPUT);
/* 中断下降沿唤醒,不需要处理函数可以使用uapi_gpio_set_isr_mode */
uapi_gpio_register_isr_func(LPC_WAKEUP_GPIO, GPIO_INTERRUPT_FALLING_EDGE, lpc_gpio_wakeup_callback);
return 0;
}
深睡模式:
static int deep_sleep_sample_task(void *data)
{
/* 注册深睡GPIO唤醒回调处理 */
lpc_gpio_task(data)
/* 设置深睡模式 */
uapi_lpc_set_type(PM_DEEP_SLEEP); // 默认配置深睡,可以不设置
/* 创建STA */
wifi_sta_enable();
/* 关闭Wi-Fi协议低功耗,避免连接后自动进入协议低功耗,后面需要主动打开Wi-Fi协议低功耗 */
uapi_wifi_set_pm_switch(0, 0);
/* 配置Wi-Fi连接测试热点 */
/* Wi-Fi连接热点示例代码参见SDK路径:\application\samples\wifi\sta_sample\sta_sample.c */
/* 使能Wi-Fi协议低功耗,配置睡眠时长1s(DTIM10) */
uapi_wifi_set_pm_switch(1, 1000);
return 0;
}
注意事项¶
暂无
浅睡模式¶
概述¶
实现原理与深睡模式类似,区别为CPU和外设不下电,通过业务子系统来降低功耗。实现上通过uapi_lpc_set_type设置模式PM_LIGHT_MODE进入浅睡,此时Wi-Fi/BLE/SLE子系统低仍然可以进入低功耗模式,CPU可以进入WFI状态来实现降低整体功耗。
接口说明¶
说明:
浅睡模式,uapi_lpc_set_type设置PM_LIGHT_SLEEP或者PM_NO_SLEEP,打开uapi_wifi_set_pm_switch,即支持wifi协议低功耗,CPU和外设不会掉电。但是PM_LIGHT_SLEEP模式CPU可进入WFI降功耗。
Wi-Fi打开时,uapi_lpc_set_type不设置PM_DEEP_SLEEP或者uapi_wifi_set_pm_switch参数1设置为1无法进入深睡,只能进入浅睡。
Wi-Fi打开时,uapi_wifi_set_pm_switch参数1设0,则关闭wifi协议低功耗,uapi_lpc_set_type设置为PM_DEEP_SLEEP或者PM_LIGHT_SLEEP模式,CPU和外设都不会掉电,CPU空闲可以进入WFI。
使能/去使能Wi-Fi协议低功耗,原接口wifi_sta_set_pm不建议使用,推荐使用新接口uapi_wifi_set_pm_switch。
uapi_wifi_sta_set_pm_param,仅调试使用,如无特殊需求,不建议配置。
表 1 浅睡模式接口说明
说明: uapi_wifi_set_pm_switch,uapi_wifi_sta_set_pm_param不支持在中断上下文调用。
应用示例¶
代码示例:
浅睡模式:
static int light_sleep_sample_task(void *data)
{
unused(data);
/* 设置浅睡模式 */
uapi_lpc_set_type(PM_LIGHT_SLEEP);
/* 创建STA */
wifi_sta_enable();
/* 关闭Wi-Fi协议低功耗,避免连接后自动进入协议低功耗,后面需要主动打开Wi-Fi协议低功耗 */
uapi_wifi_set_pm_switch(0, 0);
/* 配置Wi-Fi连接测试热点 */
/* Wi-Fi连接热点示例代码参见SDK路径:\application\samples\wifi\sta_sample\sta_sample.c */
/* 使能Wi-Fi协议低功耗,配置睡眠时长1s(DTIM10) */
uapi_wifi_set_pm_switch(1, 1000);
return 0;
}
关闭低功耗,仅使能Wi-Fi协议低功耗:
static int only_wifi_sleep_sample_task(void *data)
{
unused(data);
/* 设置浅睡模式 */
uapi_lpc_set_type(PM_NO_SLEEP);
/* 创建STA */
wifi_sta_enable();
/* 关闭Wi-Fi协议低功耗,避免连接后自动进入协议低功耗,后面需要主动打开Wi-Fi协议低功耗 */
uapi_wifi_set_pm_switch(0,0);
/* 配置Wi-Fi连接测试热点 */
/* Wi-Fi连接热点示例代码参见SDK路径:\application\samples\wifi\sta_sample\sta_sample.c */
/* 使能Wi-Fi协议低功耗,配置睡眠时长1s(DTIM10) */
uapi_wifi_set_pm_switch(1, 1000);
return 0;
}
常见问题¶
不能进入休眠模式,可能是什么原因¶
不能进入休眠模式原因比较多,常见以下几种原因:
定时器使用错误
举例:启动10ms周期定时器。
分析:系统在入睡前会检查是否有定时器即将到期,如果定时器即将到期,系统不允许进入系统低功耗模式。
建议:根据实际业务启动定时器,在业务空闲时关闭对应定时器,特别是周期性定时器。
任务使用错误
举例:任务体中循环操作,无主动释放动作,如调用阻塞接口接口。
分析:某一任务无主动释放动作,则其他低优先级任务得不到执行,严重时会引起看门狗复位。系统在入睡前会检查是否有任务即将被调度,如果存在任务主动释放过少,则系统不允许进入系统低功耗模式。
建议:业务设计上尽量调用阻塞接口,超时时间设置为无穷大或合理超时时间。
uapi_pm_add_sleep_veto/uapi_pm_remove_sleep_veto使用错误
举例:uapi_pm_add_sleep_veto/uapi_pm_remove_sleep_veto未成对使用。
分析:系统在入睡前会检查“否决”休眠的状态,如有某个模块否决休眠,则一票即否决进入休眠模式,如果不解除对应的否决状态,系统将永远不能进入休眠模式。
建议:严格检查是否成对使用,并保证否决休眠的状态持续时间尽量短,以保证尽快进入休眠模式。
未打开Wi-Fi子系统低功耗
举例:关闭Wi-Fi子系统低功耗后,未调用uapi_wifi_set_pm_switch接口恢复Wi-Fi子系统低功耗。
分析:打开Wi-Fi子系统低功耗是系统可进入休眠模式的前提,否则即使设置了低功耗模式系统也不会进入休眠模式。
建议:采用低功耗策略,必须打开Wi-Fi子系统低功耗。
UART外设阻止入睡
举例:系统默认AT业务串口具有睡眠投票属性。如果UART RX处于悬空或没有上拉,即RX为低电平,UART IP将误认为处于接收状态,会拒绝睡眠。如果通过串口执行AT命令唤醒设备,AT模块会使设备在1S定时器超时后才能进休眠。
时钟不稳定
举例:RC时钟不稳定,如VBAT电压在休眠后的唤醒瞬间抖动偏大,影响RC校准准确度。
影响:时钟不稳定会导致接受beacon异常,导致无法睡眠,可以直接使用示波器进行测量保活电流波形。
抓取无法入睡下的维测
在开启业务串口参与投票时,尽可能的减少log打印或采用延时打印等,避免投票函数的错误判断。
调试阶段,A核串口每50s打印一次A核深睡、浅睡核全系统深睡的统计,可以通过统计判断系统睡眠情况。
外设对应业务概率性收发报文异常¶
举例:SPI设备通信发现偶尔接收不到数据,或发送数据与预期不符。
分析:深睡后外设均掉电,会导致接收不到对端的发送数据,或者调用完异步发送接口后,数据实际并未发送出去,但系统认为没有业务即将或正在执行,从而进入休眠模式导致数据发送异常。
建议:对应业务上需要增加uapi_pm_add_sleep_veto/uapi_pm_remove_sleep_veto等接口调用,以通知系统是否可以进入休眠模式。
进入超深睡模式后立即被唤醒¶
建议:查看唤醒源对应管脚电平是不是稳定的低电平状态。
功耗数据会比预期偏高¶
建议从硬件和软件两个方面排查。
硬件:检查底电流是否符合预期。
软件:通过以下手段排查:
观察A核串口打印中,深睡和全系统深睡统计增长情况;
在WS53处于低功耗模式下,抓包查看到:STA周期性醒来,查收并获取到路由器的缓存数据时,会发送null data帧。之后STA会额外等待一定时间来保持唤醒状态。即STA每次发送null data后,间隔20ms才会再次发送null data帧进入睡眠状态,造成功耗偏高。
在STA连接上路由器之后,可通过调用uapi_wifi_sta_set_pm_param接口进行保持唤醒时间的动态配置,从而降低功耗。参数定义见service API手册。
Wi-Fi子系统低功耗与系统低功耗的关系¶
功耗角度:Wi-Fi子系统进行睡眠时关闭Wi-Fi业务侧的MAC PHY等;系统睡眠时Wi-Fi子系统也处于睡眠状态,如果设置系统为深睡模式则CPU会下电,如果设置系统为浅睡模式则会WFI CPU。
投票关系:Wi-Fi子系统睡眠时向系统进行投睡眠票,Wi-Fi子系统工作时向系统投否决票;系统睡眠前将Wi-Fi子系统的投票结果以及其他业务注册的投票结果一起判决,只有所有投票结果都赞成睡眠时系统才会入睡;否则,存在某一投票结果投否决票,系统将不睡。
如何调整Wi-Fi链路保活Null Data帧的发送周期¶
不支持修改Wi-Fi链路保活Null Data帧的发送周期
降低功耗的相关建议¶
不使用的外设可在深睡唤醒后关闭相应的时钟门控,建议不使用的外设在不使用时就关闭掉,可进一步降低功耗。
深睡时不使用的IO可配置为GPIO模式、配置为输入态、关闭IO的IE以及无上下拉电阻来降低漏电流。
建议使用默认提供的低功耗参数,以达到功耗和性能的平衡。
睡眠流程在锁中断、锁任务的状态下执行,尽可能的减少阻塞动作,减少不必要的打印等。
AT串口默认开启低功耗投票,尽量不使用printk。
如果业务注册了投票函数,在业务需要睡眠时要进行投睡眠票
Wi-Fi投票进入深睡的必要条件:使能低功耗(AT+PS=1),idle时间大于200ms,才投票睡眠。




