IC:

电源管理架构

SoC 搭载了先进的电源管理控制器(Power Management Controller,PMC),可灵活控制芯片不同电源域的上电时序,实现性能与功耗的最佳平衡。

SoC 的数字系统中一般包含三个核心电源域:AON 域、SYSON 域和 SOC 域。不同省电模式下,各电源域的关断策略存在差异。

Ameba 系列 SoC 的电源域和唤醒源如下所示:

../../rst_rtos/1_nda_power_save/figures/power_domains_and_wakeup_sources_dplus.svg

低功耗模式

Ameba SoC 支持两种低功耗模式:

  • 睡眠(Sleep)模式

    • 时钟门控模式(Clock Gating,CG):关闭 SOC 域的时钟,保留其供电

    • 电源门控模式(Power Gating,PG):关闭 SOC 域的电源

  • 深度睡眠(Deep-Sleep)模式:关闭 SYSON 域和 SOC 域的供电。深度睡眠模式比睡眠模式关闭更多电源域,因此功耗更低。

Tickless 是 FreeRTOS 的低功耗功能,当系统空闲时会暂停 CPU(不关闭时钟和电源)。睡眠模式流程和深度睡眠模式流程均基于 Tickless 实现。

下表详细解释了各个模式的电源域工作状态及特点:

模式

AON 域

SYSON 域

SOC 域

描述

Tickless

ON

ON

ON

  • FreeRTOS 低功耗功能

  • CPU 周期性进入 WFI 指令休眠,发生中断时唤醒

  • 射频状态可配置为关闭/周期性开启/持续开启(具体由应用场景决定)

Sleep

ON

ON

  • CG:ON

  • PG:OFF

  • 芯片级省电模式,包含时钟门控与电源门控两种子模式

  • 退出睡眠模式时可恢复 CPU 堆栈状态

  • 系统 RAM 保持供电,数据不会丢失

Deep-Sleep

ON

OFF

OFF

  • 芯片级深度省电模式

  • 退出深度睡眠模式时无法恢复 CPU 堆栈状态,需执行完整重启流程

  • 系统 RAM 供电被切断,数据不保留

  • 备份(retention)SRAM 保持供电

FreeRTOS Tickless

FreeRTOS 的 Tickless 低功耗特性通过优先级最低的空闲任务实现,当系统没有其他运行任务时触发。

备注

  • 低功耗应用必须启用 configUSE_TICKLESS_IDLE 配置项,因为睡眠模式基于 Tickless 机制实现。

  • 与原生 FreeRTOS 不同,不依赖 xExpectedIdleTime 进行唤醒。

../../rst_rtos/1_nda_power_save/figures/freertos_tickless_in_an_idle_task.svg

空闲任务中的 FreeRTOS Tickless

上图展示了空闲任务的代码流程。在空闲任务中,系统会检查睡眠条件(包括唤醒锁状态、系统活跃时间等,详见章节 唤醒锁 APIpmu_set_sysactive_time),以决定是否进入睡眠模式。

  • 当条件不满足时:CPU 执行 ARM WFI (等待中断)指令,使处理器挂起直至中断触发。通常由 SysTick 中断恢复运行,此模式称为 软件 Tickless

  • 当条件满足时:执行函数 freertos_pre_sleep_processing() 进入睡眠模式或深度睡眠模式

备注

  • 即使设置了 FreeRTOS 时间控制机制(如软件定时器或 vTaskDelay),只要空闲任务被执行且满足条件,系统仍会进入睡眠模式。

Wi-Fi 低功耗

IEEE 802.11 省电管理允许 STA 自主进入睡眠状态,其核心规则为:

  • STA 必须在特定时间戳保持唤醒状态,其余时间可进入睡眠状态

  • WLAN 驱动通过获取唤醒锁(Wakelock)阻止系统在需保持活跃时进入睡眠模式

  • 当允许休眠时,WLAN 驱动释放唤醒锁

站点休眠期间无法接收任何数据帧,因此 AP 需缓存待传数据帧,STA 需周期性唤醒检测信标帧。

../../rst_rtos/1_nda_power_save/figures/timeline_of_power_saving.png

省电模式时序图

SDK 中的实现模式如下:

IEEE 802.11 power management is called LPS, and if NP enters sleep mode when Wi-Fi is in LPS mode, we call it WoWLAN mode.

In WoWLAN mode, a timer with a period of about 102ms will be set in the suspend function. And LP will wake up every 102ms to receive the beacon to maintain the connection.

Except for LPS and WoWLAN, we also have IPS, which can be used when Wi-Fi is not connected. The following tables list all three power-saving modes for Wi-Fi and the relationship between the system power mode and Wi-Fi power mode.

模式

Wi-Fi 状态

描述

SDK

IPS

