陈拓 2022/10/29-2022/10/31
1. 开发环境
- 操作系统: Window10、WSL
- 编译环境: ARM GCC
- IDE: VSCode
- SDK版本: SDK_17.1.0
- 硬件开发板: 定制
- 开发环境构建
《WSL构建nRF5 SDK + ARM GCC开发环境》
https://blog.csdn.net/chentuo2000/article/details/125933307?spm=1001.2014.3001.5502
《WSL构建nRF5 SDK + ARM GCC开发环境 – RTT打印调试日志》
https://blog.csdn.net/chentuo2000/article/details/126104346?spm=1001.2014.3001.5502
2. 看门狗WDT概述
- 硬件的看门狗,防止应用程序锁定。
- 使用32.768kHz低频时钟源(LFCLK)
看门狗启动后,若芯片外部没有焊接32.768kHz的晶体,芯片会自动启动内部RC振荡器。
- CRV寄存器指定计数值
- 看门狗启动后加载 CRV 寄存器中的值
- 倒计时,向下计数器到0后,会溢出产生 TIMEOUT 事件。看门狗 TIMEOUT 事件会导致系统复位 或者 TIMEOUT 中断。
- 在程序正常运行时,应该在向下计数器数还未到0时重置计数器(喂狗)
- 当CPU在低功耗模式处于睡眠状态时,或调试过程中暂停CPU运行时,看门狗可以暂停
- 看门狗的超时时间由以下公式给出
timeout [s] = ( CRV + 1 ) / 32768
3. 看门狗WDT使用
3.1 sdk_config.h设置
~/nrf/nRF5_SDK_17.1.0_ddde560/examples/peripheral/wdt/pca10040/blank/config/sdk_config.h
// <e> NRFX_WDT_ENABLED - nrfx_wdt - WDT 外设驱动
//==========================================================
#ifndef NRFX_WDT_ENABLED
#define NRFX_WDT_ENABLED 1
#endif
// <o> NRFX_WDT_CONFIG_BEHAVIOUR - CPU SLEEP或HALT模式下的WDT行为
// <1=> 在睡眠状态下运行,在挂起状态下暂停
// <8=> 在睡眠状态下暂停,在挂起状态下运行
// <9=> 在睡眠和挂起状态下运行
// <0=> 在睡眠和挂起状态下暂停
#ifndef NRFX_WDT_CONFIG_BEHAVIOUR
#define NRFX_WDT_CONFIG_BEHAVIOUR 0
#endif
// <o> NRFX_WDT_CONFIG_RELOAD_VALUE - 重新加载值(毫秒) ms <1-131072000>
#ifndef NRFX_WDT_CONFIG_RELOAD_VALUE
#define NRFX_WDT_CONFIG_RELOAD_VALUE 2000
#endif
// <o> NRFX_WDT_CONFIG_NO_IRQ - 从WDT驱动中删除WDT IRQ处理
// <0=> 包括WDT IRQ中断处理
// <1=> 删除WDT IRQ中断处理
#ifndef NRFX_WDT_CONFIG_NO_IRQ
#define NRFX_WDT_CONFIG_NO_IRQ 0
#endif
// <o> NRFX_WDT_CONFIG_IRQ_PRIORITY - 中断优先级
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7
#ifndef NRFX_WDT_CONFIG_IRQ_PRIORITY
#define NRFX_WDT_CONFIG_IRQ_PRIORITY 6
#endif
// <e> NRFX_WDT_CONFIG_LOG_ENABLED - 启用模块中的日志记录。
//==========================================================
#ifndef NRFX_WDT_CONFIG_LOG_ENABLED
#define NRFX_WDT_CONFIG_LOG_ENABLED 0
#endif
// <o> NRFX_WDT_CONFIG_LOG_LEVEL - 默认日志级别
// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug
#ifndef NRFX_WDT_CONFIG_LOG_LEVEL
#define NRFX_WDT_CONFIG_LOG_LEVEL 3
#endif
// <o> NRFX_WDT_CONFIG_INFO_COLOR - ANSI转义代码前缀。
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRFX_WDT_CONFIG_INFO_COLOR
#define NRFX_WDT_CONFIG_INFO_COLOR 0
#endif
// <o> NRFX_WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix.
// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White
#ifndef NRFX_WDT_CONFIG_DEBUG_COLOR
#define NRFX_WDT_CONFIG_DEBUG_COLOR 0
#endif
3.2 头文件
#include "nrf_drv_wdt.h"
#include "nrf_drv_clock.h"
在nrfx_wdt.h中有头文件nrf_wdt.h的引用:
#include <hal/nrf_wdt.h>
- Makefile文件添加
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_wdt.c \
3.3 官方例程
- 使用sdk_config.h设置的默认值初始化
//Configure WDT.
nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
APP_ERROR_CHECK(err_code);
nrf_drv_wdt_enable();
- wdt_event_handler是事件触发回调处理函数
看门狗计数器溢出时触发。
/**
* @brief WDT events handler.
*/
void wdt_event_handler(void)
{
bsp_board_leds_off();
//NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
}
- 喂狗nrf_drv_wdt_channel_feed(m_channel_id);
在BSP事件触发回调处理函数中:
nrf_drv_wdt_channel_id m_channel_id;
/**
* @brief BSP events callback.
*/
void bsp_event_callback(bsp_event_t event)
{
switch (event)
{
case BSP_EVENT_KEY_0:
nrf_drv_wdt_channel_feed(m_channel_id);
break;
default :
//Do nothing.
break;
}
}
- BSP事件触发回调处理函数注册
err_code = bsp_init(BSP_INIT_BUTTONS, bsp_event_callback);
APP_ERROR_CHECK(err_code);
3.4 非官方例程
可以在初始化时修改某些sdk_config.h的设置。
//Configure WDT.
NRF_LOG_DEBUG("main Configure WDT.");
nrf_drv_wdt_config_t config = {
.behaviour = NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT,
.reload_value = 60000,
.interrupt_priority = 7,
};
nrf_drv_wdt_config_t wdt_config = config;
err_code = nrf_drv_wdt_init(&wdt_config, NULL);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
APP_ERROR_CHECK(err_code);
nrf_drv_wdt_enable();
其中:
- 函数f_drv_wdt_init(&wdt_config, NULL);
NULL表示不使用事件触发回调处理函数。
- 宏RF_WDT_BEHAVIOUR_RUN_SLEEP_HALT
在nrf_wdt.h中定义:
/** @brief WDT behavior in the SLEEP or HALT CPU modes. */
typedef enum
{
NRF_WDT_BEHAVIOUR_RUN_SLEEP = WDT_CONFIG_SLEEP_Msk, /**< WDT will run when CPU is in SLEEP mode. */
NRF_WDT_BEHAVIOUR_RUN_HALT = WDT_CONFIG_HALT_Msk, /**< WDT will run when CPU is in HALT mode. */
NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT = WDT_CONFIG_SLEEP_Msk | WDT_CONFIG_HALT_Msk, /**< WDT will run when CPU is in SLEEP or HALT mode. */
NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT = 0, /**< WDT will be paused when CPU is in SLEEP or HALT mode. */
} nrf_wdt_behaviour_t;
- 喂狗
在主循环中喂狗
NRF_LOG_INFO("main loop..........");
for (;;) {
nrf_drv_wdt_channel_feed(m_channel_id);
参考文档
nRF52832 Product Specification v1.3