HS6621 A/C/P系列功耗管理

CYF · 1062次点击 · 2023-05-25

1 概述

co_power_sleep_enable函数控制整个睡眠系统是否使能,参数设为true表示使能,否则表示禁止。

睡眠模式的设置主要涉及这些函数:pmu_32k_enable_in_deep_sleepco_power_ultra_sleep_mode_enableco_power_hib_sleep_mode_enable

睡眠模式分为四种:浅睡、深睡、超深睡、冬眠。它们的唤醒源不同,唤醒后代码的运行位置也不同,对比如下:

模式

唤醒源

代码运行位置

浅睡

所有GPIORTCTimer,射频

从唤醒处运行

深睡

所有GPIORTC

从唤醒处运行

超深睡

所有GPIORTC

main函数开始运行

冬眠

GPIO 0-12PMU Timer

main函数开始运行

 co_power.h文件中,可以看到只有两种睡眠状态:POWER_SLEEPPOWER_DEEP_SLEEP。前面说的浅睡就是POWER_SLEEP,深睡、超深睡、冬眠都是POWER_DEEP_SLEEP的一种。

typedef enum

{

      /// All modules are alive, and CPU   run with full speed

      POWER_ACTIVE,

      /// All modules are alive, but CPU   clock is gating

      POWER_IDLE,

      /// Power down most of module(CPU,   Peripheral, etc),

      /// but 32K is alive, only gpio and   sleep-timer can wake up chip

      POWER_SLEEP,

      /// Power down most of module(CPU,   Peripheral, etc),

      /// 32K is not alive, only gpio can   wake up chip

      POWER_DEEP_SLEEP,

      /// Power down all module,

      /// only the power pin can wake up   chip

      POWER_SHUTDOWN,

} co_power_status_t;

如果在POWER_SLEEP_ENTRY睡眠事件中加一些日志,如图所示,发现只有浅睡的时候打印“#”,其它睡眠模式都打印“&”。    

注意:

         此处加日志输出,是为了让睡眠模式的描述更直观,平时调试也可以作为参考,但正常的应用程序中不要加。

2 睡眠模式

         前面说到系统有4中睡眠模式,任何一种睡眠模式,进入休眠后CPU、外设都会被关闭,所有外设的中断都无法响应。要使用外设,首先得唤醒系统,然后阻止系统休眠(pmu_lowpower_prevent(PMU_LP_USER);)。比如系统处于休眠,此时想通过UART接收数据,那必须先唤醒,再阻止休眠,然后才能正常接收数据。在需要休眠的时候调用pmu_lowpower_allow(PMU_LP_USER);

此章节对这些睡眠模式进行详细描述,所有测试使用的硬件是HS6621CF-C EVB开发板,软件是SVN2969,测试的例程是ble_app_simple_server

2.1 浅睡模式

         使能了睡眠系统,任何情况下,只要开启了定时器,或者开启了射频(广播、扫描),系统就处于浅睡模式。在定时器超时期间,广播、扫描的间隔期间,都会进入浅睡。浅睡时的平均电流是5uA,常称为“底电流”。

         2秒周期性软件定时器为例,每次定时器超时都会唤醒系统,执行完回调后立即进入浅睡,如图2.1-1日志所示每隔2秒会打印一次“#”。

02.png

2.1-1 仅开启定时器的日志

03.png

2.1-2 仅开启定时器的电流波形

1秒间隔的广播为例,每次广播后进入浅睡,下一秒射频唤醒系统又发一次广播,如图2.1-3日志所示每隔1秒会打印一次“#”。

04.png

2.1-3 仅开启广播的日志

05.png

2.1-4 仅开启广播的电流波形

2.2 深睡模式

深睡模式是常用的模式,因为此时可以快速唤醒系统,功耗也比较低。

软件上应按下面代码配置。

static void ble_stack_config(void)

