当前位置: 首页 > news >正文

RT thread 的看门狗框架分析

看门狗框架分析

核心数据结构说明

根据数据结构在具体的芯片上仅仅需要提供2个接口实现

#define RT_DEVICE_CTRL_WDT_GET_TIMEOUT    (RT_DEVICE_CTRL_BASE(WDT) + 1) /* 获取看门狗超时时间(以秒为单位) get timeout(in seconds) */
#define RT_DEVICE_CTRL_WDT_SET_TIMEOUT    (RT_DEVICE_CTRL_BASE(WDT) + 2) /* 设置看门狗超时时间(以秒为单位) set timeout(in seconds) */
#define RT_DEVICE_CTRL_WDT_GET_TIMELEFT   (RT_DEVICE_CTRL_BASE(WDT) + 3) /* 获取重启前的剩余时间(以秒为单位) get the left time before reboot(in seconds) */
#define RT_DEVICE_CTRL_WDT_KEEPALIVE      (RT_DEVICE_CTRL_BASE(WDT) + 4) /* 喂狗(刷新看门狗)refresh watchdog */
#define RT_DEVICE_CTRL_WDT_START          (RT_DEVICE_CTRL_BASE(WDT) + 5) /* 启动看门狗 start watchdog */
#define RT_DEVICE_CTRL_WDT_STOP           (RT_DEVICE_CTRL_BASE(WDT) + 6) /* 停止看门狗 stop watchdog */struct rt_watchdog_ops;
/*** @brief 看门狗设备结构体* */
struct rt_watchdog_device
{struct rt_device parent;const struct rt_watchdog_ops *ops;
};
typedef struct rt_watchdog_device rt_watchdog_t;/*** 2个接口函数:init和control* init:初始化看门狗* control:控制看门狗,包括设置超时时间、获取超时时间、获取剩余时间、喂狗、启动看门狗、停止看门狗*/
struct rt_watchdog_ops
{rt_err_t (*init)(rt_watchdog_t *wdt);rt_err_t (*control)(rt_watchdog_t *wdt, int cmd, void *arg);
};

看门狗注册

在看门狗框架层提供了4个api函数;

rt_err_t rt_hw_watchdog_register(struct rt_watchdog_device *wtd,const char                *name,rt_uint32_t                flag,void                      *data)
{struct rt_device *device;RT_ASSERT(wtd != RT_NULL);device = &(wtd->parent);device->type        = RT_Device_Class_WDT;//看门狗设备类device->rx_indicate = RT_NULL;device->tx_complete = RT_NULL;#ifdef RT_USING_DEVICE_OPSdevice->ops         = &wdt_ops;
#elsedevice->init        = rt_watchdog_init;//初始化看门狗device->open        = rt_watchdog_open;//打开看门狗device->close       = rt_watchdog_close;//关闭看门狗device->read        = RT_NULL;device->write       = RT_NULL;device->control     = rt_watchdog_control;//控制看门狗
#endifdevice->user_data   = data;/* register a character device */return rt_device_register(device, name, flag);
}

核心层驱动分析

1.初始化rt_watchdog_init

直接调用底层的init函数

static rt_err_t rt_watchdog_init(struct rt_device *dev)
{rt_watchdog_t *wtd;RT_ASSERT(dev != RT_NULL);wtd = (rt_watchdog_t *)dev;if (wtd->ops->init){return (wtd->ops->init(wtd));}return (-RT_ENOSYS);
}
stm32的init
static rt_err_t wdt_init(rt_watchdog_t *wdt)
{return RT_EOK;
}

2.打开rt_watchdog_open

无具体操作

static rt_err_t rt_watchdog_open(struct rt_device *dev, rt_uint16_t oflag)
{return (RT_EOK);
}

3.rt_watchdog_close

wtd->ops->control停止看门狗

static rt_err_t rt_watchdog_close(struct rt_device *dev)
{rt_watchdog_t *wtd;RT_ASSERT(dev != RT_NULL);wtd = (rt_watchdog_t *)dev;if (wtd->ops->control(wtd, RT_DEVICE_CTRL_WDT_STOP, RT_NULL) != RT_EOK){rt_kprintf(" This watchdog can not be stoped\n");return (-RT_ERROR);}return (RT_EOK);
}

4.rt_watchdog_control

直接调用底层的wtd->ops->control

static rt_err_t rt_watchdog_control(struct rt_device *dev,int              cmd,void             *args)
{rt_watchdog_t *wtd;RT_ASSERT(dev != RT_NULL);wtd = (rt_watchdog_t *)dev;return (wtd->ops->control(wtd, cmd, args));
}

5.这里学习下STM32的看门狗

1. 时钟源
  • IWDG 使用 内部低速 RC 振荡器(LSI),典型频率约为 40 kHz(范围通常为 30~60 kHz,具体见数据手册)。
  • LSI 不受系统时钟控制,即使主系统时钟失效,IWDG 仍可正常工作。
2.超时时间计算公式

IWDG 的超时时间由两个寄存器决定:

  • 预分频器(Prescaler):可选值为 4、8、16、32、64、128、256。
  • 重装载值(Reload Value):范围 0x000 ~ 0xFFF(即 0~4095)。

超时时间计算公式为:

在这里插入图片描述

其中:

  • fLS**I≈40kHz
  • Prescaler 取值如 4、8、…、256(对应寄存器值 0~7)
  • Reload 是 12 位整数(最大 4095)
3. 示例:设置 1 秒超时

假设 fLS**I=40kHz,目标 T=1s

选择 Prescaler = 32(寄存器值 = 3),则:

在这里插入图片描述

6.继续STM32的分析控制函数

这里就是实现了几个控制指令

