硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6142|回复: 13
收起左侧

[FreeRTOS教程] 第29章 FreeRTOS独立看门狗监测任务执行状态

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2016-9-10 14:20:25 | 显示全部楼层 |阅读模式



第29章      FreeRTOS独立看门狗监测任务执行状态



      通过前面的几个章节,我们基本已经完成了FreeRTOS所有功能的讲解,本章节为大家介绍一种使用独立看门狗监测任务执行状态的方法,借此为大家提供一种在软件或者硬件死机时,FreeRTOS系统如何保证系统复位的思路。
      本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407以及F429。
29.1 独立看门狗监测任务的实现思路
29.2 实验例程说明
29.3      总结



29.1 独立看门狗监测任务的实现思路


29.1.1  什么是独立看门狗

      假设有一只饥饿的狗正在看守一座房子,而有人要闯入。如果这个强盗的同谋以2分钟的时间间隔不停的向看门狗扔肉。那么这只狗将忙于吃肉而忽视保卫工作,因此将不会犬叫。然而,如果同谋扔完了肉或者由于其它原因忘了喂肉,狗将开始犬叫,从而惊动邻居、房屋主人或者警察。
      嵌入式化的独立看门狗定时器遵循同样的方法。用户需要每隔一段时间就刷新看门狗定时器,否则将导致看门狗定时器溢出。在大多数情况下,看门狗定时器的溢出将使得系统复位。即使经过仔细规划和设计,嵌入式系统也有可能由于出乎预料的问题而死机,看门狗定时器就是用来处理类似情况的,看门狗定时器可用于从这种状态恢复。
      教程使用的STM32F103,STM32F407和STM32F429都自带独立看门狗,使用也比较简单,用户初始化好看门狗,并设置好看门狗溢出时间即可,剩下就是在溢出时间范围内及时喂狗。
      下面就提供一种利用独立看门狗监测多任务的执行状态的思路。

29.1.2 多任务监测实现思路

      为了保证FreeRTOS的所有用户任务都在正常的运行,我们通过独立看门狗的形式来监测,一旦发现有某个任务长时间没有执行,看门狗就会将系统复位。
29.1.JPG

运行条件:
    (1)创建5个用户任务Task1Task2Task3Task4Task5。其中Task5的优先级最高,然后依次是Task4Task3Task2Task1
    (2)任务Task1Task4定期发事件标志给任务Task5,表示任务运行正常。
实现思路:
    (1)喂狗程序放在最高优先级的任务Task5里面,其它的4个任务都定期的向最高优先级任务发送事件标志,只有四个任务都发来了事件标志才进行喂狗。
    (2)看门狗的复位时间设置为多少合适呢?这个要根据四个任务Task1Task4的最大发送事件标志间隔来确定。假设测试发现,最大的发送事件标志时间间隔是由Task4产生的,间隔是6s,我们可以在此基础上再设置一些时间容限,把看门狗的复位时间设置为10s,也就是说,四个任务Task1Task4需要在10s内给任务Task5发送事件标志,让Task5执行喂狗操作,否则看门狗定时器溢出,从而导致系统将复位。
    (3)推荐在最高优先级任务里面实现喂狗,这样才可以保证其它低优先级任务发来了事件标志后,Task5可以及时的喂狗。如果放在一个低优先级的任务里面会存在问题,比如所有的任务都已经发送了表示自己正常运行的事件标志,但是此低优先级任务在执行喂狗程序前被其它高优先级的任务抢占了,造成不能及时喂狗,从而导致系统复位,这种误判断会使得系统不能够正常工作。

按照上面的实现思路,我们在开发板上面实战演练下。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-9-10 14:28:15 | 显示全部楼层
29.2 实验例程说明



29.2.1 STM32F103开发板实验


配套例子:
    V4-335_FreeRTOS实验_独立看门狗监测任务执行状态
实验目的:
    1.     学习独立看门狗监测FreeRTOS任务执行状态。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下后将任务vTaskTaskUserIF延迟20s后执行,从而实现看门狗复位。
    3.     看门狗监测任务执行状态说明:
        (1)  设置看门狗复位时间是10s,如果10s内不喂狗系统复位。
        (2)  使用事件标志组,在最高优先级任务中等待其它所有用户任务发来的事件标志,如果所有任务都发来了事件标志,那么就执行喂狗程序,如果有一个任务10s内没有发来事件标志,那么系统会被复位。
        (3)  简单的说就是为了检测任务的执行状态,我们设置每个任务10s内必须发一次事件标志以此来表示任务在执行。如果10s内有一个任务没有发来消息,系统会被复位。
        (4)  等待事件标志的任务:  
       uxBits= xEventGroupWaitBits(xCreatedEventGroup,
                                                   TASK_BIT_ALL,
                                                   pdTRUE,
                                                   pdTRUE,
                                                 xTicksToWait);
                        其它四个发送事件标志的任务:
                     xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_0);
                 xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_1);
                 xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_2);
                xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_3);
    4.     各个任务实现的功能如下:
              vTaskUserIF任务 :按键消息处理。
              vTaskLED任务    :LED闪烁
              vTaskMsgPro任务:LED闪烁。
                vTaskScan 任务   : 按键扫描
              vTaskStart任务   :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. #endif
  6. #define configUSE_PREEMPTION         1
  7. #define configUSE_IDLE_HOOK          0
  8. #define configUSE_TICK_HOOK          0
  9. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 72000000 )  
  10. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  11. #define configMAX_PRIORITIES         ( 5 )
  12. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  13. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  14. #define configMAX_TASK_NAME_LEN      ( 16 )
  15. #define configUSE_TRACE_FACILITY      1
  16. #define configUSE_16_BIT_TICKS       0
  17. #define configIDLE_SHOULD_YIELD      1
  18. /* Run time and task stats gathering related definitions. */
  19. #define configGENERATE_RUN_TIME_STATS                1
  20. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  21. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  22. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  23. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  24. /* Co-routine definitions. */
  25. #define configUSE_CO_ROUTINES            0
  26. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  27. /* Set the following definitions to 1 to include the API function, or zero
  28. to exclude the API function. */
  29. #define INCLUDE_vTaskPrioritySet          1
  30. #define INCLUDE_uxTaskPriorityGet         1
  31. #define INCLUDE_vTaskDelete               1
  32. #define INCLUDE_vTaskCleanUpResources      0
  33. #define INCLUDE_vTaskSuspend              1
  34. #define INCLUDE_vTaskDelayUntil           1
  35. #define INCLUDE_vTaskDelay                1
  36. /* Cortex-M specific definitions. */
  37. #ifdef __NVIC_PRIO_BITS
  38.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  39.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  40. #else
  41.      #define configPRIO_BITS              4        /* 15 priority levels */
  42. #endif
  43. /* The lowest interrupt priority that can be used in a call to a "set priority"
  44. function. */
  45. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  46. /* The highest interrupt priority that can be used by any interrupt service
  47. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  48. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  49. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  50. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01
复制代码
几个重要选项说明:
1、#define configUSE_PREEMPTION        1
        使能抢占式调度器
2、#define configCPU_CLOCK_HZ      ( ( unsigned long ) 72000000 )   
        系统主频72MHz。
3、#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
        系统时钟节拍1KHz,即1ms。
4、#define configMAX_PRIORITIES          ( 5 )
        定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
5、#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
        定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
6、configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
        定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    (1)使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    (2)对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为015,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    (3)这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY0x01表示用户可以在抢占式优先级为115的中断里面调用FreeRTOSAPI函数,抢占式优先级为0的中断里面是不允许调用的。
    更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
29.2.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
    #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 17 * 1024 ) )
系统栈大小分配:
29.3.jpg

FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.      /* 创建任务通信机制 */
  34.      AppObjCreate();
  35.    
  36.     /* 启动调度,开始执行任务 */
  37.     vTaskStartScheduler();
  38.      /*
  39.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  40.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  41.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  42.      */
  43.      while(1);
  44. }