{

      // Disable WDT

      wdt_enable(0);

      // Enable DCDC

      pmu_dcdc_enable(true);

      // Power down xtal32k in deep sleep   mode

      pmu_32k_enable_in_deep_sleep(false);

      // Select 32k clock for stack

      //pmu_xtal32k_change_param(15, 1);

      pmu_select_32k(PMU_32K_SEL_RC);

      // xtal32m param

      pmu_xtal32m_change_param(15);

      // ultra sleep mode enable

      co_power_ultra_sleep_mode_enable(false);

      // Enable sleep, SWD will be   closed.

      co_power_sleep_enable(true);

}

 

int main(void)

{

      ble_stack_config();

      hardware_init();

      rwip_init(RESET_NO_ERROR);

      co_power_register_sleep_event(power_sleep_event_handler);

      log_debug("running %d\n", pmu_reboot_reason());

      // dbg_mmi_enable();

      appm_init();

      // co_timer_set(&simple_timer,   100, TIMER_REPEAT, simple_timer_handler, NULL);

      while(1)

      {

          rwip_schedule();

      }

}

上电后,系统会进入深睡模式,按下按键会唤醒系统,唤醒后直接运行唤醒回调里的代码,松开按键时触发GPIO中断然后又进入深睡,如图2.2-1日志所示。

06.png

2.2-1 深睡模式运行日志

如果深睡时禁用32K时钟(pmu_32k_enable_in_deep_sleep(false);),此时平均电流是3uA,如图2.2-2所示。

07.png

2.2-2 禁用32K的深睡电流波形

         如果深睡时使能32K时钟(pmu_32k_enable_in_deep_sleep(true);),此时平均电流是4.7uA,如图2.2-3所示。

08.png

2.2-3 使能32K的深睡电流波形

2.3 超深睡模式

         co_power_ultra_sleep_mode_enable函数控制超深睡是否使能。超深睡模式下,可以设置任意GPIO唤醒,也可以设置RTC唤醒。

static void ble_stack_config(void)

{

      // Disable WDT

      wdt_enable(0);

      // Enable DCDC

      pmu_dcdc_enable(true);

      // Power down xtal32k in deep sleep   mode

      pmu_32k_enable_in_deep_sleep(false);

      // Select 32k clock for stack

      //pmu_xtal32k_change_param(15, 1);

      pmu_select_32k(PMU_32K_SEL_RC);

      // xtal32m param

      pmu_xtal32m_change_param(15);

      // ultra sleep mode enable

      co_power_ultra_sleep_mode_enable(true);

      // Enable sleep, SWD will be   closed.

      co_power_sleep_enable(true);

}

 

int main(void)

{

      ble_stack_config();

      hardware_init();

      rwip_init(RESET_NO_ERROR);

      co_power_register_sleep_event(power_sleep_event_handler);

      log_debug("running %d\n", pmu_reboot_reason());

      // dbg_mmi_enable();

      appm_init();

      // co_timer_set(&simple_timer,   100, TIMER_REPEAT, simple_timer_handler, NULL);

      while(1)

      {

          rwip_schedule();

      }

}

上电后,系统进入休眠,此时是超深睡。按键按下后唤醒系统,代码从main函数开始运行,从日志看复位原因是1,即PMU_REBOOT_FROM_ULTRA_DEEP_SLEEP,如图2.3-1所示。

09.png

2.3-1 超深睡模式运行日志

超深睡模式平均电流是1.6uA,如图2.3-2所示。

10.png

2.3-2 超深睡电流波形

2.4 冬眠模式

co_power_hib_sleep_mode_enable函数控制冬眠模式是否使能。冬眠模式下,可以设置GPIO 0 – 12来唤醒,也可以设置定时唤醒。

冬眠模式是基于超深睡模式实现的,所以必须使能超深睡模式。

static void ble_stack_config(void)

{

      // Disable WDT

      wdt_enable(0);

      // Enable DCDC

      pmu_dcdc_enable(true);

      // Power down xtal32k in deep sleep   mode

      pmu_32k_enable_in_deep_sleep(false);

      // Select 32k clock for stack

      //pmu_xtal32k_change_param(15, 1);

      pmu_select_32k(PMU_32K_SEL_RC);

      // xtal32m param

      pmu_xtal32m_change_param(15);

      // ultra sleep mode enable

      co_power_ultra_sleep_mode_enable(true);

      // hibernation sleep mode enable

      co_power_hib_sleep_mode_enable(true);

      REGW(&HS_PMU->ANA_PD, MASK_1REG(PMU_ANA_PD_CKOPMU32K, 1));

      // Enable sleep, SWD will be   closed.

      co_power_sleep_enable(true);

}

 

