Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Kernel
一个看门狗保护多线程的简单方案
发布于 2020-07-01 21:58:34 浏览:3925
订阅该版
在OS中,如何使用看门狗对多线程进行保护是一个问题。 这里我的做法是使用一个较高优先级的线程作为守护进程。每个需要看门狗保护的线程均进行注册,守护线程将注册过的线程维护在链表中,同时在循环中等待每个注册过的线程的喂狗事件。若在规定时间内有任意线程没有喂狗则打印出线程名称,并停止喂狗,等待看门狗复位MCU。 更完善可以添加对应的处理机制如“重启进程”“调用回调”等。 ```#define LOG_TAG "DAEMON" #include
#include
#include
#include "daemon.h" static uint32_t daemon_wd_flag_get(struct daemon_object *daemon); static void daemon_watchdog_init(struct daemon_object *daemon); static void daemon_wd_feed(struct daemon_object *daemon); static struct daemon_register_thread* daemon_find_thread(struct daemon_object *daemon, uint8_t index); static inline uint32_t daemon_wd_flag_clear(struct daemon_object *daemon); void daemon_thread_entry(void * param){ uint32_t threadFlag = 0; struct daemon_object *daemon = (struct daemon_object *)param; uint32_t time = daemon->wdtTimeout*1000;; while(1){ threadFlag = daemon_wd_flag_get(daemon); if(threadFlag !=0){ rt_err_t err = rt_event_recv(&daemon->event, threadFlag, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, time, RT_NULL); if (err == RT_EOK){ daemon_wd_flag_clear(daemon); LOG_D("All threads are running, feed the watch dog"); daemon_wd_feed(daemon); rt_thread_mdelay(1000); }else if(err == -RT_ETIMEOUT){ daemon->threadFlag = ~daemon->threadFlag; for(uint8_t i=0; i < daemon->daemonNum; i++){ if(daemon->threadFlag & 0x01){ struct daemon_register_thread* temp = daemon_find_thread(daemon, i); if(temp != RT_NULL) LOG_E("Thread [%s] is not running", temp->thread->name); } daemon->threadFlag >>=1; } daemon_wd_flag_clear(daemon); LOG_E("Wait watch dog reset the mcu"); while(1){ rt_thread_mdelay(1000); } }else{ LOG_E("Event recv err:%d", err); rt_thread_mdelay(100); } }else{ LOG_D("No thread register.."); daemon_wd_feed(daemon); rt_thread_mdelay(1000); } } } static uint32_t daemon_wd_flag_get(struct daemon_object *daemon){ uint32_t flag = 0; for(uint8_t i=0; i
daemonNum; i++){ flag <<= 1; flag |= 0x01; } return flag; } static inline uint32_t daemon_wd_flag_clear(struct daemon_object *daemon){ daemon->threadFlag = 0; } APP_ErrType daemon_init(struct daemon_object *daemon, const char *wd_device_name, uint32_t timeout){ APP_ErrType err = APP_OK; rt_err_t result; rt_slist_init(&daemon->threadHead); daemon->daemonNum = 0; daemon->threadFlag = 0; daemon->iwgDevice = rt_device_find(wd_device_name); if(daemon->iwgDevice == RT_NULL){ LOG_D("Cant find watch dog device"); return APP_ERR; } daemon->wdtTimeout = timeout; daemon_watchdog_init(daemon); result = rt_event_init(&daemon->event, "wd_event", RT_IPC_FLAG_FIFO); if (result != RT_EOK){ err = APP_ERR; goto errend; } daemon->daemonThread = rt_thread_create("daemon", daemon_thread_entry, daemon, 1024, 3, 40); if(daemon->daemonThread == RT_NULL) err = APP_OUT_OF_MEM; rt_thread_startup(daemon->daemonThread); errend: return err; } uint32_t daemon_thread_register(struct daemon_object *daemon, rt_thread_t tid){ uint32_t flag = 0; if(daemon->daemonNum < 32){ struct daemon_register_thread *temp = rt_malloc(sizeof(struct daemon_register_thread)); if(temp != RT_NULL){ daemon->daemonNum ++; temp->thread = tid; rt_slist_append(&daemon->threadHead, &temp->list); flag = (1<<(daemon->daemonNum-1)); } } return flag; } void daemon_fd_wd(struct daemon_object *daemon, uint32_t flag){ rt_event_send(&daemon->event, flag); daemon->threadFlag |= flag; } static struct daemon_register_thread* daemon_find_thread(struct daemon_object *daemon, uint8_t index){ struct daemon_register_thread* thread = RT_NULL; rt_slist_t *temp_list; if(index < daemon->daemonNum){ temp_list = rt_slist_next(&daemon->threadHead); for(uint8_t i=0; i < index; i++){ if(temp_list != RT_NULL) temp_list = rt_slist_next(temp_list); else break; } if(temp_list != RT_NULL) thread = rt_slist_entry(temp_list, struct daemon_register_thread, list); } return thread; } static void daemon_watchdog_init(struct daemon_object *daemon){ rt_device_t iwgDevice; iwgDevice = daemon->iwgDevice; rt_err_t ret = rt_device_init(iwgDevice); if (ret != RT_EOK){ LOG_E("Init wdt failed!
"); return; } ret = rt_device_control(iwgDevice, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &daemon->wdtTimeout + 3); if (ret != RT_EOK){ LOG_E("Set wdt timeout failed!
"); return; } ret = rt_device_control(iwgDevice, RT_DEVICE_CTRL_WDT_START, RT_NULL); if (ret != RT_EOK){ LOG_E("start wdt failed!
"); return; } } static void daemon_wd_feed(struct daemon_object *daemon){ rt_device_control(daemon->iwgDevice, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL); } ``` ```#ifndef _DAEMON_H #define _DAEMON_H #include
#include
#include "app_def.h" struct daemon_object{ uint8_t daemonNum; uint32_t threadFlag; uint32_t wdtTimeout; rt_thread_t daemonThread; rt_device_t iwgDevice; struct rt_event event; rt_slist_t threadHead; }; struct daemon_register_thread{ rt_slist_t list; rt_thread_t thread; }; APP_ErrType daemon_init(struct daemon_object *daemon, const char *wd_device_name, uint32_t timeout); uint32_t daemon_thread_register(struct daemon_object *daemon, rt_thread_t tid); void daemon_fd_wd(struct daemon_object *daemon, uint32_t flag); inline uint8_t daemon_is_watchdog_reset(void); inline void daemon_reset_flag_clear(void); #endif ```
查看更多
2
个回答
默认排序
按发布时间排序
红枫
认证专家
2020-07-01
这家伙很懒,什么也没写!
你没看到系统看守组件吗?
bernard
2020-07-01
这家伙很懒,什么也没写!
楼主可以去发一个软件包,让更多人(包括自己)未来在项目中更好、更方便的用起来
撰写答案
登录
注册新账号
关注者
0
被浏览
3.9k
关于作者
yushigengyu
这家伙很懒,什么也没写!
提问
15
回答
25
被采纳
0
关注TA
发私信
相关问题
1
请教cpu使用率分析
2
选择FreeRTOS, 还是RT-Thread。
3
thread heap stack overflow ?
4
rtt消息队列delay问题
5
释放被删除线程的内存地方在哪里啊
6
请教:各线程结束后,释放其中的内存的连续性问题
7
STM32F103中断关于信号量、邮箱问题
8
RTT中的线程栈大小如何控制
9
关于线程由执行态变为挂起态的代码实现,,,
10
rt_malloc(rt_size_t size)内存分配函数最小分配尺寸问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
2
RT-Thread 发布 EtherKit开源以太网硬件!
3
rt-thread使用cherryusb实现虚拟串口
4
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
5
《原子操作:程序世界里的“最小魔法单位”解析》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
a1012112796
13
个答案
1
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部