未连线:

  • RF/BB/MAC 全关闭

Wi-Fi 驱动自动关闭 Wi-Fi 模块

禁止IPS后,系统平均功耗会大幅增加,不建议禁用

LPS

已连线:

  • RF 周期性开关

  • MAC/BB 保持常开

LPS 模式用于实现 IEEE 802.11 省电管理

基于信标的 TSF 和 TIM IE 控制射频的开关

默认启用 LPS 模式,可通过 API

wifi_set_lps_enable() 禁用

WoWLAN

已连线:

  • RF/BB 周期性开关

  • MAC 周期性进入/退出 CG/PG

每次信标提前中断时WIFI 会被打开,以接收来自AP router的信标帧

当接收到唤醒数据包时,会唤醒系统并将数据交由网络层处理。

默认启用 WoWLAN 模式

系统功耗模式和 Wi-Fi 功耗模式之间的关系如下表所示:

系统功耗模式

Wi-Fi 功耗模式

描述

Active

IPS

Wi-Fi 已开启但未建立连接

LPS

Wi-Fi 已连接并进入 IEEE 802.11 省电管理模式

Sleep

Wi-Fi 关闭/IPS

WoWLAN

Wi-Fi 保持关联状态

Deep-Sleep

Wi-Fi 关闭

需保持 Wi-Fi 持续在线或关联的场景,不推荐使用 Deep-Sleep 模式

唤醒源

在不同低功耗模式下,可用于唤醒系统的唤醒源如下表所示:

唤醒源

Sleep CG

Sleep PG

Deep-Sleep

限制

WLAN

X

BT

X

IPC

X

仅 KM0 可通过 IPC 唤醒 KM4

Basic Timer4~7

X

PMC Timer

X

仅内部使用

UART0~2

X

当使用 UART 作为唤醒源时:

  • Rx 的时钟源只能是 OSC2M,且在睡眠期间禁止关闭 OSC4M

  • 当波特率大于 115200bps 时,不建议使用 UART 作为唤醒源

  • 当唤醒指令超过 64 字节 FIFO 深度时,超出的部分会丢失

LOGUART

X

当使用 LOGUART 作为唤醒源时:

  • 如果 Rx 的时钟源是 XTAL40M,在睡眠期间禁止关闭 XTAL 或 OSC4M

  • 如果 Rx 的时钟源是 OSC2M,在睡眠期间禁止关闭 OSC4M

  • 当唤醒指令超过 16 字节 FIFO 深度时,超出的部分会丢失

GPIO

X

I2C

X

CAP_TOUCH

X

ADC

X

SDIO

X

Key-Scan

X

BOR

PWR_DOWN

AON_TIMER

AON_WAKEPIN

RTC

进入 Sleep 模式

睡眠模式基于 FreeRTOS Tickless 模式实现,因此推荐通过释放唤醒锁(Wakelock) 的方式进入睡眠模式。

  1. 初始化目标外设

  2. 启用和注册外设中断

  3. 设置 ambea_sleepcfg.c 文件中的 sleep_wevent_config[],确保中断注册在 sleep_wevent_config[] 选择的相同的 CPU 上

  4. 对于需要特殊时钟配置的外设,在 ameba_sleepcfg.c 文件中设置 ps_config[]

  5. 根据需要注册睡眠/唤醒回调函数

  6. 通过释放 AP 的唤醒锁进入睡眠模式(启动时 PMU_OS 默认被占用,需在进入睡眠模式前释放)

  7. 在系统唤醒后,及时清除外设中断

进入 Deep-Sleep 模式

通过 FreeRTOS Tickless 流程同样可以进入深度睡眠模式。

当系统启动时,应用处理器(AP)自动持有深度唤醒锁 PMU_OS,导致 freertos_ready_to_dsleep() 校验失败,系统默认不在空闲任务中进入深度睡眠模式。

只有当 freertos_ready_to_sleep() 校验通过,才会校验 freertos_ready_to_dsleep(),因此需同时释放唤醒锁和深度唤醒锁方可进入深度睡眠模式。

配置:

  1. 初始化目标外设并启用中断

  2. ameba_sleepcfg.c 文件中设置 sleep_wakepin_config[],使用 AON 唤醒引脚作为唤醒源

  3. 通过释放 AP 的唤醒锁和深度唤醒锁进入深度睡眠模式

低功耗配置

请参考 开发者配置 章节以获取详细信息.

低功耗相关 API

唤醒锁 API

唤醒锁(Wakelock)是一个 32 位的映射,如果某个模块持有唤醒锁,系统将无法进入睡眠模式。每个模块在唤醒锁位图中都有其对应的位(参见枚举 PMU_DEVICE),用户也可以在枚举中添加自定义的唤醒锁,但不得修改已经定义好的唤醒锁。