int main(void)

{

      ble_stack_config();

      hardware_init();

      rwip_init(RESET_NO_ERROR);

      co_power_register_sleep_event(power_sleep_event_handler);

      log_debug("running %d\n", pmu_reboot_reason());

      // dbg_mmi_enable();

      appm_init();

      // co_timer_set(&simple_timer,   100, TIMER_REPEAT, simple_timer_handler, NULL);

      while(1)

      {

          rwip_schedule();

      }

}

冬眠模式平均电流是0.5 ~ 0.6uA,如图2.4-1所示。

11.png

2.4-1 冬眠模式电流波形

冬眠模式下可以设置定时唤醒,设置函数是hib_timer_start,设置的时间单位是1/32768 S,例如参数设置为327680,就是设置定时唤醒时间为10秒。上电后设置一次即可,此时底电流是1.5uA,如图2.4-2所示。

12.png

2.4-2 冬眠模式定时唤醒电流波形

上电后,系统进入休眠,此时是冬眠。PMU timer超时唤醒系统,系统从main函数开始运行,从日志看复位原因也是1,即PMU_REBOOT_FROM_ULTRA_DEEP_SLEEP,如图2.4-3所示。

13.png

2.4-3 冬眠模式定时唤醒日志

3 功耗调试

         产品的功耗调试不是简单的按上面说的模式设置完就结束了。即使打印发现系统已经进入POWER_DEEP_SLEEP,但是产品硬件还是可能漏电。此时,可以开启一个定时器,周期的dump一下系统信息。

static   void simple_timer_handler(co_timer_t *timer, void *param)

{

// sysdump();

    pmu_dump(printf);

    co_timer_dump(printf);

}

 

co_timer_set(&simple_timer,   2000, TIMER_REPEAT, simple_timer_handler, NULL);

         例如,ble_app_simple_server例程,设置GPIO2GPIO30低电平唤醒,dump的信息如图3-1所示,

14.png

3-1 pmu_dump信息

l  prevent_status

         prevent_status每个bit表示一种阻止休眠的原因,具体查看pmu.h文件中的pmu_lowpower_peripheral_t类型定义。

         如果发现此值不为0,表示系统没有进入休眠,找到对应的bit即可找到原因。

l  wakeup_pin

         wakeup_pin是当前所有可唤醒系统的GPIOpin mask值,为1bit是可唤醒的GPIO

sleep_level表示当前唤醒IO的状态,此状态应该和唤醒电平相反。如果设置了低电平唤醒,那sleep_level中唤醒IO对应的bit应该为1,否则为0

         cur_level必须和sleep_level相同,否则系统一致处于唤醒状态。

l  pull_uppull_down

         pull_up是当前所有上拉GPIOpin mask值,后面括号内cur_level值必须和pull_up值相同,表示当前所有上拉的GPIO状态都是高电平。但凡其中有一个GPIO是低电平,系统就会有漏电。

         pull_down是当前所有下拉GPIOpin mask值,后面括号内cur_level值必须为全0,表示当前所有下拉的GPIO状态是低电平。但凡其中有一个GPIO是高电平,系统就会漏电。

l  clocking

         关注CPU时钟频率即可,如果想降低功耗,可以在休眠时把CPU时钟频率降低。

4 总结

         无论是否使能冬眠模式、或是超深睡模式,系统上电后都可以开启定时器、射频、RTC,开启后系统就处于浅睡模式。

         当所有定时器停止工作,射频也停了,RTC也关闭了,系统就会进入当前设定允许的功耗最低的睡眠模式。


OM6621_A_C_P 功耗管理v1202305259042.pdf
被收藏 1  ∙  1 赞  
加入收藏
点赞
7 回复  
善言善语 (您需要 登录 后才能回复 没有账号 ?)

请先登录网站