电源管理架构

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

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

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

低功耗模式

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 进行唤醒。

../../_images/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 规范中定义的 WiFi STA 省电模式包括以下关键特性:

  • 在未发送或接收数据时,进入休眠状态。

  • 定期唤醒以接收 AP 的 Beacon 帧。

  • 利用 Beacon 中的 TIM(Traffic Indication Map, 流量指示映射)进行数据管理。

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

../../_images/wifi_timeline_of_power_saving.svg

省电模式时序图

基于上述标准 IEEE 802.11 省电机制,Ameba IC 提供三种 WiFi 省电模式:

模式

全称

描述

LPS

传统省电模式

在WiFi连接状态下,在活跃和休眠状态之间切换,并定期打开或关闭收发器以实现省电。

WoWLAN

无线局域网唤醒

允许SoC系统在保持WiFi连接的同时进入睡眠模式。 系统可通过单播数据包、广播/组播数据包(可选)以及AP断连事件被唤醒。

IPS

非活动省电模式

在未连接时实现完全断电状态。

WiFi 省电模式进入和退出条件:

模式

用户配置项

进入和退出条件

LPS

wifi_user_config.lps_enable

在WiFi连接状态下,根据流量低于或高于设定阈值时,自动进入或退出LPS模式。

WoWLAN

默认支持

在WiFi连接状态下,随AP(application processor)休眠或活跃模式自动进入或退出WoWLAN模式。

IPS

wifi_user_config.ips_enable

WiFi连接或断开时进入或退出。

唤醒源

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

唤醒源

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 字节)的部分会丢失。