Ameba Soc 定义了两种唤醒锁,每种唤醒锁都可以支持 32 个不同的模块:

  • wakelock:用于睡眠模式,当 wakelock 为 0 时,系统可进入睡眠模式;否则,不允许进入睡眠模式。

  • deepwakelock:用于深睡眠模式,当 deepwakelock 为 0 时,系统可进入深睡眠模式;否则,不允许进入深睡眠模式。

以下内容展示了系统定义的唤醒锁位图:

enum PMU_DEVICE {
  PMU_OS        = 0,
  PMU_WLAN_DEVICE,
  PMU_KM4_RUN,
  PMU_WLAN_FW_DEVICE,
  PMU_BT_DEVICE,
  PMU_DEV_USER_BASE,  /*编号 7~31 预留给客户使用*/
  PMU_MAX
};
  1. 睡眠模式:通过函数 freertos_ready_to_sleep() 判断 wakelock 是否为 0。

  1. wakelock:当系统启动时,应用核(AP)持有 wakelock PMU_OS,而网络核(NP)则持有 wakelock PMU_OS 以及 PMU_KM4_RUN

  2. 睡眠条件:只有当所有 wakelock 都被释放后,AP 或 NP 才允许进入休眠模式。

  3. 睡眠流程:当 AP 的 wakelock PMU_OS 被释放后,AP 会在空闲任务中进入休眠模式,并向 NP 发送 IPC。NP 会对 AP 进行断电(power-gate)或时钟门控(clock-gate),然后释放 PMU_OS 以及 PMU_KM4_RUN

  1. 深睡眠模式:通过函数 freertos_ready_to_dsleep() 判断 deepwakelock 是否为 0。

  1. deepwakelock: 当系统启动时,应用核持有 deepwakelock PMU_OS

  2. 睡眠条件:当 AP 的所有 deepwakelock 被释放后,AP 和 NP 才允许进入 deep-sleep 模式。

  3. 睡眠流程:当 AP 的所有 deepwakelock 被释放后,并在空闲任务中向 NP 发送 IPC。NP 会发送 deep-sleep 请求,最终让芯片进入 deep-sleep 模式。

当系统唤醒后,除非重新获取 wakelock,否则会很快再次进入休眠模式。

下文列示了用于控制唤醒锁或深度唤醒锁的 API。

pmu_acquire_wakelock

项目

描述

功能

为某个模块获取唤醒锁

参数

nDeviceId:对应模块的设备 ID

返回值

pmu_release_wakelock

项目

描述

功能

释放某个模块的唤醒锁

参数

nDeviceId:对应模块的设备 ID

返回值

pmu_acquire_deepwakelock

项目

描述

功能

为某个模块获取深度唤醒锁

参数

nDeviceId:对应模块的设备 ID

返回值

pmu_release_deepwakelock

项目

描述

功能

释放某个模块的深度唤醒锁

参数

nDeviceId:对应模块的设备 ID

返回值

pmu_set_sysactive_time

在某些场景下,系统需要在活跃状态保持唤醒一段时间以完成特定流程。

项目

描述

功能

设置系统保持活跃状态的持续时间

参数

timeout:时间(单位:毫秒)

系统将从当前时刻起保持活跃状态达此时长

返回值

0

睡眠/唤醒回调 API

用于为 <nDeviceId> 注册挂起/恢复回调函数:

  • 挂起回调函数:系统进入睡眠模式前在空闲任务中触发

  • 恢复回调函数:系统唤醒后立即执行

如果在芯片休眠前或唤醒后有相关操作需要处理,可以使用 suspend 和 resume 回调函数。resume 函数的一个典型应用是获取唤醒锁,以防止芯片再次进入休眠模式。此外,如果 CPU 选择 PG(掉电关断),部分外设会断电,因此需要重新初始化。这些操作可以在 resume 函数中实现。

备注

  • 禁止在回调函数中使用可能引发 OS 调度的 API(如: rtos_task_yieldrtos_time_delay_ms、信号量/互斥锁相关操作)

  • 禁止在挂起回调函数中调用 pmu_set_sysactive_time (恢复回调函数中允许)

pmu_register_sleep_callback

项目

描述

功能

为某个模块注册挂起/恢复回调函数

参数

  • nDeviceId:需要挂起/恢复回调函数的设备 ID

  • sleep_hook_fun:挂起回调函数

  • sleep_param_ptr:挂起回调函数参数

  • wakeup_hook_fun:恢复回调函数

  • wakeup_param_ptr:恢复回调函数参数

返回值

pmu_unregister_sleep_callback

项目

描述

功能

注销某个模块的挂起/恢复回调函数