复制代码
硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
  5. *             全局变量。
  6. *    形    参: 无
  7. *    返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_Init(void)
  11. {
  12.      /*
  13.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  14.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  15.          系统时钟缺省配置为72MHz,如果需要更改,可以修改 system_stm32f10x.c 文件
  16.      */
  17.    
  18.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  19.      bsp_InitUart();    /* 初始化串口 */
  20.      bsp_InitLed();     /* 初始LED指示灯端口 */
  21.      bsp_InitKey();     /* 初始化按键 */
  22. }
复制代码
FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.      xTaskCreate( vTaskScan,              /* 任务函数  */
  34.                  "vTaskScan",             /* 任务名    */
  35.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  36.                  NULL,                    /* 任务参数  */
  37.                  4,                       /* 任务优先级*/
  38.                  &xHandleTaskMsgPro );   /* 任务句柄  */
  39.      xTaskCreate( vTaskStart,             /* 任务函数  */
  40.                  "vTaskStart",            /* 任务名    */
  41.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  42.                  NULL,                    /* 任务参数  */
  43.                  5,                       /* 任务优先级*/
  44.                  &xHandleTaskStart );   /* 任务句柄  */
  45. }
复制代码
FreeRTOS事件标志组创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppObjCreate
  4. *    功能说明: 创建任务通信机制
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppObjCreate (void)
  10. {
  11.      /* 创建事件标志组 */
  12.      xCreatedEventGroup = xEventGroupCreate();
  13.    
  14.      if(xCreatedEventGroup == NULL)
  15.     {
  16.         /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  17.     }
  18. }
