当前文档版本为 v0.9.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

LowPower: DeepSleep GPIO PWM Wakeup

1 功能概述

本例程演示如何使 SoC 进入 DeepSleep 状态,然后通过 2 路外部 PWM 波形触发 GPIO 中断将其唤醒。

2 环境准备

  • 硬件设备与线材:

    • PAN1080 EVB 核心板底板各一块

    • JLink 仿真器(用于烧录例程程序)

    • 电流计(本文使用电流可视化测量设备 PPK2 [Nordic Power Profiler Kit II] 进行演示)

    • 带 2 路 PWM 波形输出的逻辑分析仪(本文使用 Kingst LA1010 逻辑分析仪进行演示)

    • USB-TypeC 线一条(用于底板供电和查看串口打印 Log)

    • 杜邦线数根(用于连接各个硬件设备)

  • 硬件接线:

    • 为确保能够准确地测量 SoC 本身的功耗,排除底板外围电路的影响,请勿将 EVB 核心板插到 EVB 底板上

    • 使用 USB-TypeC 线,将 PC USB 插口与 EVB 底板 USB->UART 插口相连

    • 使用杜邦线将(根据核心板芯片的型号不同,以下两种接法二选一):

      • EVB 底板上的 TX0 引脚与核心板上的 P00 引脚相连, EVB 底板上的 RX0 引脚与核心板上的 P01 引脚相连(若核心板芯片为 QFN32 或 LQFP64 封装)

      • EVB 底板上的 TX0 引脚与核心板上的 P30 引脚相连, EVB 底板上的 RX0 引脚与核心板上的 P31 引脚相连(若核心板芯片为 QFN48 封装)

    • 使用杜邦线将 JLink 仿真器的:

      • SWD_CLK 引脚与 EVB 核心板的 P46 引脚相连

      • SWD_DAT 引脚与 EVB 核心板的 P47 引脚相连

      • SWD_GND 引脚与 EVB 核心板的 GND 引脚相连

    • 使用杜邦线将 EVB 核心板上的:

      • P20 引脚与 EVB 底板的 P20 引脚相连

      • P02 引脚与 EVB 底板的 P02 引脚相连

      • P03 引脚与 EVB 底板的 P03 引脚相连

    • 将 PPK2 硬件的:

      • USB DATA/POWER 接口连接至 PC USB 接口

      • VOUT 引脚连接至 EVB 核心板的 VBAT 引脚

      • GND 引脚连接至 EVB 核心板的 GND 引脚

      • LOGIC PORT 的 VCC 引脚连接至 EVB 底板的 VBAT 引脚

      • LOGIC PORT 的 GND 引脚连接至 EVB 底板的 GND 引脚

      • LOGIC PORT 的 D0 引脚连接至 EVB 底板的 P20 引脚

      • LOGIC PORT 的 D1 引脚连接至 EVB 底板的 P02 引脚

      • LOGIC PORT 的 D2 引脚连接至 EVB 底板的 P03 引脚

    • 将 LA1010 硬件的:

      • USB 接口连接至 PC USB 接口

      • PWM1 引脚连接至 EVB 底板的 P02 引脚(用于触发 GPIO 唤醒)

      • PWM2 引脚连接至 EVB 底板的 P03 引脚(用于触发 GPIO 唤醒)

  • PC 软件:

    • 串口调试助手(UartAssist)或终端工具(SecureCRT),波特率 921600(用于接收串口打印 Log)

    • nRF Connect Desktop(用于配合 PPK2 测量 SoC 电流)

    • Kingst VIS(用于配合 LA1010 逻辑分析仪输出 PWM 波形)

3 编译和烧录

例程位置:zephyr\samples_panchip\low_power\deepsleep_gpio_pwm_wakeup

使用 ZAL 工具擦除 Flash 程序。关于 ZAL 工具的详细介绍请参考:Zephyr APP Launcher 工具介绍

