STM32 看门狗多线程状态监护 - 基于RT-Thread应用 - 源码

说明:本文记录基于RT-Thread 的 stm32看门狗的多线程监控方法,这里介绍的方法让看门狗线程监控多个线程,任何被监控的线程的卡死都可以触发看门狗复位。

测试平台:STM32 ,RT-Thread 3.1.5

1.详见代码:

1.1 iwdg.h

#ifndef __iwdg_H
#define __iwdg_H
#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ---------------------------------*/
#include "stm32g4xx.h"
#include "stm32g4xx_hal.h"
#include "stm32g4xx_ll_pwr.h"
#include "rtthread.h"

extern IWDG_HandleTypeDef hiwdg;

void MX_IWDG_Init(void);
void iwdg_thread_entry(void* parameter);
void sys_iwdg_app(rt_thread_t thread);
int sys_iwdg_thread_init(void);

#ifdef __cplusplus
}
#endif
#endif /*__ iwdg_H */

1.2 iwdg.c

/* 使用范例 */
#if 0
/* step:1 打开看门狗相关头文件宏  stm32g4xx_hal_conf.h 文件的 #define HAL_IWDG_MODULE_ENABLED */
#define HAL_IWDG_MODULE_ENABLED

/* step:2 打开看门狗初始化函数定义,定义看门狗的溢出时间   */
MX_IWDG_Init();

/* step:3 系统看门狗管理线程初始化 sys_iwdg_thread_init() */
sys_iwdg_thread_init();

/* step:4 在需要看护的线程中调用这个函数即可,在线程中循环调用完成线程喂狗 */
sys_iwdg_app(rt_thread_self());

#endif

/* Includes ------------------------------------------------------------------*/
#include "iwdg.h"
#include 
#include "stdio.h"
#include 

/* 系统线程管理看门狗配置参数 --------------------------------------------------*/
#define SYS_IWDG_DATA_NUM      (10)         /* 系统看门狗管理线程数量 */
#define SYS_IWDG_TIMEOUT       (2000)       /* 系统看门狗超时时间 :单位 ms,注意必须小于 IWDG_TIMOUT  */
#define SYS_IWDG_TIME          (100)        /* 系统看门狗超循环监测间隔时间 :单位 ms,注意必须小于 IWDG_TIMOUT */
#define IWDG_PRINTF            (1)          /* 系统看门狗超信息打印,1开启,0关闭  */

#define IWDG_TIMOUT            (5000)       /* 看门狗重启时间,单位 ms,范围(8 - 32760)ms */
#define IWDG_LSI_RC            (32000)      /* 看门狗时钟,根据芯片确定, 单位 Hz, */
#define IWDG_RELOAD            (uint32_t)(IWDG_TIMOUT * IWDG_LSI_RC / (256 * 1000))  /* 看门狗重载值,自动计算  */


/* IWDG 看门狗管理线程配置*/
#ifndef IWDG_THREAD_THREAD_PRIORITY_LEVEL
#define IWDG_THREAD_THREAD_PRIORITY_LEVEL                       (1)       /* 线程优先级 */
#endif

#ifndef IWDG_THREAD_THREAD_STACKSIZE
#define IWDG_THREAD_THREAD_STACKSIZE                          (512)       /* 线程堆栈 */
#endif

#ifndef IWDG_THREAD_THREAD_SLOT_DURATION
#define IWDG_THREAD_THREAD_SLOT_DURATION                       (20)       /* 线程时间片 */
#endif

typedef struct
{
    uint32_t thread;            /* 看门狗线程句柄指针 */
    uint32_t tick_time;         /* 线程喂狗时间 */
}sys_iwdg_data_t;

static sys_iwdg_data_t sys_iwdg_data[SYS_IWDG_DATA_NUM]; /* 系统看门狗管理变量 */


IWDG_HandleTypeDef hiwdg;

/* IWDG init function 看门狗初始化函数
 * LSI_RC 看门狗独立时钟 32K
 * .看门狗延时计算 (1/32000) * Prescaler * Reload
 * */

void MX_IWDG_Init(void)
{
    hiwdg.Instance = IWDG;
    hiwdg.Init.Prescaler = IWDG_PRESCALER_256; /* IWDG计数器时钟预分频器 */
    hiwdg.Init.Window = 4095; /* IWDG看门狗窗口值,0~4095 */
    hiwdg.Init.Reload = IWDG_RELOAD; /* IWDG看门狗重置值,0~4095,重置后会自减,减到0时MCU会复位。 */
    if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
    {
       // Error_Handler();
    }
}


/* 线程注册和喂狗函数,如果线程没注册过就自动注册并喂狗 */
void sys_iwdg_app(rt_thread_t thread)
{
    /* 查找线程 指针存储位置 */
    for (uint16_t var = 0; var < SYS_IWDG_DATA_NUM; ++var)
    {
        if (sys_iwdg_data[var].thread == 0)
        {
            sys_iwdg_data[var].thread  = (uint32_t)thread;
            sys_iwdg_data[var].tick_time = rt_tick_get(); /* 存储线程喂狗时间 */
            break;
        }
        else if (sys_iwdg_data[var].thread == (uint32_t)thread)
        {
            sys_iwdg_data[var].tick_time = rt_tick_get(); /* 存储线程喂狗时间 */
            break;
        }
    }
}


/* 获取时间差 (差值为ms级别 由RT_TICK_PER_SECOND决定的) */
uint32_t get_time_difference_ms(uint32_t now_tick, uint32_t last_tick)
{
    if (now_tick >= last_tick)
    {
        return (now_tick - last_tick);
    }
    else
    {
        return (UINT32_MAX - last_tick + now_tick + 1);
    }
}

/* 看门狗管理线程 */
void sys_iwdg_thread_entry(void* parameter)
{
    uint8_t timeout = 0;
    memset(sys_iwdg_data, 0, sizeof(sys_iwdg_data_t));
    while (1)
    {
        for (uint16_t var = 0; var < SYS_IWDG_DATA_NUM; ++var)
        {
            if (sys_iwdg_data[var].thread != 0)
            {
                if (get_time_difference_ms(rt_tick_get(), sys_iwdg_data[var].tick_time) > SYS_IWDG_TIMEOUT)
                {
#if IWDG_PRINTF
                    printf("iwdg_thread_entry():thread timeout : No:%d ,thread_add = 0x%08X ,name = %s\r\n",
                            var,sys_iwdg_data[var].thread, ((rt_thread_t) sys_iwdg_data[var].thread)->name);
#endif
                    timeout = 1;
                }
            }

        }

        if (timeout == 0)
        {
            HAL_IWDG_Refresh(&hiwdg);
        }

        rt_thread_mdelay(SYS_IWDG_TIME);
    }
}

static rt_thread_t sys_iwdg_thread = RT_NULL;

/* 系统看门狗初始化线程 */
int sys_iwdg_thread_init(void)
{
    MX_IWDG_Init();

    sys_iwdg_thread = rt_thread_create("sys_iwdg_thread", sys_iwdg_thread_entry, RT_NULL, IWDG_THREAD_THREAD_STACKSIZE, IWDG_THREAD_THREAD_PRIORITY_LEVEL, IWDG_THREAD_THREAD_SLOT_DURATION);
    if (sys_iwdg_thread != RT_NULL)
    {
        rt_thread_startup(sys_iwdg_thread);
    }
    else
    {
#if IWDG_PRINTF
        printf("sys_iwdg_thread_entry():create thread fail!\n\n");
#endif
        return -1;
    }
    return 1;
}



/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

你可能感兴趣的:(STM32,RTOS,RT-Thread,stm32,嵌入式硬件,单片机)