复制代码
四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      MSG_T *ptMsg;
  13.      uint8_t ucCount = 0;
  14.      uint8_t ucKeyCode;
  15.      uint8_t pcWriteBuffer[500];
  16. /*
  17. *********************************************************************************************************
  18. *    函 数 名: vTaskTaskUserIF
  19. *    功能说明: 接口消息处理。
  20. *    形    参: pvParameters 是在创建该任务时传递的形参
  21. *    返 回 值: 无
  22. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  23. *********************************************************************************************************
  24. */
  25. static void vTaskTaskUserIF(void *pvParameters)
  26. {
  27.      uint8_t ucKeyCode;
  28.      uint8_t pcWriteBuffer[500];
  29.      const TickType_t xTicksToWait = 20000 / portTICK_PERIOD_MS; /* 最大延迟20s */
  30.     while(1)
  31.     {
  32.          ucKeyCode = bsp_GetKey();
  33.         
  34.          if (ucKeyCode != KEY_NONE)
  35.          {
  36.               switch (ucKeyCode)
  37.               {
  38.                    /* K1键按下 打印任务执行情况 */
  39.                    case KEY_DOWN_K1:         
  40.                        printf("=================================================\\r\\n");
  41.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  42.                        vTaskList((char *)&pcWriteBuffer);
  43.                        printf("%s\\r\\n", pcWriteBuffer);
  44.                   
  45.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  46.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  47.                        printf("%s\\r\\n", pcWriteBuffer);
  48.                        break;
  49.                   
  50.                    /* K2按键按下,让vTaskTaskUserIF任务延迟20s,以实现看门狗复位情况 */
  51.                    case KEY_DOWN_K2:
  52.                        printf("K2按键按下,让vTaskTaskUserIF任务延迟20s,以实现看门狗复位情况\\r\\n");
  53.                        vTaskDelay(xTicksToWait);
  54.                        break;
  55.                   
  56.                    /* 其他的键值不处理 */
  57.                    default:                    
  58.                        break;
  59.               }
  60.          }
  61.         
  62.          /* 发送事件标志,表示任务正常运行 */
  63.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_0);
  64.         
  65.          vTaskDelay(20);
  66.      }
  67. }
  68. /*
  69. *********************************************************************************************************
  70. *    函 数 名: vTaskLED
  71. *    功能说明: LED闪烁
  72. *    形    参: pvParameters 是在创建该任务时传递的形参
  73. *    返 回 值: 无
  74. *   优 先 级: 2
  75. *********************************************************************************************************
  76. */
  77. static void vTaskLED(void *pvParameters)
  78. {
  79.      TickType_t xLastWakeTime;
  80.      const TickType_t xFrequency = 500;
  81.      /* 获取当前的系统时间 */
  82.     xLastWakeTime = xTaskGetTickCount();
  83.    
  84.     while(1)
  85.     {
  86.          bsp_LedToggle(2);
  87.          bsp_LedToggle(3);
  88.         
  89.           /* 发送事件标志,表示任务正常运行 */
  90.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_1);
  91.         
  92.           /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
  93.         vTaskDelayUntil(&xLastWakeTime, xFrequency);
  94.     }
  95. }
  96. /*
  97. *********************************************************************************************************
  98. *    函 数 名: vTaskMsgPro
  99. *    功能说明: LED闪烁
  100. *    形    参: pvParameters 是在创建该任务时传递的形参
  101. *    返 回 值: 无
  102. *   优 先 级: 3
  103. *********************************************************************************************************
  104. */
  105. static void vTaskMsgPro(void *pvParameters)
  106. {
  107.      TickType_t xLastWakeTime;
  108.      const TickType_t xFrequency = 1000;
  109.      /* 获取当前的系统时间 */
  110.     xLastWakeTime = xTaskGetTickCount();
  111.    
  112.     while(1)
  113.     {
  114.          bsp_LedToggle(1);
  115.          bsp_LedToggle(4);
  116.         
  117.          /* 发送事件标志,表示任务正常运行 */
  118.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_2);
  119.         
  120.           /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
  121.         vTaskDelayUntil(&xLastWakeTime, xFrequency);
  122.     }
  123. }
  124. /*
  125. *********************************************************************************************************
  126. *    函 数 名: vTaskScan
  127. *    功能说明: 按键扫描
  128. *    形    参: pvParameters 是在创建该任务时传递的形参
  129. *    返 回 值: 无
  130. *   优 先 级: 4
  131. *********************************************************************************************************
  132. */
  133. static void vTaskScan(void *pvParameters)
  134. {
  135.     while(1)
  136.     {
  137.           /* 按键扫描 */
  138.          bsp_KeyScan();
  139.         
  140.          /* 发送事件标志,表示任务正常运行 */
  141.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_3);
  142.         vTaskDelay(10);
  143.     }
  144. }
  145. /*
  146. *********************************************************************************************************
  147. *    函 数 名: vTaskStart
  148. *    功能说明: 启动任务,等待所有任务发事件标志过来。
  149. *    形    参: pvParameters 是在创建该任务时传递的形参
  150. *    返 回 值: 无
  151. *   优 先 级: 5
  152. *********************************************************************************************************
  153. */
  154. static void vTaskStart(void *pvParameters)
  155. {
  156.      EventBits_t uxBits;
  157.      const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; /* 最大延迟100ms */
  158.    
  159.      /*
  160.        开始执行启动任务主函数前使能独立看门狗。
  161.        设置LSI是128分频,下面函数参数范围0-0xFFF,分别代表最小值3.2ms和最大值13107.2ms
  162.        下面设置的是10s,如果10s内没有喂狗,系统复位。
  163.      */
  164.      bsp_InitIwdg(0xC35);
  165.    
  166.      /* 打印系统开机状态,方便查看系统是否复位 */
  167.      printf("=====================================================\\r\\n");
  168.      printf("=系统开机执行\\r\\n");
  169.      printf("=====================================================\\r\\n");
  170.    
  171.     while(1)
  172.     {
  173.          /* 等待所有任务发来事件标志 */
  174.          uxBits = xEventGroupWaitBits(xCreatedEventGroup, /* 事件标志组句柄 */
  175.                                           TASK_BIT_ALL,    /* 等待TASK_BIT_ALL被设置 */
  176.                                           pdTRUE,          /* 退出前TASK_BIT_ALL被清除,这里是TASK_BIT_ALL
  177. 都被设置才表示“退出”*/
  178.                                          pdTRUE,          /* 设置为pdTRUE表示等待TASK_BIT_ALL都被设置*/
  179.                                           xTicksToWait);   /* 等待延迟时间 */
  180.         
  181.          if((uxBits & TASK_BIT_ALL) == TASK_BIT_ALL)
  182.          {
  183.               IWDG_Feed();
  184.               printf("五个用户任务都正常运行\\r\\n");
  185.          }
  186.          else
  187.          {
  188.               /* 基本是每xTicksToWait进来一次 */
  189.               /* 通过变量uxBits简单的可以在此处检测那个任务长期没有发来运行标志 */
  190.          }
  191.     }
  192. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-9-10 14:33:33 | 显示全部楼层
29.2.2 STM32F407开发板实验


配套例子:
    V5-335_FreeRTOS实验_独立看门狗监测任务执行状态
实验目的:
    1.     学习独立看门狗监测FreeRTOS任务执行状态。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下后将任务vTaskTaskUserIF延迟20s后执行,从而实现看门狗复位。
    3.     看门狗监测任务执行状态说明:
        (1)  设置看门狗复位时间是10s,如果10s内不喂狗系统复位。
        (2)  使用事件标志组,在最高优先级任务中等待其它所有用户任务发来的事件标志,如果所有任务都发来了事件标志,那么就执行喂狗程序,如果有一个任务10s内没有发来事件标志,那么系统会被复位。
        (3)  简单的说就是为了检测任务的执行状态,我们设置每个任务10s内必须发一次事件标志以此来表示任务在执行。如果10s内有一个任务没有发来消息,系统会被复位。
        (4)  等待事件标志的任务:  
                   uxBits= xEventGroupWaitBits(xCreatedEventGroup,
                                                                    TASK_BIT_ALL,
                                                                    pdTRUE,
                                                                    pdTRUE,
                                                                    xTicksToWait);
                    其它四个发送事件标志的任务:
                xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_0);
                xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_1);
                xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_2);
                xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_3);
    4.     各个任务实现的功能如下:
              vTaskUserIF任务 :按键消息处理。
              vTaskLED任务    :LED闪烁
              vTaskMsgPro任务:LED闪烁。
               vTaskScan 任务   : 按键扫描
              vTaskStart任务   :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. /* Ensure stdint is only used by the compiler, and not the assembler. */
  6. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  7. #include <stdint.h>
  8. extern volatile uint32_t ulHighFrequencyTimerTicks;
  9. #endif
  10. #define configUSE_PREEMPTION         1
  11. #define configUSE_IDLE_HOOK          0
  12. #define configUSE_TICK_HOOK          0
  13. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  14. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  15. #define configMAX_PRIORITIES         ( 5 )
  16. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  17. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  18. #define configMAX_TASK_NAME_LEN      ( 16 )
  19. #define configUSE_TRACE_FACILITY      1
  20. #define configUSE_16_BIT_TICKS       0
  21. #define configIDLE_SHOULD_YIELD      1
  22. /* Run time and task stats gathering related definitions. */
  23. #define configGENERATE_RUN_TIME_STATS                1
  24. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  25. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  26. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  27. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  28. /* Co-routine definitions. */
  29. #define configUSE_CO_ROUTINES             0
  30. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  31. /* Set the following definitions to 1 to include the API function, or zero
  32. to exclude the API function. */
  33. #define INCLUDE_vTaskPrioritySet     1
  34. #define INCLUDE_uxTaskPriorityGet         1
  35. #define INCLUDE_vTaskDelete               1
  36. #define INCLUDE_vTaskCleanUpResources 0
  37. #define INCLUDE_vTaskSuspend              1
  38. #define INCLUDE_vTaskDelayUntil           1
  39. #define INCLUDE_vTaskDelay                1
  40. /* Cortex-M specific definitions. */
  41. #ifdef __NVIC_PRIO_BITS
  42.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  43.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  44. #else
  45.      #define configPRIO_BITS              4        /* 15 priority levels */
  46. #endif
  47. /* The lowest interrupt priority that can be used in a call to a "set priority"
  48. function. */
  49. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  50. /* The highest interrupt priority that can be used by any interrupt service
  51. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  52. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  53. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  54. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    0x01
复制代码
几个重要选项说明:
1、#define configUSE_PREEMPTION        1
        使能抢占式调度器
2、#define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )
        系统主频168MHz。
3、#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
        系统时钟节拍1KHz,即1ms。
4、#define configMAX_PRIORITIES          ( 5 )
        定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
5、#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
        定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
6、configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
        定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    (1)使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    (2)对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为015,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    (3)这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY0x01表示用户可以在抢占式优先级为115的中断里面调用FreeRTOSAPI函数,抢占式优先级为0的中断里面是不允许调用的。
    更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
29.4.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
    #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 30 * 1024 ) )
系统栈大小分配:
29.5.jpg

FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.      /* 创建任务通信机制 */
  35.      AppObjCreate();
  36.     /* 启动调度,开始执行任务 */
  37.     vTaskStartScheduler();
  38.      /*
  39.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  40.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  41.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  42.      */
  43.      while(1);
  44. }
