Standby Mode0 P02 Key Wakeup¶
1 功能概述¶
本例程演示如何使 SoC 进入 Standby Mode 0 状态,然后通过 WKUP (P02) 按键将其唤醒。
Standby Mode 0 是芯片的最低功耗模式,只支持 P00/P01/P02 这三个 IO 将芯片唤醒(唤醒电平可配且共用)。由于 P00/P01 两个引脚默认为 SWD 功能,为方便演示本例程仅以 P02 唤醒为例进行说明。
2 环境准备¶
硬件设备与线材:
PAN107X EVB 核心板与底板各一块
JLink 仿真器(用于烧录例程程序)
电流计(本文使用电流可视化测量设备 PPK2 [Nordic Power Profiler Kit II] 进行演示)
USB-TypeC 线一条(用于底板供电和查看串口打印 Log)
杜邦线数根或跳线帽数个(用于连接各个硬件设备)
硬件接线:
将 EVB 核心板插到底板上
为确保能够准确地测量 SoC 本身的功耗,排除底板外围电路的影响,请确认 EVB 底板上的:
Voltage 排针组中的 VCC 和 VDD 均接至 3V3
POWER 开关从 LDO 档位拨至 BAT 档位(并确认底板背部的电池座内没有纽扣电池)
使用 USB-TypeC 线,将 PC USB 插口与 EVB 底板 USB->UART 插口相连
使用杜邦线将 EVB 底板上的 TX 引脚接至核心板 P16,RX 引脚接至核心板 P17
使用杜邦线将 JLink 仿真器的:
SWD_CLK 引脚与 EVB 底板的 P00 排针相连
SWD_DAT 引脚与 EVB 底板的 P01 排针相连
SWD_GND 引脚与 EVB 底板的 GND 排针相连
将 PPK2 硬件的:
USB DATA/POWER 接口连接至 PC USB 接口
VOUT 连接至 EVB 底板的 VBAT 排针
GND 连接至 EVB 底板的 GND 排针
PC 软件:
串口调试助手(UartAssist)或终端工具(SecureCRT),波特率 921600(用于接收串口打印 Log)
nRF Connect Desktop(用于配合 PPK2 测量 SoC 电流)
3 编译和烧录¶
例程位置:<PAN10XX-NDK>\01_SDK\nimble\samples\low_power\standby_m0_p02_key_wakeup\keil_107x
双击 Keil Project 文件打开工程进行编译烧录,烧录成功后断开 JLink 连线以避免漏电。
4 例程演示说明¶
PC 上打开 PPK2 Power Profiler 软件,供电电压选择 3300 mV,然后打开供电开关
从串口工具中看到如下的打印信息:
Try to load HW calibration data.. DONE. - Chip Info : 0x1 - Chip CP Version : 255 - Chip FT Version : 6 - Chip MAC Address : E11000000FF8 - Chip UID : 6D0001465454455354 - Chip Flash UID : 4250315A3538380B005B7B4356037D78 - Chip Flash Size : 512 KB APP version: 255.255.65535 Reset Reason: nRESET Pin Reset. Busy wait 100ms to keep SoC in active mode.. Try to enter SoC sleep/deepsleep mode for 1000ms.. Waked up from SoC sleep/deepsleep mode. Try to enter SoC standby mode 0..
此时观察芯片电流波形,发现稳定在 220nA 左右(说明芯片成功进入了 Standby Mode 0 状态):
芯片低功耗状态下的底电流(漏电流)与环境温度相关,温度越高,漏电流越大。
尝试按下 EVB 底板上的 WKUP 按键,由串口打印信息可知触发了唤醒并复位,复位的原因为 Standby Mode 0 EXTIO Wakeup(即 WKUP 按键唤醒),随后芯片依次进入 100ms 的 Busy 状态,1s 的 DeepSleep 状态,接着唤醒后进入 Standby Mode 0 状态继续等待 WKUP 按键唤醒:
Try to load HW calibration data.. DONE. - Chip Info : 0x1 - Chip CP Version : 255 - Chip FT Version : 6 - Chip MAC Address : E11000000FF8 - Chip UID : 6D0001465454455354 - Chip Flash UID : 4250315A3538380B005B7B4356037D78 - Chip Flash Size : 512 KB APP version: 255.255.65535 Reset Reason: Standby Mode 0 EXTIO Wakeup (cnt = 1). Busy wait 100ms to keep SoC in active mode.. Try to enter SoC sleep/deepsleep mode for 1000ms.. Waked up from SoC sleep/deepsleep mode. Try to enter SoC standby mode 0..
5 开发者说明¶
5.1 App Config 配置¶
本例程的 App Config(对应 app_config_spark.h 文件)配置如下:
其中,与本例程相关的配置有:
Enable DCDC (
CONFIG_SOC_DCDC_PAN1070 = 1
):使能芯片 DCDC 供电模式,以降低芯片动态功耗Log Enable (
CONFIG_LOG_ENABLE = 1
):使能串口 Log 输出Low Power Enable (
CONFIG_PM = 1
):使能系统低功耗流程
5.2 程序代码¶
5.2.1 主程序¶
主程序 app_main() 函数内容如下:
void app_main(void)
{
BaseType_t r;
print_version_info();
/* Create an App Task */
r = xTaskCreate(app_task, // Task Function
"App Task", // Task Name
APP_TASK_STACK_SIZE, // Task Stack Size
NULL, // Task Parameter
APP_TASK_PRIORITY, // Task Priority
NULL // Task Handle
);
/* Check if task has been successfully created */
if (r != pdPASS) {
printf("Error, App Task created failed!\n");
while (1);
}
}
打印 App 版本信息
创建 App 主任务 “App Task”,对应任务函数
app_task
确认线程创建成功,否则打印出错信息
5.2.2 App 主任务¶
App 主任务 app_task() 函数内容如下:
void app_task(void *arg)
{
uint8_t rst_reason;
/* Get the last reset reason */
printf("\nReset Reason: ");
rst_reason = soc_reset_reason_get();
switch (rst_reason) {
case SOC_RST_REASON_POR_RESET:
printf("Power On Reset.\n");
break;
case SOC_RST_REASON_PIN_RESET:
printf("nRESET Pin Reset.\n");
break;
case SOC_RST_REASON_SYS_RESET:
printf("NVIC System Reset.\n");
break;
case SOC_RST_REASON_STBM0_EXTIO_WAKEUP:
printf("Standby Mode 0 EXTIO Wakeup (cnt = %d).\n", ++wkup_cnt);
break;
default:
printf("Unhandled Reset Reason, refer to more reason define in os_lp.h!\n");
}
/* Enable P02 low level wakeup for standby mode 0 */
wakeup_p02_key_init(0);
printf("\nBusy wait 100ms to keep SoC in active mode..\n");
soc_busy_wait(100000);
printf("Try to enter SoC sleep/deepsleep mode for 1000ms..\n");
vTaskDelay(pdMS_TO_TICKS(1000));
printf("Waked up from SoC sleep/deepsleep mode.\n");
printf("Try to enter SoC standby mode 0..\n\n");
soc_busy_wait(1000); /* Wait for all log print done */
soc_enter_standby_mode_0();
printf("WARNING: Failed to enter SoC standby mode 0 due to unexpected interrupt detected.\n");
printf(" Please check if there is an unhandled interrupt during the standby mode 0\n");
printf(" entering flow.\n");
while (1) {
/* Busy wait */
}
}
获取并打印本次芯片启动的复位原因
在 wakeup_p02_key_init() 函数中初始化 EXTIO (P02) 配置
调用
soc_busy_wait()
接口使芯片在 Active 状态下全速运行 100ms调用
vTaskDelay()
接口使系统切换至 Idle Task 执行 1s,实际上会使芯片进入持续 1s 的 DeepSleep 状态调用
soc_busy_wait()
接口延时 1ms,目的是确保所有串口打印消息都发送完成调用
soc_enter_standby_mode_0()
接口,使系统进入 Standby Mode 0 低功耗状态
5.2.3 WKUP Key(P02)初始化程序¶
P02 初始化程序 wakeup_p02_key_init() 函数内容如下:
static void wakeup_p02_key_init(uint8_t wakeup_edge)
{
/* Configure GPIO P02 (WKUP Key) as Lowlevel Wakeup */
/* Configure P02 wakeup level due to wakeup_edge */
LP_SetExternalWake(ANA, wakeup_edge);
/* Set pinmux func of P56 as GPIO */
SYS_SET_MFP(P0, 2, GPIO);
/* Set P02 to input mode */
GPIO_SetMode(P0, BIT2, GPIO_MODE_INPUT);
if (wakeup_edge == 0) {
/* Enable internal pull-up resistor if P02 is low level wakeup */
GPIO_EnablePullupPath(P0, BIT2);
} else {
/* Enable internal pull-down resistor if P02 is high level wakeup */
GPIO_EnablePulldownPath(P0, BIT2);
}
/* Necessary for P02 to do manual 3v aon sync */
CLK_Wait3vSyncReady();
/* Wait for a while to ensure the internal pullup is stable before entering low power mode */
soc_busy_wait(10000);
}
配置 EXTIO 的唤醒电平
配置 P02 引脚 Pinmux 至 GPIO 功能
配置 P02 为数字输入模式
根据唤醒电平使能内部上拉或下拉电阻
执行一次 3v always-on 寄存器同步动作,以确保 P02 引脚的上下拉电阻配置生效
等待一段时间,确保上下拉电阻稳定
5.2.4 与低功耗相关的 Hook 函数¶
本例程还用到了 2 个与低功耗密切相关的 Hook 函数:
CONFIG_RAM_CODE void vSocDeepSleepEnterHook(void)
{
#if CONFIG_LOG_ENABLE
reset_uart_io();
#endif
}
CONFIG_RAM_CODE void vSocDeepSleepExitHook(void)
{
#if CONFIG_LOG_ENABLE
set_uart_io();
#endif
}
上述两个 Hook 函数用于在进入 DeepSleep 前和从 DeepSleep 唤醒后做一些额外操作,如关闭和重新配置 IO 为串口功能,以防止 DeepSleep 状态下 IO 漏电
详细解释请参考 Standby Mode1 GPIO Key Wakeup 例程中的相关介绍