4 例程演示说明

  1. PC 上打开 Kingst VIS 软件,自动连接逻辑分析仪,连接成功后,先确保其 2 路 PWM 输出功能均为关闭状态:

    image

    LA1010 关闭 2 路 PWM 信号输出功能

  2. PC 上打开 PPK2 Power Profiler 软件,供电电压选择 3300 mV,然后打开供电开关:

    image

    PPK2 使能芯片供电

    测试芯片中目前还没有程序,所以看到此时芯片耗电保持在 3mA 左右。

  3. 使用 ZAL 工具将编译后的例程烧录至芯片

    烧录成功后,最好断开 JLink 与芯片的连接以防止芯片 P46 和 P47 两个引脚有漏电情况发生

  4. 从串口工具中看到如下的打印信息:

    Try to load HW calibration data.. DONE.
    - Chip Type         : 0x80
    - Chip CP Version   : None
    - Chip FT Version   : 5
    - Chip MAC Address  : D0000C0293CA
    - Chip Flash UID    : 31373237300A29494330FFFFFFFFFFFF
    - Chip Flash Size   : 1024 KB
    *** Booting Zephyr OS build zephyr-v2.7.0-1346-g181eea9cf7ca  ***
    Try to take wakeup_sem..
    
  5. 此时观察芯片电流波形,发现稳定在 10uA 左右(说明芯片成功进入了 DeepSleep 模式):

    image

    系统初始化后进入 DeepSleep 模式

    这里芯片进入 DeepSleep 模式的底电流实际上是偏大的,这是由于 PPK2 的逻辑分析功能引脚接到芯片上的原因;若此时将逻分功能引脚 D0、D1、D2 从芯片底板上移除,则可看到芯片底电流会下降至 7uA 左右。

  6. 在 Kingst VIS 界面上,打开 2 路 PWM 输出功能,并分别将波形频率配置为 1Hz 和 0.5Hz,然后点击确定即可输出 PWM 波形:

    image

    LA1010 配置并开启 2 路 PWM 信号输出功能

  7. 由串口打印信息可知 2 路 PWM 均触发了芯片唤醒:

    [Uptime: 534106 ms] GPIO IRQ triggered: P02.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 534608 ms] GPIO IRQ triggered: P02.
    [Uptime: 534608 ms] GPIO IRQ triggered: P03.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 535110 ms] GPIO IRQ triggered: P02.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 535615 ms] GPIO IRQ triggered: P02.
    [Uptime: 535616 ms] GPIO IRQ triggered: P03.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 536114 ms] GPIO IRQ triggered: P02.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 536616 ms] GPIO IRQ triggered: P02.
    [Uptime: 536616 ms] GPIO IRQ triggered: P03.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 537118 ms] GPIO IRQ triggered: P02.
    wakeup_sem is taken.
    Try to take wakeup_sem..
    [Uptime: 537623 ms] GPIO IRQ triggered: P02.
    [Uptime: 537624 ms] GPIO IRQ triggered: P03.
    wakeup_sem is taken.
    
    • 程序配置为 GPIO 检测到上升沿或下降沿均可被唤醒并触发中断,而由上述 Log 可知,每隔 500ms 触发一次 P02 中断,每隔 1s 触发一次 P03 中断,与对应的 PWM 触发信号相符。

    • 对于本例程来说,PWM 波形频率最好不要高于 250 Hz,也即两次 GPIO 唤醒的间隔不小于 2ms;这是因为本例程使能了 UART 串口打印,而且程序会等待打印消息完全发送出去才会允许进入 DeepSleep 状态,而这期间下一个 GPIO 唤醒事件可能会到来, 从而导致丢掉一个 GPIO 中断。

    • 芯片本身设计的 GPIO 唤醒指标,对 GPIO 维持唤醒电平的时间也是有要求的:为保证 GPIO 能够正常唤醒,且唤醒中断也能正常触发, 需要将 GPIO 唤醒电平保持 350us 以上。在实际应用中,如果可能,我们推荐将 GPIO 唤醒电平保持 1ms 以上

  8. 此时再观察芯片电流波形与 GPIO 逻辑波形,可以看到芯片每隔 500ms 会从 DeepSleep 状态下醒来:

    image

    使用 2 路 PWM 波形通过 GPIO 唤醒芯片

    由电流波形可知芯片每隔 500ms 会被外部 PWM 波形唤醒,然后翻转 GPIO P20 后重新进入了 DeepSleep 模式,如此往复。

5 开发者说明

5.1 App Config 配置

本例程的 App Config(对应 prj.conf 文件)配置如下:

# Enable Low Power Flow
CONFIG_PM=y
CONFIG_BT_CTLR_SLEEP_CLOCK_SOURCE=1