复制代码
硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.      bsp_InitUart();    /* 初始化串口 */
  19.      bsp_InitKey();     /* 初始化按键变量 */
  20.      bsp_InitLed();     /* 初始LED指示灯端口 */
  21. }
复制代码
FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.      xTaskCreate( vTaskScan,              /* 任务函数  */
  34.                  "vTaskScan",             /* 任务名    */
  35.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  36.                  NULL,                    /* 任务参数  */
  37.                  4,                       /* 任务优先级*/
  38.                  &xHandleTaskMsgPro );   /* 任务句柄  */
  39.      xTaskCreate( vTaskStart,             /* 任务函数  */
  40.                  "vTaskStart",            /* 任务名    */
  41.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  42.                  NULL,                    /* 任务参数  */
  43.                  5,                       /* 任务优先级*/
  44.                  &xHandleTaskStart );   /* 任务句柄  */
  45. }
复制代码
FreeRTOS事件标志组创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppObjCreate
  4. *    功能说明: 创建任务通信机制
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppObjCreate (void)
  10. {
  11.      /* 创建事件标志组 */
  12.      xCreatedEventGroup = xEventGroupCreate();
  13.    
  14.      if(xCreatedEventGroup == NULL)
  15.     {
  16.         /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  17.     }
  18. }