1. 喂狗RT_DEVICE_CTRL_WDT_KEEPALIVE
2. 设置看门狗超时时间 RT_DEVICE_CTRL_WDT_SET_TIMEOUT
3. 获取看门狗超时时间RT_DEVICE_CTRL_WDT_GET_TIMEOUT
4. 启动看门狗 RT_DEVICE_CTRL_WDT_START
static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
{switch (cmd){/* feed the watchdog 喂狗 */case RT_DEVICE_CTRL_WDT_KEEPALIVE:if(HAL_IWDG_Refresh(&stm32_wdt.hiwdg) != HAL_OK)//刷新看门狗{LOG_E("watch dog keepalive fail.");}break;/* set watchdog timeout  设置看门狗超时时间 */case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
#if defined(LSI_VALUE)if(LSI_VALUE){stm32_wdt.hiwdg.Init.Reload = (*((rt_uint32_t*)arg)) * LSI_VALUE / 256 ;//根据LSI_VALUE计算重新加载值;这里得到了重载值}else{LOG_E("Please define the value of LSI_VALUE!");}if(stm32_wdt.hiwdg.Init.Reload > 0xFFF)//重载的合法性判定{LOG_E("wdg set timeout parameter too large, please less than %ds",0xFFF * 256 / LSI_VALUE);return -RT_EINVAL;}
#else#error "Please define the value of LSI_VALUE!"
#endifif(stm32_wdt.is_start)//这里就是在修改了重载值后,重新初始化一次{if (HAL_IWDG_Init(&stm32_wdt.hiwdg) != HAL_OK){LOG_E("wdg set timeout failed.");return -RT_ERROR;}}break;/* get watchdog timeout 获取看门狗超时时间 */case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
#if defined(LSI_VALUE)if(LSI_VALUE){(*((rt_uint32_t*)arg)) = stm32_wdt.hiwdg.Init.Reload * 256 / LSI_VALUE;//获取看门狗超时时间;这里根据重载值和LSI_VALUE计算超时时间}else{LOG_E("Please define the value of LSI_VALUE!");}
#else#error "Please define the value of LSI_VALUE!"
#endifbreak;/* start watchdog 启动看门狗 */case RT_DEVICE_CTRL_WDT_START:if (HAL_IWDG_Init(&stm32_wdt.hiwdg) != HAL_OK){LOG_E("wdt start failed.");return -RT_ERROR;}stm32_wdt.is_start = 1;break;default:LOG_W("This command is not supported.");return -RT_ERROR;}return RT_EOK;
}

7.注册看门狗

  • 是初始化 hiwdg结构体;
  • 设置wdt_init 和 wdt_control 接口
int rt_wdt_init(void)
{
#if defined(SOC_SERIES_STM32H7)stm32_wdt.hiwdg.Instance = IWDG1;
#elsestm32_wdt.hiwdg.Instance = IWDG;
#endifstm32_wdt.hiwdg.Init.Prescaler = IWDG_PRESCALER_256;//设置预分频器为256stm32_wdt.hiwdg.Init.Reload = 0x00000FFF;
#if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G4)|| defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) \|| defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0)stm32_wdt.hiwdg.Init.Window = 0x00000FFF;
#endifstm32_wdt.is_start = 0;ops.init = &wdt_init;ops.control = &wdt_control;stm32_wdt.watchdog.ops = &ops;/* register watchdog device */if (rt_hw_watchdog_register(&stm32_wdt.watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK){LOG_E("wdt device register failed.");return -RT_ERROR;}LOG_D("wdt device register success.");return RT_EOK;
}
INIT_BOARD_EXPORT(rt_wdt_init);

在这里插入图片描述

http://www.dtcms.com/a/589643.html

相关文章:

  • 分销商城网站开发证书兼职的人才网站
  • 11.9 脚本网页 消消乐
  • Spring AI Alibaba 1.x 源码分析-架构设计
  • 有哪些做海岛的网站上海网站建设排名公司哪家好
  • 太原市建设局网站网站建设经验典型
  • AIGC(生成式AI)试用 40 -- 程序(Python + OCR)-2
  • 3.Python基础:函数
  • 中山市西区建设局网站wordpress 获取导航
  • RHCSA笔记1
  • 用户按下字符键后的vk键状态是win32k!xxxSkipSysMsg函数里面的win32k!UpdateKeyState函数设置的====非常重要
  • Zynq-7000嵌入式开发100问全解析解答共十万字回答,适用入门嵌入式软件初级工程师,筑牢基础,技术积累,校招面试。
  • 有没有专门做化妆品小样的网站国内的有什么好wordpress主题
  • 帝国cms 网站搬家python编程课哪个机构最好
  • 响应式网站代码规范河南省工程建设信息网官网入口
  • 做网站 分工深圳软件开发工作室
  • 一周学习总结
  • 长沙品牌网站设计做网站app要注册哪类商标
  • 【AIGC面试面经第五期】AI绘画-AI绘画框架相关问答
  • 音乐网站设计外国手做网站
  • 网站有什么采集网站后台数据
  • Linux33 网络编程-多线程TCP并发
  • Tomcat和负载均衡
  • 【算力】AI万卡GPU集群交付确认项与日常运维(算力压测、数据倒腾、日常运维)
  • 网站建设 东八区学校网站建设的意义的主要负责人
  • 网站开发招商计划书c 网站开发框架有
  • 成都企业网站开发网站主页设计费用
  • 数据结构——四十、折半查找(王道408)
  • 操作系统 内存(5)虚拟内存机制
  • 郑州网站建设专业乐云seowordpress user role
  • JavaScript 的 Web APIs 入门到实战全总结(day7):从数据处理到交互落地的全链路实战(附实战案例代码)