参数

  • nDeviceId:需要注销挂起/恢复回调函数的设备ID

  • sleep_hook_fun:挂起回调函数

  • sleep_param_ptr:挂起回调函数参数

  • wakeup_hook_fun:恢复回调函数

  • wakeup_param_ptr:恢复回调函数参数

返回值

pmu_set_max_sleep_time

项目

描述

功能

设置最大睡眠时间

参数

timer_ms:系统最大睡眠超时时间(单位:毫秒)

返回值

备注

  • 超时后,系统不会被唤醒。

  • 超时前,系统可能被其他事件唤醒。

  • 此设置仅单次有效,系统唤醒后时间自动清零。

唤醒原因 API

备注

唤醒时,相应的外设中断会被触发;清除中断时,唤醒原因中的对应位也会被清除。因此,在中断被清除之后,将无法获得唤醒原因。

SOCPS_AONWakeReason

项目

描述

功能

获取从深睡眠唤醒的原因

参数

返回值

  • Bit[0]: CHIP_EN 短按

  • Bit[1]: CHIP_EN 长按

  • Bit[2]: 掉电复位

  • Bit[3]: AON 定时器

  • Bit[5:4]: AON GPIO

  • Bit[8]: RTC

WAK_STATUS0

以下寄存器可用于获取唤醒原因。

寄存器

参数

WAK_STATUS0

  • Bit[1:0]: WLAN

  • Bit[2]: KM4_WAKE

  • Bit[3]: BT_WAKE_HOST

  • Bit[4]: IPC_KM4

  • Bit[9:6]: Basic TIMER4~7

  • Bit[11:10]: PMC TIMER0~1

  • Bit[14:12]: UART0~2

  • Bit[15]: UART_LOG

  • Bit[16]: GPIOA

  • Bit[17]: GPIOB

  • Bit[19:18]:I2C0~1

  • Bit[20]: Cap-Touch

  • Bit[21]: RTC

  • Bit[22]: ADC

  • Bit[24]: BOR

  • Bit[25]: PWR_DOWN

  • Bit[26]: Key-Scan

  • Bit[27]: AON_Timer

  • Bit[28]: AON_Wakepin

  • Bit[29]: SDIO

UART 和 LOGUART

对于需要特定时钟设置的外设,例如 UART 和 LOGUART,其设置流程在以下章节中进行了描述。

  1. 初始化 UART/LOGUART 并使能其中断。

  2. 设定唤醒源:在 sleep_wevent_config[] 中设置唤醒源 (WAKE_SRC_UART0/WAKE_SRC_UART1/WAKE_SRC_UART2_BT/WAKE_SRC_UART_LOG) 要唤醒的 CPU( WAKEUP_KM4WAKEUP_KM0),并确保中断注册在要唤醒的 CPU 上。

  3. 选择时钟源:

    1. XTAL: 在 ps_config[] 中将 xtal_mode_in_sleep 设置为 XTAL_Normal, 将 keep_OSC4M_on 设置为 TRUE。

    2. OSC2M: 在 ps_config[] 中将 keep_OSC4M_on 设置为 TRUE。

  4. 设置工作电压:在 ps_config[] 中将 sleep_to_08V 设定为 TRUE

  5. 通过释放 KM4 上的唤醒锁进入睡眠模式(PMU_OS 需要被释放,因为系统启动时默认已获取)。

  6. 唤醒后清除 UART/LOGUART 中断。

备注

  • 当使用 UART 作为唤醒源时,有以下限制:

    • Rx 时钟源只能为 OSC2M,且睡眠期间不可关闭 OSC4M。当波特率大于 115200 时,不建议使用 UART 作为唤醒源。

      • 睡前需要调用 API RCC_PeriphClockSource_UART(UARTx_DEV, UART_RX_CLK_OSC_LP) 将时钟切换到 OSC2M。

      • 醒后需要更高波特率,可通过 API RCC_PeriphClockSource_UART(UARTx_DEV, UART_RX_CLK_XTAL_40M) 切换为 XTAL40M Rx 时钟。

    • 用于唤醒的命令中超出 FIFO 深度(64 字节)的部分会丢失。

  • 当使用 LOGUART 作为唤醒源时,有以下限制:

    • 若 Rx 时钟源为 OSC2M,睡眠期间不可关闭 OSC4M。

      • 睡前需要调用 API RCC_PeriphClockSource_LOGUART(LOGUART_CLK_OSC_LP) 将时钟切换到 OSC2M。

      • 醒后需要更高波特率,可通过 API RCC_PeriphClockSource_LOGUART(LOGUART_CLK_XTAL_40M) 切换为 XTAL40M Rx 时钟。

    • 若 Rx 时钟源为 XTAL40M,睡眠期间不可关闭 XTAL。

    • 用于唤醒的命令中超出 FIFO 深度(16 字节)的部分会丢失。