复制代码
四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      MSG_T *ptMsg;
  13.      uint8_t ucCount = 0;
  14.      uint8_t ucKeyCode;
  15.      uint8_t pcWriteBuffer[500];
  16. /*
  17. *********************************************************************************************************
  18. *    函 数 名: vTaskTaskUserIF
  19. *    功能说明: 接口消息处理。
  20. *    形    参: pvParameters 是在创建该任务时传递的形参
  21. *    返 回 值: 无
  22. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  23. *********************************************************************************************************
  24. */
  25. static void vTaskTaskUserIF(void *pvParameters)
  26. {
  27.      uint8_t ucKeyCode;
  28.      uint8_t pcWriteBuffer[500];
  29.      const TickType_t xTicksToWait = 20000 / portTICK_PERIOD_MS; /* 最大延迟20s */
  30.     while(1)
  31.     {
  32.          ucKeyCode = bsp_GetKey();
  33.         
  34.          if (ucKeyCode != KEY_NONE)
  35.          {
  36.               switch (ucKeyCode)
  37.               {
  38.                    /* K1键按下 打印任务执行情况 */
  39.                    case KEY_DOWN_K1:         
  40.                        printf("=================================================\\r\\n");
  41.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  42.                        vTaskList((char *)&pcWriteBuffer);
  43.                        printf("%s\\r\\n", pcWriteBuffer);
  44.                   
  45.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  46.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  47.                        printf("%s\\r\\n", pcWriteBuffer);
  48.                        break;
  49.                   
  50.                    /* K2按键按下,让vTaskTaskUserIF任务延迟20s,以实现看门狗复位情况 */
  51.                    case KEY_DOWN_K2:
  52.                        printf("K2按键按下,让vTaskTaskUserIF任务延迟20s,以实现看门狗复位情况\\r\\n");
  53.                        vTaskDelay(xTicksToWait);
  54.                        break;
  55.                   
  56.                    /* 其他的键值不处理 */
  57.                    default:                    
  58.                        break;
  59.               }
  60.          }
  61.         
  62.          /* 发送事件标志,表示任务正常运行 */
  63.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_0);
  64.         
  65.          vTaskDelay(20);
  66.      }
  67. }
  68. /*
  69. *********************************************************************************************************
  70. *    函 数 名: vTaskLED
  71. *    功能说明: LED闪烁
  72. *    形    参: pvParameters 是在创建该任务时传递的形参
  73. *    返 回 值: 无
  74. *   优 先 级: 2
  75. *********************************************************************************************************
  76. */
  77. static void vTaskLED(void *pvParameters)
  78. {
  79.      TickType_t xLastWakeTime;
  80.      const TickType_t xFrequency = 500;
  81.      /* 获取当前的系统时间 */
  82.     xLastWakeTime = xTaskGetTickCount();
  83.    
  84.     while(1)
  85.     {
  86.          bsp_LedToggle(2);
  87.          bsp_LedToggle(3);
  88.         
  89.           /* 发送事件标志,表示任务正常运行 */
  90.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_1);
  91.         
  92.           /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
  93.         vTaskDelayUntil(&xLastWakeTime, xFrequency);
  94.     }
  95. }
  96. /*
  97. *********************************************************************************************************
  98. *    函 数 名: vTaskMsgPro
  99. *    功能说明: LED闪烁
  100. *    形    参: pvParameters 是在创建该任务时传递的形参
  101. *    返 回 值: 无
  102. *   优 先 级: 3
  103. *********************************************************************************************************
  104. */
  105. static void vTaskMsgPro(void *pvParameters)
  106. {
  107.      TickType_t xLastWakeTime;
  108.      const TickType_t xFrequency = 1000;
  109.      /* 获取当前的系统时间 */
  110.     xLastWakeTime = xTaskGetTickCount();
  111.    
  112.     while(1)
  113.     {
  114.          bsp_LedToggle(1);
  115.          bsp_LedToggle(4);
  116.         
  117.          /* 发送事件标志,表示任务正常运行 */
  118.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_2);
  119.         
  120.           /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
  121.         vTaskDelayUntil(&xLastWakeTime, xFrequency);
  122.     }
  123. }
  124. /*
  125. *********************************************************************************************************
  126. *    函 数 名: vTaskScan
  127. *    功能说明: 按键扫描
  128. *    形    参: pvParameters 是在创建该任务时传递的形参
  129. *    返 回 值: 无
  130. *   优 先 级: 4
  131. *********************************************************************************************************
  132. */
  133. static void vTaskScan(void *pvParameters)
  134. {
  135.     while(1)
  136.     {
  137.           /* 按键扫描 */
  138.          bsp_KeyScan();
  139.         
  140.          /* 发送事件标志,表示任务正常运行 */
  141.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_3);
  142.         vTaskDelay(10);
  143.     }
  144. }
  145. /*
  146. *********************************************************************************************************
  147. *    函 数 名: vTaskStart
  148. *    功能说明: 启动任务,等待所有任务发事件标志过来。
  149. *    形    参: pvParameters 是在创建该任务时传递的形参
  150. *    返 回 值: 无
  151. *   优 先 级: 5
  152. *********************************************************************************************************
  153. */
  154. static void vTaskStart(void *pvParameters)
  155. {
  156.      EventBits_t uxBits;
  157.      const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; /* 最大延迟100ms */
  158.    
  159.      /*
  160.        开始执行启动任务主函数前使能独立看门狗。
  161.        设置LSI是128分频,下面函数参数范围0-0xFFF,分别代表最小值3.2ms和最大值13107.2ms
  162.        下面设置的是10s,如果10s内没有喂狗,系统复位。
  163.      */
  164.      bsp_InitIwdg(0xC35);
  165.    
  166.      /* 打印系统开机状态,方便查看系统是否复位 */
  167.      printf("=====================================================\\r\\n");
  168.      printf("=系统开机执行\\r\\n");
  169.      printf("=====================================================\\r\\n");
  170.    
  171.     while(1)
  172.     {
  173.          /* 等待所有任务发来事件标志 */
  174.          uxBits = xEventGroupWaitBits(xCreatedEventGroup, /* 事件标志组句柄 */
  175.                                           TASK_BIT_ALL,    /* 等待TASK_BIT_ALL被设置 */
  176.                                           pdTRUE,          /* 退出前TASK_BIT_ALL被清除,这里是TASK_BIT_ALL
  177. 都被设置才表示“退出”*/
  178.                                          pdTRUE,          /* 设置为pdTRUE表示等待TASK_BIT_ALL都被设置*/
  179.                                           xTicksToWait);   /* 等待延迟时间 */
  180.         
  181.          if((uxBits & TASK_BIT_ALL) == TASK_BIT_ALL)
  182.          {
  183.               IWDG_Feed();
  184.               printf("五个用户任务都正常运行\\r\\n");
  185.          }
  186.          else
  187.          {
  188.               /* 基本是每xTicksToWait进来一次 */
  189.               /* 通过变量uxBits简单的可以在此处检测那个任务长期没有发来运行标志 */
  190.          }
  191.     }
  192. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-9-10 14:39:22 | 显示全部楼层
29.2.3 STM32F429开发板实验


配套例子:
    V4-335_FreeRTOS实验_独立看门狗监测任务执行状态
实验目的:
    1.     学习独立看门狗监测FreeRTOS任务执行状态。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.      K2按键按下后将任务vTaskTaskUserIF延迟20s后执行,从而实现看门狗复位。
    3.      看门狗监测任务执行状态说明:
      (1)   设置看门狗复位时间是10s,如果10s内不喂狗系统复位。
      (2)    使用事件标志组,在最高优先级任务中等待其它所有用户任务发来的事件标志,如果所有任务都发来了事件标志,那么就执行喂狗程序,如果有一个任务10s内没有发来事件标志,那么系统会被复位。
      (3)    简单的说就是为了检测任务的执行状态,我们设置每个任务10s内必须发一次事件标志以此来表示任务在执行。如果10s内有一个任务没有发来消息,系统会被复 位。
      (4)    等待事件标志的任务:      
      uxBits= xEventGroupWaitBits(xCreatedEventGroup,
                                                              TASK_BIT_ALL,
                                                             pdTRUE,
                                                             pdTRUE,
                                                             xTicksToWait);
                其它四个发送事件标志的任务:
                  xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_0);
                  xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_1);
                  xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_2);
                  xEventGroupSetBits(xCreatedEventGroup,TASK_BIT_3);
    4.      各个任务实现的功能如下:
              vTaskUserIF任务 :按键消息处理。
              vTaskLED任务    :LED闪烁
              vTaskMsgPro任务:LED闪烁。
              vTaskScan 任务   : 按键扫描
              vTaskStart任务   :启动任务,也是最高优先级任务,这里实现按键扫描。
