本文介绍的数据结构和 API 可以参考 SDK 中 zyf_wtd.h 文件
在 OpenCPU 方案中,默认在库中有启用硬件看门狗,而且会定时去喂狗,开发者不用去处理这块逻辑。另外,本方案向开发者提供了一个软件看门狗。通过调用 ZYF_Wdt_Enable 对软件看门狗进行开启,开启后,如果规定时间内没有去清除软件看门狗计数器数值,则模块会重启。通过 ZYF_FeedDog 对软件看门狗计数器清零。以防模块重启。通过 ZYF_Wdt_Disable 可关闭看门狗。
1.2.1 ZYF_Wdt_Enable 此功能用于启动看门狗· 函数原型 bool ZYF_Wdt_Enable(uint32_t max_interval_ms);· 参数 max_interval_ms: [输入]:看门狗触发时间· 返回值 使能看门狗的结果
1.2.2 ZYF_Wdt_Disable 此函数用来关闭看门狗· 函数原型 bool ZYF_Wdt_Disable(void);
· 参数 NONE· 返回值 关闭看门狗的结果
1.2.3 ZYF_FeedDog 喂狗,即将寄存器中的数值清零。· 函数原型 void ZYF_FeedDog(void);· 参数 NONE· 返回值 NONE
本章节主要介绍如何在 SDK 中使用 example_wtd.c 单独测试看门狗功能。
例程中,开启一个线程 SMSThread_Example 用来测试看门狗功能。ZYF_WtdTest() 用来设置定时器参数。ZYF_Wtd()的功能一方面是设置好看门狗的超时时间为 10 秒;另一方 面是设置好定时器的喂狗周期为 9 秒。具体如下:
#include <stddef.h> #include <stdint.h> #include <stdbool.h> #include "zyf_timer.h" #include "zyf_wtd.h" #include "zyf_trace.h" #include "zyf_app.h" #include "zyf_uart.h" #include "zyf_thread.h" typedef struct { uint32_t max_interval; uint32_t feed_interval; ZYF_Timer_t *feed_timer; } ZYF_Wdt_t; static ZYF_Wdt_t gBsjWdt; static Uart_Param_t g_uart1param; void UartWriteCallBack(void* Param) // general com { Uart_Param_t *uartparam = (Uart_Param_t *)Param; if(Param == NULL) { return; } ZYF_UartWrite(uartparam->port,(uint8_t *)"UartWrite succeed\r\n",strlen("UartWrite succeed\r\n")); ZYF_UartWriteCallbackSwitch(uartparam->port,false); } void UartReadCallBack(void* Param) // { uint32_t recvlen = 0; Uart_Param_t *uartparam = (Uart_Param_t *)Param; ZYF_LOG("Uart%d recv",uartparam->port); while(ZYF_UartRead(uartparam->port, &(uartparam->uartbuf[recvlen]), 1)) { ZYF_LOG("recv :x",uartparam->uartbuf[recvlen]); recvlen++; } ZYF_UartWrite(uartparam->port,uartparam->uartbuf,recvlen); ZYF_UartWriteCallbackSwitch(uartparam->port,true); } static void AppUartInit(void) { int32_t ret; g_uart1param.port = DEBUG_PORT; ZYF_UartRegister(g_uart1param.port, UartReadCallBack,&g_uart1param); ZYF_UartWriteCbRegister(g_uart1param.port,UartWriteCallBack,&g_uart1param); ZYF_UartOpen(g_uart1param.port, 115200, ZYF_FC_NONE); ZYF_LOG("AppUartInit"); return; } static void _feedDog(void *wd_) { ZYF_Wdt_t *wd = (ZYF_Wdt_t *)wd_; ZYF_LOG("ZYF_feedDog"); ZYF_FeedDog(); ZYF_StartTimer(wd->feed_timer, wd->feed_interval); } void ZYF_WtdClose(void) { ZYF_Wdt_Disable(); } bool ZYF_WtdOpen(uint32_t max_interval_ms, uint32_t feed_interval_ms) { ZYF_Wdt_t *wd = &gBsjWdt; if (max_interval_ms < feed_interval_ms) return false; ZYF_Wdt_t *timer = ZYF_CreateTimer(_feedDog, (void *)wd); if (timer == NULL) return false; wd->max_interval = max_interval_ms; wd->feed_interval = feed_interval_ms; wd->feed_timer = timer; bool r = ZYF_Wdt_Enable(max_interval_ms); if (!r) { ZYF_DeleteTimer(timer); return false; } ZYF_StartTimer(wd->feed_timer, wd->feed_interval); return true; } void ZYF_WtdTest(void) { bool ret = ZYF_WtdOpen(10000, 9000); if(!ret) { ZYF_LOG("ZYF_WTD init failed."); } ZYF_LOG("ZYF_WTD init success!"); } void SMSThread_Example(void * Param) { ZYF_MsgQ_t *ptMsg; ZYF_AppMsg_t tMsg; int iRet = -1; ptMsg = ZYF_MsgQCreate(10, sizeof(ZYF_AppMsg_t)); ZYF_LOG("thread enter!"); ZYF_WtdTest(); while (1) { ZYF_LOG("in while."); iRet = ZYF_MsgQGet(ptMsg, (void *)&tMsg); if (iRet < 0) { ZYF_LOG("Failed to get msg"); ZYF_ThreadSleep(1000); } } } static void prvInvokeGlobalCtors(void) { extern void (*__init_array_start[])(); extern void (*__init_array_end[])(); size_t count = __init_array_end - __init_array_start; for (size_t i = 0; i < count; ++i) __init_array_start[i](); } int appimg_enter(void *param) { AppUartInit(); ZYF_LOG("application image enter, param 0x%x", param); prvInvokeGlobalCtors(); ZYF_ThreadCreate("SMSThread_Example", SMSThread_Example, NULL, ZYF_PRIORITY_HIGH, 10*1024); return 0; } void appimg_exit(void) { OSI_LOGI(0, "application image exit"); }