# Enable GPIO Input Sentinel
CONFIG_PM_GPIO_INPUT_SENTINEL=y
CONFIG_PM_GPIO_INPUT_SENTINEL_INVERT_CTRL=y

# Disable Serial Uart & Log
# CONFIG_SERIAL=n
# CONFIG_UART_INTERRUPT_DRIVEN=n
# CONFIG_CONSOLE=n
# CONFIG_UART_CONSOLE=n
# CONFIG_PRINTK=n

# Forcely calibrate 32K RCL Clock
# CONFIG_SOC_FORCE_CALIB_RCL_CLK=y

# Increase Low power LDO calibrate code (can be 0/1/2/3)
# CONFIG_SOC_INCREASE_LLDO_CALIB_CODE=1

# Enable DC/DC
CONFIG_SOC_DCDC_PAN1080=y

其中:

  • CONFIG_PM=y:使能低功耗流程

  • CONFIG_BT_CTLR_SLEEP_CLOCK_SOURCE=1:低功耗时钟相关配置(目前必须固定配置为1)

  • CONFIG_PM_GPIO_INPUT_SENTINEL=y:开启 GPIO 输入电平检测功能,开启后当系统试图进入 DeepSleep 模式时,会先检查当前是否有使能中断的 GPIO,若有,则接着检查其输入电平是否与中断配置冲突,若冲突则阻止系统进入 DeepSleep 模式

    此处 “输入电平与中断配置冲突” 的含义是:中断配置为下降沿触发而此时输入电平已经为低电平,或者中断配置为上升沿触发而此时输入电平已经为高电平; PAN1080 SoC 的低功耗模式不支持这种冲突情况,因此在配置 GPIO 唤醒的时候为安全起见可将此开关打开。

  • CONFIG_PM_GPIO_INPUT_SENTINEL_INVERT_CTRL=y:当检测到当输入电平与中断配置冲突时,直接将当前的中断配置修改为不冲突的状态(此功能生效需要同时开启 GPIO 输入电平检测功能)

    例如,系统进入 DeepSleep 模式前,若检测到中断配置为下降沿触发而此时输入电平已经为低电平,则直接将当前中断配置修改为上升沿触发,然后进入 DeepSleep 状态;这样可以确保无论 当前 GPIO 输入电平为高还是低,均可以正常进入 DeepSleep 流程,直到下次输入电平变化重新将芯片唤醒。

  • CONFIG_SOC_DCDC_PAN1080=y:使能芯片的 DCDC 供电模式,以降低芯片动态功耗

5.2 App DeviceTree 配置

本例程的 App DeviceTree(对应 app.overlay 文件)配置如下:

&uart1 {
	status = "disabled";
};

&clk_xtl {
	/* Frequency of XTL clock, DO NOT CHANGE THIS ITEM */
	clock-frequency = <32768>;
	/* Enable/Disable the external 32768 Hz low speed crystal oscillator */
	status = "disabled";
};

&clk_rcl {
	/* Frequency of RCL clock, DO NOT CHANGE THIS ITEM */
	clock-frequency = <32000>;
	/* Enable/Disable the internal 32 KHz Low Speed RC */
	status = "okay";
};

&rcc {
	clocks = <&dpll &clk_rcl>;
	clock-frequency-slow = <32000>;
};

其中:

  • uart1status 属性配置为 disabled 以禁止系统上电后初始化 uart1 设备,确保不会因为 uart1 的引脚配置产生 IO 漏电

  • clk_xtlstatus 属性配置为 disabled 以禁用 32768Hz XTL 低速晶振(此为 SDK 默认配置)

  • clk_rclstatus 属性配置为 okay 以打开 32kHz RCL 内部低速时钟(此为 SDK 默认配置)

  • rcc 的:

    • clocks 属性的第 2 项(clk_slow)配置为 clk_rcl 以使系统使用 32kHz RCL 内部低速时钟(此为 SDK 默认配置)

    • clock-frequency-slow 属性配置为 32000 以告诉系统当前使用的低速时钟频率为 32000 Hz(此为 SDK 默认配置)

5.3 程序代码

请参考例程代码中的相关注释以获取详细解释。

6 RAM/Flash资源使用情况

Memory region         Used Size  Region Size  %age Used
           FLASH:       22964 B       256 KB      8.76%
            SRAM:        7128 B        64 KB     10.88%