FreeRTOS的配置:
    FreeRTOSConfig.h文件中的配置如下:
  1. /* Ensure stdint is only used by the compiler, and not the assembler. */
  2. #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
  3. #include <stdint.h>
  4. extern volatile uint32_t ulHighFrequencyTimerTicks;
  5. #endif
  6. #define configUSE_PREEMPTION         1
  7. #define configUSE_IDLE_HOOK          0
  8. #define configUSE_TICK_HOOK          0
  9. #define configCPU_CLOCK_HZ           ( ( unsigned long ) 168000000 )
  10. #define configTICK_RATE_HZ           ( ( TickType_t ) 1000 )
  11. #define configMAX_PRIORITIES         ( 5 )
  12. #define configMINIMAL_STACK_SIZE     ( ( unsigned short ) 128 )
  13. #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
  14. #define configMAX_TASK_NAME_LEN      ( 16 )
  15. #define configUSE_TRACE_FACILITY      1
  16. #define configUSE_16_BIT_TICKS       0
  17. #define configIDLE_SHOULD_YIELD      1
  18. /* Run time and task stats gathering related definitions. */
  19. #define configGENERATE_RUN_TIME_STATS                1
  20. #define configUSE_STATS_FORMATTING_FUNCTIONS         1
  21. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (ulHighFrequencyTimerTicks = 0ul)
  22. #define portGET_RUN_TIME_COUNTER_VALUE()             ulHighFrequencyTimerTicks
  23. //#define portALT_GET_RUN_TIME_COUNTER_VALUE           1
  24. /* Co-routine definitions. */
  25. #define configUSE_CO_ROUTINES            0
  26. #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
  27. /* Set the following definitions to 1 to include the API function, or zero
  28. to exclude the API function. */
  29. #define INCLUDE_vTaskPrioritySet          1
  30. #define INCLUDE_uxTaskPriorityGet         1
  31. #define INCLUDE_vTaskDelete               1
  32. #define INCLUDE_vTaskCleanUpResources      0
  33. #define INCLUDE_vTaskSuspend              1
  34. #define INCLUDE_vTaskDelayUntil           1
  35. #define INCLUDE_vTaskDelay                1
  36. /* Cortex-M specific definitions. */
  37. #ifdef __NVIC_PRIO_BITS
  38.      /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
  39.      #define configPRIO_BITS              __NVIC_PRIO_BITS
  40. #else
  41.      #define configPRIO_BITS              4        /* 15 priority levels */
  42. #endif
  43. /* The lowest interrupt priority that can be used in a call to a "set priority"
  44. function. */
  45. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY              0x0f
  46. /* The highest interrupt priority that can be used by any interrupt service
  47. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
  48. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
  49. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
  50. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY         0x01
复制代码
几个重要选项说明:
1、#define configUSE_PREEMPTION        1
        使能抢占式调度器
2、#define configCPU_CLOCK_HZ      ( ( unsigned long ) 168000000 )
        系统主频168MHz。
3、#define configTICK_RATE_HZ              ( ( TickType_t ) 1000 )
        系统时钟节拍1KHz,即1ms。
4、#define configMAX_PRIORITIES          ( 5 )
        定义可供用户使用的最大优先级数,如果这个定义的是5,那么用户可以使用的优先级号是0,1,2,3,4,不包含5,对于这一点,初学者要特别的注意。
5、#define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 30 * 1024 ) )
        定义堆大小,FreeRTOS内核,用户动态内存申请,任务栈等都需要用这个空间。
6、configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY          0x01
        定义受FreeRTOS管理的最高优先级中断。简单的说就是允许用户在这个中断服务程序里面调用FreeRTOS的API的最高优先级。为了进一步说明这个宏定义的的作用,解释如下:
    (1)使用CM内核的MCU,官方强烈建议将NVIC的优先级分组配置为全抢占式优先级,全部配置为抢占式优先级的好处就是方便管理。
    (2)对于STM32来说,设置NVIC的优先级分组为4时,NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4)就是全部配置为抢占式优先级。又因为STM32的优先级设置仅使用CM内核8bit中的高4bit,即只能区分2^4 = 16种优先级。因此当优先级分组设置为4的时候可供用户选择抢占式优先级为015,共16个优先级,配置为0表示最高优先级,配置为15表示最低优先级,不存在子优先级。
    (3)这里配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY0x01表示用户可以在抢占式优先级为115的中断里面调用FreeRTOSAPI函数,抢占式优先级为0的中断里面是不允许调用的。
    更多关于这个参数说明请参看第12章。
FreeRTOS任务调试信息(按K1按键,串口打印):
29.6.jpg

上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
    #definetskBLOCKED_CHAR          ( 'B' )  任务阻塞
    #definetskREADY_CHAR           ( 'R' ) 任务就绪
    #definetskDELETED_CHAR           ( 'D' )  任务删除
    #definetskSUSPENDED_CHAR   ( 'S' ) 任务挂起
程序设计:
任务栈大小分配:
    vTaskUserIF任务   :2048字节
    vTaskLED任务     :2048字节
    vTaskMsgPro任务 :2048字节
    vTaskStart任务    :2048字节
    任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
    #defineconfigTOTAL_HEAP_SIZE        ( ( size_t )( 30 * 1024 ) )
系统栈大小分配:
29.7.jpg

FreeROTS初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.      /*
  12.        在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
  13.        这样做的好处是:
  14.        1. 防止执行的中断服务程序中有FreeRTOS的API函数。
  15.        2. 保证系统正常启动,不受别的中断影响。
  16.        3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
  17.        在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
  18.        和cpsie i是等效的。
  19.      */
  20.      __set_PRIMASK(1);
  21.    
  22.      /* 硬件初始化 */
  23.      bsp_Init();
  24.    
  25.      /* 1. 初始化一个定时器中断,精度高于滴答定时器中断,这样才可以获得准确的系统信息 仅供调试目的,实际项
  26.            目中不要使用,因为这个功能比较影响系统实时性。
  27.         2. 为了正确获取FreeRTOS的调试信息,可以考虑将上面的关闭中断指令__set_PRIMASK(1); 注释掉。
  28.      */
  29.      vSetupSysInfoTest();
  30.    
  31.      /* 创建任务 */
  32.      AppTaskCreate();
  33.    
  34.      /* 创建任务通信机制 */
  35.      AppObjCreate();
  36.     /* 启动调度,开始执行任务 */
  37.     vTaskStartScheduler();
  38.      /*
  39.        如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
  40.        heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
  41.        #define configTOTAL_HEAP_SIZE        ( ( size_t ) ( 17 * 1024 ) )
  42.      */
  43.      while(1);
  44. }
复制代码
硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  17.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  18.    
  19.      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
  20.      bsp_InitUart();    /* 初始化串口 */
  21.      bsp_InitKey();     /* 初始化按键变量 */
  22.      bsp_InitExtIO();   /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
  23.      bsp_InitLed();     /* 初始LED指示灯端口 */
  24. }
复制代码
FreeRTOS任务创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskCreate
  4. *    功能说明: 创建应用任务
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppTaskCreate (void)
  10. {
  11.     xTaskCreate( vTaskTaskUserIF,   /* 任务函数  */
  12.                  "vTaskUserIF",     /* 任务名    */
  13.                  512,               /* 任务栈大小,单位word,也就是4字节 */
  14.                  NULL,              /* 任务参数  */
  15.                  1,                 /* 任务优先级*/
  16.                  &xHandleTaskUserIF );  /* 任务句柄  */
  17.    
  18.    
  19.      xTaskCreate( vTaskLED,           /* 任务函数  */
  20.                  "vTaskLED",         /* 任务名    */
  21.                  512,                /* 任务栈大小,单位word,也就是4字节 */
  22.                  NULL,               /* 任务参数  */
  23.                  2,                  /* 任务优先级*/
  24.                  &xHandleTaskLED ); /* 任务句柄  */
  25.    
  26.      xTaskCreate( vTaskMsgPro,            /* 任务函数  */
  27.                  "vTaskMsgPro",           /* 任务名    */
  28.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  29.                  NULL,                    /* 任务参数  */
  30.                  3,                       /* 任务优先级*/
  31.                  &xHandleTaskMsgPro );  /* 任务句柄  */
  32.    
  33.      xTaskCreate( vTaskScan,              /* 任务函数  */
  34.                  "vTaskScan",             /* 任务名    */
  35.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  36.                  NULL,                    /* 任务参数  */
  37.                  4,                       /* 任务优先级*/
  38.                  &xHandleTaskMsgPro );   /* 任务句柄  */
  39.      xTaskCreate( vTaskStart,             /* 任务函数  */
  40.                  "vTaskStart",            /* 任务名    */
  41.                  512,                     /* 任务栈大小,单位word,也就是4字节 */
  42.                  NULL,                    /* 任务参数  */
  43.                  5,                       /* 任务优先级*/
  44.                  &xHandleTaskStart );   /* 任务句柄  */
  45. }
