nRF Connect SDK system off模式介绍
目录
概述
1. 软硬件环境
1.1 软件开发环境
1.2 硬件环境
2 System Off 模式
2.1 模式介绍
2.2 注意事项
3 功能实现
3.1 框架结构介绍
3.2 代码介绍
4 功能验证
4.1 编译和下载代码
4.2 测试
4.3 使能CONFIG_APP_USE_RETAINED_MEM的测试
5 main.c的源代码文件
参考文献
概述
System Off 模式是 Nordic nRF 系列芯片最省电的工作模式,在 nRF Connect SDK 中通过 Zephyr RTOS 的电源管理框架提供完善支持。本文通过一个demo介绍system off功能的用法及其相关函数的功能。
1. 软硬件环境
1.1 软件开发环境
nordic提供了基于zephyr平台sdk, 其提供了大量的demo可供开发者参考和使用,同时nordi还提供一个集成的软件库工具,方便开发者安装相应的SDK和编译工具链。集成环境同时包含了其他的一些软件,非常便于进行项目开发。
软件工具 | 功能 | 版本信息 |
nRF Connect SDK | nordic提供基于zephyr的代码库 | v2.9.0 |
nRF Connect SDK Toolchain | 代码编译工具 | v2.9.1 |
VS-CODE | 集成开发环境 | v1.99.3 |
nRF Connect for Desktop | nordic集成工具链 | v5.1.0 |
nRF Connect | 手机App |
手机App下载地址:
https://nav.nordicsemi.com/search?query=nRF%20Connect
搭建编译环境的注意点
安装工具时,在D:\ncs\v2.9.0目录下执行如下语句,安装与编译器相关的工具链
pip3 install --user -r scripts/requirements.txt
运行该语句后,安装信息如下:
1.2 硬件环境
本案例是在nRF52832开发板(nRF52-DK)上实现的,该开发板nRF52832的主要特点如下:
1)板载j-link调试接口
2)引出所有 IO接口,用户可根据实际应用,外载其他设备
3)支持4个LED
4)支持4路Key接口
5)板载UART调试接口,方便打印调试信息
2 System Off 模式
2.1 模式介绍
System Off 是 Nordic nRF 系列芯片的一种深度节能模式,在 nRF Connect SDK (基于 Zephyr RTOS) 中有完整的支持。这种模式可以最大限度地降低功耗,适用于电池供电设备。
System Off 模式特性
超低功耗:仅保持 RAM 保持电源 (约 0.7μA @ 3V)
唤醒源:特定 GPIO、LPCOMP、NFC、RTC 等。注意: nRF52832不支持RTC唤醒模式
数据保留:可选择保留部分或全部 RAM 内容
系统状态:CPU 和外设完全停止
1)电源特性
-
功耗表现:0.7μA @ 3V (RAM 保持)
-
电压范围:1.7V - 3.6V
-
唤醒时间:~100μs 从 OFF 到 RUN
2) 状态对比
模式 | 电流消耗 | 唤醒源 | RAM保持 | 执行恢复 |
---|---|---|---|---|
RUN | ~4mA | 任意 | 保持 | 继续执行 |
IDLE | ~1.5mA | 任意 | 保持 | 继续执行 |
System Off | ~0.7μA | 有限 | 可选 | 复位重启 |
2.2 注意事项
调试限制:在 System Off 模式下,调试器连接会断开
外设状态:进入 System Off 前应正确关闭所有外设
电流测量:使用高精度电流表测量实际功耗
唤醒延迟:从 System Off 唤醒会有约 100μs 的启动延迟
GPIO 状态:配置为唤醒源的 GPIO 必须保持有效电平
3 功能实现
3.1 框架结构介绍
软件使用VS-CODE开发工具搭建,底层使用zephry平台,其实现功能主要如下:
1)系统上电运行一段时间后,通过调用system off进入到低功耗模式
2)使用按button-1触发系统重新运行
3)retained组件管理进入睡眠后的参数
3.2 代码介绍
1)prj.conf
代码第1行: 使能PM管理模式
代码第2行:使能IO工具库
代码第3行:使能CRC工具库
代码第4行:使能POWEROFF工具库
2)main.c文件
代码12~17行: 引入zephyr提供的代码库
代码23行: 使用按键,其用于唤醒MCU
代码第29行:获取控制云台串口端口信息
代码第31行:check device初始化是否完成
代码第63行: 配置和按键相连的端口为输入口
代码第69行:配置该端口为输入中断模式
代码第78行: 挂起控制台设备
注释:
pm_device_action_run
的功能介绍
pm_device_action_run
是 Zephyr RTOS (以及基于它的 nRF Connect SDK) 中电源管理子系统的一个重要函数,用于对设备执行特定的电源管理操作。1)函数原型
int pm_device_action_run(const struct device *dev, enum pm_device_action action);
2)参数说明
dev
: 指向目标设备的指针,可使用DEVICE_DT_GET
宏获取
action
: 要执行的电源管理操作,有以下几种可能值:
PM_DEVICE_ACTION_SUSPEND
: 挂起设备
PM_DEVICE_ACTION_RESUME
: 恢复设备
PM_DEVICE_ACTION_TURN_ON
: 打开设备
PM_DEVICE_ACTION_TURN_OFF
: 关闭设备
PM_DEVICE_ACTION_LOW_POWER
: 进入低功耗模式
PM_DEVICE_ACTION_FORCE_SUSPEND
: 强制挂起3)返回值
0: 操作成功
负数: 错误代码 (如 -ENOTSUP 表示设备不支持该操作)
4) 函数的用法
- 1) 基本用法
const struct device *sensor_dev = DEVICE_DT_GET(DT_NODELABEL(bme280));// 关闭传感器 pm_device_action_run(sensor_dev, PM_DEVICE_ACTION_TURN_OFF);// 需要时重新打开 pm_device_action_run(sensor_dev, PM_DEVICE_ACTION_TURN_ON);
- 2)批量管理多个设备
const struct device *devices[] = {DEVICE_DT_GET(DT_NODELABEL(uart0)),DEVICE_DT_GET(DT_NODELABEL(i2c0)),DEVICE_DT_GET(DT_NODELABEL(spi1)), };void suspend_all_devices(void) {for (int i = 0; i < ARRAY_SIZE(devices); i++) {pm_device_action_run(devices[i], PM_DEVICE_ACTION_SUSPEND);} }
- 3) 与电源状态结合使用
#include <pm/pm.h>void enter_low_power_mode(void) {// 首先挂起所有设备suspend_all_devices();// 然后进入系统低功耗状态pm_power_state_force(0, (struct pm_state_info){.state = PM_STATE_SUSPEND_TO_RAM,.substate_id = 0,.info = PM_STATE_INFO_DT_ITEMS_LIST(DT_NODELABEL(power_states))}); }
- 4) 传感器周期性采样
void sample_sensor_periodically(void) {const struct device *sensor = DEVICE_DT_GET(DT_NODELABEL(bme280));while (1) {// 唤醒传感器pm_device_action_run(sensor, PM_DEVICE_ACTION_TURN_ON);k_msleep(10); // 等待稳定// 采样sensor_sample_fetch(sensor);// 完成后再关闭pm_device_action_run(sensor, PM_DEVICE_ACTION_TURN_OFF);k_sleep(K_MINUTES(5)); // 5分钟后再采样} }
- 5) 电池供电设备
void manage_battery_life(void) {const struct device *display = DEVICE_DT_GET(DT_NODELABEL(ssd1306));// 用户不活动时if (inactive_time > INACTIVITY_THRESHOLD) {// 关闭显示屏pm_device_action_run(display, PM_DEVICE_ACTION_TURN_OFF);// 挂起非必要外设pm_device_action_run(DEVICE_DT_GET(DT_NODELABEL(i2c1)), PM_DEVICE_ACTION_SUSPEND);} }
4 功能验证
4.1 编译和下载代码
编译配置项如下:
编译结果如下:
下载代码至板卡中:
4.2 测试
下载代码到板卡中之后,可以看见如下log:
提示信息显示,按键sw0可以重新唤醒MCU,按键swo后,
4.3 使能CONFIG_APP_USE_RETAINED_MEM的测试
1)编译后重新下载代码至板卡,运行结果如下:
2)按下SW0后的log
5 main.c的源代码文件
/** Copyright (c) 2019 Nordic Semiconductor ASA** SPDX-License-Identifier: Apache-2.0*/#include "retained.h"#include <inttypes.h>
#include <stdio.h>#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/pm/device.h>
#include <zephyr/sys/poweroff.h>
#include <zephyr/sys/util.h>#if IS_ENABLED(CONFIG_GRTC_WAKEUP_ENABLE)
#include <zephyr/drivers/timer/nrf_grtc_timer.h>
#define DEEP_SLEEP_TIME_S 2
#else
static const struct gpio_dt_spec sw0 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
#endifint main(void)
{int rc;const struct device *const cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));if (!device_is_ready(cons)) {printf("%s: device not ready.\n", cons->name);return 0;}printf("\n%s system off demo\n", CONFIG_BOARD);if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) {bool retained_ok = retained_validate();/* Increment for this boot attempt and update. */retained.boots += 1;retained_update();printf("Retained data: %s\n", retained_ok ? "valid" : "INVALID");printf("Boot count: %u\n", retained.boots);printf("Off count: %u\n", retained.off_count);printf("Active Ticks: %" PRIu64 "\n", retained.uptime_sum);} else {printf("Retained data not supported\n");}#if IS_ENABLED(CONFIG_GRTC_WAKEUP_ENABLE)int err = z_nrf_grtc_wakeup_prepare(DEEP_SLEEP_TIME_S * USEC_PER_SEC);if (err < 0) {printk("Unable to prepare GRTC as a wake up source (err = %d).\n", err);} else {printk("Entering system off; wait %u seconds to restart\n", DEEP_SLEEP_TIME_S);}
#else/* configure sw0 as input, interrupt as level active to allow wake-up */rc = gpio_pin_configure_dt(&sw0, GPIO_INPUT);if (rc < 0) {printf("Could not configure sw0 GPIO (%d)\n", rc);return 0;}rc = gpio_pin_interrupt_configure_dt(&sw0, GPIO_INT_LEVEL_ACTIVE);if (rc < 0) {printf("Could not configure sw0 GPIO interrupt (%d)\n", rc);return 0;}printf("Entering system off; press sw0 to restart\n");
#endifrc = pm_device_action_run(cons, PM_DEVICE_ACTION_SUSPEND);if (rc < 0) {printf("Could not suspend console (%d)\n", rc);return 0;}if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) {/* Update the retained state */retained.off_count += 1;retained_update();}sys_poweroff();return 0;
}
参考文献
D:\ncs\v2.9.0\zephyr\samples\boards\nordic\system_off