复制代码
FreeRTOS事件标志组创建:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppObjCreate
  4. *    功能说明: 创建任务通信机制
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void AppObjCreate (void)
  10. {
  11.      /* 创建事件标志组 */
  12.      xCreatedEventGroup = xEventGroupCreate();
  13.    
  14.      if(xCreatedEventGroup == NULL)
  15.     {
  16.         /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
  17.     }
  18. }
复制代码
四个FreeRTOS任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: vTaskTaskUserIF
  4. *    功能说明: 接口消息处理。
  5. *    形    参: pvParameters 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  8. *********************************************************************************************************
  9. */
  10. static void vTaskTaskUserIF(void *pvParameters)
  11. {
  12.      MSG_T *ptMsg;
  13.      uint8_t ucCount = 0;
  14.      uint8_t ucKeyCode;
  15.      uint8_t pcWriteBuffer[500];
  16. /*
  17. *********************************************************************************************************
  18. *    函 数 名: vTaskTaskUserIF
  19. *    功能说明: 接口消息处理。
  20. *    形    参: pvParameters 是在创建该任务时传递的形参
  21. *    返 回 值: 无
  22. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
  23. *********************************************************************************************************
  24. */
  25. static void vTaskTaskUserIF(void *pvParameters)
  26. {
  27.      uint8_t ucKeyCode;
  28.      uint8_t pcWriteBuffer[500];
  29.      const TickType_t xTicksToWait = 20000 / portTICK_PERIOD_MS; /* 最大延迟20s */
  30.     while(1)
  31.     {
  32.          ucKeyCode = bsp_GetKey();
  33.         
  34.          if (ucKeyCode != KEY_NONE)
  35.          {
  36.               switch (ucKeyCode)
  37.               {
  38.                    /* K1键按下 打印任务执行情况 */
  39.                    case KEY_DOWN_K1:         
  40.                        printf("=================================================\\r\\n");
  41.                        printf("任务名      任务状态 优先级   剩余栈 任务序号\\r\\n");
  42.                        vTaskList((char *)&pcWriteBuffer);
  43.                        printf("%s\\r\\n", pcWriteBuffer);
  44.                   
  45.                        printf("\\r\\n任务名       运行计数         使用率\\r\\n");
  46.                        vTaskGetRunTimeStats((char *)&pcWriteBuffer);
  47.                        printf("%s\\r\\n", pcWriteBuffer);
  48.                        break;
  49.                   
  50.                    /* K2按键按下,让vTaskTaskUserIF任务延迟20s,以实现看门狗复位情况 */
  51.                    case KEY_DOWN_K2:
  52.                        printf("K2按键按下,让vTaskTaskUserIF任务延迟20s,以实现看门狗复位情况\\r\\n");
  53.                        vTaskDelay(xTicksToWait);
  54.                        break;
  55.                   
  56.                    /* 其他的键值不处理 */
  57.                    default:                    
  58.                        break;
  59.               }
  60.          }
  61.         
  62.          /* 发送事件标志,表示任务正常运行 */
  63.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_0);
  64.         
  65.          vTaskDelay(20);
  66.      }
  67. }
  68. /*
  69. *********************************************************************************************************
  70. *    函 数 名: vTaskLED
  71. *    功能说明: LED闪烁
  72. *    形    参: pvParameters 是在创建该任务时传递的形参
  73. *    返 回 值: 无
  74. *   优 先 级: 2
  75. *********************************************************************************************************
  76. */
  77. static void vTaskLED(void *pvParameters)
  78. {
  79.      TickType_t xLastWakeTime;
  80.      const TickType_t xFrequency = 500;
  81.      /* 获取当前的系统时间 */
  82.     xLastWakeTime = xTaskGetTickCount();
  83.    
  84.     while(1)
  85.     {
  86.          bsp_LedToggle(2);
  87.          bsp_LedToggle(3);
  88.         
  89.           /* 发送事件标志,表示任务正常运行 */
  90.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_1);
  91.         
  92.           /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
  93.         vTaskDelayUntil(&xLastWakeTime, xFrequency);
  94.     }
  95. }
  96. /*
  97. *********************************************************************************************************
  98. *    函 数 名: vTaskMsgPro
  99. *    功能说明: LED闪烁
  100. *    形    参: pvParameters 是在创建该任务时传递的形参
  101. *    返 回 值: 无
  102. *   优 先 级: 3
  103. *********************************************************************************************************
  104. */
  105. static void vTaskMsgPro(void *pvParameters)
  106. {
  107.      TickType_t xLastWakeTime;
  108.      const TickType_t xFrequency = 1000;
  109.      /* 获取当前的系统时间 */
  110.     xLastWakeTime = xTaskGetTickCount();
  111.    
  112.     while(1)
  113.     {
  114.          bsp_LedToggle(1);
  115.          bsp_LedToggle(4);
  116.         
  117.          /* 发送事件标志,表示任务正常运行 */
  118.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_2);
  119.         
  120.           /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
  121.         vTaskDelayUntil(&xLastWakeTime, xFrequency);
  122.     }
  123. }
  124. /*
  125. *********************************************************************************************************
  126. *    函 数 名: vTaskScan
  127. *    功能说明: 按键扫描
  128. *    形    参: pvParameters 是在创建该任务时传递的形参
  129. *    返 回 值: 无
  130. *   优 先 级: 4
  131. *********************************************************************************************************
  132. */
  133. static void vTaskScan(void *pvParameters)
  134. {
  135.     while(1)
  136.     {
  137.           /* 按键扫描 */
  138.          bsp_KeyScan();
  139.         
  140.          /* 发送事件标志,表示任务正常运行 */
  141.          xEventGroupSetBits(xCreatedEventGroup, TASK_BIT_3);
  142.         vTaskDelay(10);
  143.     }
  144. }
  145. /*
  146. *********************************************************************************************************
  147. *    函 数 名: vTaskStart
  148. *    功能说明: 启动任务,等待所有任务发事件标志过来。
  149. *    形    参: pvParameters 是在创建该任务时传递的形参
  150. *    返 回 值: 无
  151. *   优 先 级: 5
  152. *********************************************************************************************************
  153. */
  154. static void vTaskStart(void *pvParameters)
  155. {
  156.      EventBits_t uxBits;
  157.      const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; /* 最大延迟100ms */
  158.    
  159.      /*
  160.        开始执行启动任务主函数前使能独立看门狗。
  161.        设置LSI是128分频,下面函数参数范围0-0xFFF,分别代表最小值3.2ms和最大值13107.2ms
  162.        下面设置的是10s,如果10s内没有喂狗,系统复位。
  163.      */
  164.      bsp_InitIwdg(0xC35);
  165.    
  166.      /* 打印系统开机状态,方便查看系统是否复位 */
  167.      printf("=====================================================\\r\\n");
  168.      printf("=系统开机执行\\r\\n");
  169.      printf("=====================================================\\r\\n");
  170.    
  171.     while(1)
  172.     {
  173.          /* 等待所有任务发来事件标志 */
  174.          uxBits = xEventGroupWaitBits(xCreatedEventGroup, /* 事件标志组句柄 */
  175.                                           TASK_BIT_ALL,    /* 等待TASK_BIT_ALL被设置 */
  176.                                           pdTRUE,          /* 退出前TASK_BIT_ALL被清除,这里是TASK_BIT_ALL
  177. 都被设置才表示“退出”*/
  178.                                          pdTRUE,          /* 设置为pdTRUE表示等待TASK_BIT_ALL都被设置*/
  179.                                           xTicksToWait);   /* 等待延迟时间 */
  180.         
  181.          if((uxBits & TASK_BIT_ALL) == TASK_BIT_ALL)
  182.          {
  183.               IWDG_Feed();
  184.               printf("五个用户任务都正常运行\\r\\n");
  185.          }
  186.          else
  187.          {
  188.               /* 基本是每xTicksToWait进来一次 */
  189.               /* 通过变量uxBits简单的可以在此处检测那个任务长期没有发来运行标志 */
  190.          }
  191.     }
  192. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2016-9-10 14:40:11 | 显示全部楼层
29.3 总结

        本章节为大家介绍了一种使用独立看门狗监测任务执行状态的方法,主要目的是拓展一下大家的思
路,如果有更好的思路也可以尝试一下。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

0

主题

1

回帖

16

积分

新手上路

积分
16
发表于 2018-4-16 17:51:45 | 显示全部楼层
请教一个问题,这种思路是:除了监控任务外的其他任务定时给监控任务发标志。那么可能会遇到一种情况,某个任务可能就是单纯的等待接收消息队列或者其他内核对象,此时可以选择等待不限时,一直等下去,但现在由于需要定期给监控任务发标志,则需要刻意的设置一个超时时间了。当然,设置一个超时时间也未尝不可,与不设超时时间相比,就是在超时的时候需要内核处理一次,当然也无大碍。不知道有没有更好的看门狗算法可以分享?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
发表于 2018-4-16 17:59:48 | 显示全部楼层
素心之剑 发表于 2018-4-16 17:51
请教一个问题,这种思路是:除了监控任务外的其他任务定时给监控任务发标志。那么可能会遇到一种情况,某个 ...

暂无。
回复

使用道具 举报

21

主题

61

回帖

124

积分

初级会员

积分
124
发表于 2020-5-22 16:28:29 | 显示全部楼层
对监测任务Task5的优先级我觉得应该设置为最低:
假设Task5优先级最低,如果有高优先级任务抢占导致Task5,导致其在规定时间内不能喂狗,这本身就说明了系统已经发生异常。因为我觉得系统在正常运行条件下就应该能保证低优先级的Task5在规定时间内执行喂狗。
不知道我这样的看法对不对?
回复

使用道具 举报

21

主题

61

回帖

124

积分

初级会员

积分
124
发表于 2020-5-22 16:30:06 | 显示全部楼层
感谢分享!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
发表于 2020-5-22 16:57:53 | 显示全部楼层
zhumx 发表于 2020-5-22 16:28
对监测任务Task5的优先级我觉得应该设置为最低:
假设Task5优先级最低,如果有高优先级任务抢占导致Task5 ...

相对来说,配置为最高更好些。
回复

使用道具 举报

0

主题

4

回帖

4

积分

新手上路

积分
4
发表于 2020-9-28 15:05:12 | 显示全部楼层
zhumx 发表于 2020-5-22 16:28
对监测任务Task5的优先级我觉得应该设置为最低:
假设Task5优先级最低,如果有高优先级任务抢占导致Task5 ...

从功能安全的角度来说,看门狗的目的就是监控运行的异常,同意你的看法,将喂狗的动作放在最低任务中操作,这样保证监控最低任务的运行。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
发表于 2020-9-28 15:10:38 | 显示全部楼层
dujieyou 发表于 2020-9-28 15:05
从功能安全的角度来说,看门狗的目的就是监控运行的异常,同意你的看法,将喂狗的动作放在最低任务中操作 ...

举一个最常用的案例,比如我们做一个GUI任务,如果你的喂狗任务比GUI任务还低,这个任务得到执行的概率是大大降低,因为GUI操作期间不会占用大量CPU执行时间,比他低的得到执行的几乎很小。特别是一些复杂界面的操作。
回复

使用道具 举报

0

主题

4

回帖

4

积分

新手上路

积分
4
发表于 2020-9-30 17:47:30 | 显示全部楼层
eric2013 发表于 2020-9-28 15:10
举一个最常用的案例,比如我们做一个GUI任务,如果你的喂狗任务比GUI任务还低,这个任务得到执行的概率是 ...

如果因为你的gui的执行导致最低任务的无法正常运行,本身就说明问题,如果你的GUItask对于功能安全分解下来是有要求的,那就必须要监控你的GUI的运行状态,那看门狗的喂狗动作就得低于你的GUI,特别是对于汽车行业来说,
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
发表于 2020-9-30 19:55:33 | 显示全部楼层
dujieyou 发表于 2020-9-30 17:47
如果因为你的gui的执行导致最低任务的无法正常运行,本身就说明问题,如果你的GUItask对于功能安全分解下 ...

不是无法执行,而是这段时间像DAM2D等各种加速,我们全部统一都塞到这个任务里面,以此来达到性能最大化。像单片机去处理复杂GUI,很难做到时间确定性,这些低优先级任务抖动性很大,而且随着工程的复杂,看门狗放在低优先级任务设计难度会非常大,大部分项目完全没有必要为个看门狗做这么大牺牲,所以不推荐放在最低优先级。

放在高优先级任务里面的话,低优先级任务发送喂狗消息,高优先级任务如果处于非就绪态就可以立即得到执行。这种方式下,程序的设计的复杂度要低很多。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-1 02:49 , Processed in 0.244097 second(s), 34 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表