当前位置:   article > 正文

[FREERTOS] 任务的创建、删除、调度与状态_void mx_freertos_init(void)

void mx_freertos_init(void)

1.什么是任务?

我的理解是:任务像是进程/线程,创建一个任务就会开辟一个空间,每一个任务都是独立的执行相应的动作互不干扰,就比如玩游戏,陪女朋友,任务通常都会有一个while(1)死循环

2.与任务创建和删除相关的的几个方式

·xTaskCreate()---------------------------动态方式创建任务

·xTaskCreateStatic()-------------------静态方式创建任务

·vTaskDeletc()---------------------------删除任务

动态方式和静态方式的区别

动态方式创建任务的堆栈是由系统分配,静态方式创建任务的堆栈是由用户自己传递,通常情况下都是使用动态方式创建

cubeMX创建任务会自动封装函数用的是osThreadCread,F12进去之后可以看到依然是调用xTaskCreate();

 

xTaskCreate()的原型

 在cubeMX中可以创建队列

 

 这个对应的就是xTaskCreate()原型这个结构体

任务的优先级和之前所学的优先级不一样,之前学的比如滴答定时器优先级,外部中断,串口中断这些优先级都是数值越小优先级越高,任务优先级是数值越大优先级越高

pxVreatedTask:用于返回已创建任务的句柄可以被引用

如果返回pdPASS说明任务创建成功

如果返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY说明任务创建失败

cubuMx封装的函数 比如一个关于led1的任务:

taskLed2Handle = osThreadCreate(osThread(taskLed2), NULL);

也会返回一个句柄,如果taskLed2Handle == NULL就说明任务不存在 

如果taskLed2Handle != NULL则说明任务已经创建成功,任务存在

删除函数的原型

void vTaskDelete(TaskHandle_t xTasjToDelete);

只需要将待删除的任务的句柄传入函数即可以删除这个任务

当传入的参数为NULL时,就是删除当前运行的任务

 3.任务的调度

FreeRtos开启任务调度的函数是:vTaskStarScheduler(); 但是在cubeMX中被封装为osKernelStart();

 

FreeRtos是一个实时操作系统,任务调度的规则是:

1.高优先级任务抢占低优先级任务,系统永远先执行高优先级的任务(抢占式调度)

抢占式调度用更直白的话来说就是:先执行优先级高的,然后执行优先级略低的,如果正在执行优先级低的,这个时候出现了优先级高的任务,就中断优先级低的任务去执行优先级高的任务,如果优先级最高的任务堵塞(比如使用了延时函数)就执行优先级略低的那个任务,等待优先级最高的任务堵塞结束后重新执行优先级最高的任务

2.同等优先级任务轮转制度(时间片制度)

时间片制度用更直白的话来说就是:1ms执行任务一,1ms执行任务二.........每隔1ms执行下一个任务,如果一个任务只执行了0.5ms就被打断了,下一个任务执行完是不会返回上一个任务执行剩下的0.5ms任务

4.任务的状态

任务一共有四种状态

1.Running运行态:

当任务处于实际运行的状态称为运行态,即cpu的使用权被这个任务占用(同一时间仅允许一个任务处于运行态)

2.Ready就绪态:

处于就绪态的任务是指那些能够运行(没有被堵塞和挂起),但是当前没有运行的任务,因为优先级更高或同优先级的任务正在运行

3.Blocked阻塞态

如果一个任务因为延时或者等待信号量,消息队列,时间标志组而处于的状态被称为阻塞态

4.Suspend挂起态

类似于暂停,通过调用函数vTaskSuspend();对指定任务进行挂起,挂起后这个任务将不会被执行,除非使用函数vTaskResume()才可以将这个任务从挂起态恢复

 从图标分析可以知道:

        阻塞态没拌饭直接到运行态,只能先到就绪态再到运行态

        阻塞态、就绪态、运行态可以调用函数直接到挂起态,挂起态调用函数只能到就绪态

 做一个任务的小实验:

创建四个任务,taskLed1,taskLed2,taskKey1,taskKey2要求如下:

taskLed1:Led1按500ms的间隔闪烁

taskLed2:Led2按700ms的间隔闪烁

taskKey1:按下Key1如果taskLed1存在则删除taskLed1这个任务,如果任务不存在就创建taskLed1这个任务

taskKey2:按下Key2后挂起taskLed2,再次按下恢复taskLed2

freertos.c

  1. #include "FreeRTOS.h"
  2. #include "task.h"
  3. #include "main.h"
  4. #include "cmsis_os.h"
  5. /* Private includes ----------------------------------------------------------*/
  6. /* USER CODE BEGIN Includes */
  7. #include <stdio.h>
  8. #include "usart.h"
  9. /*cubeMX配置生成---------------------------------↓*/
  10. /* USER CODE END Includes */
  11. osThreadId taskLed1Handle;
  12. osThreadId taskLed2Handle;
  13. osThreadId taskKey1Handle;
  14. osThreadId taskKey2Handle;
  15. /* Private function prototypes -----------------------------------------------*/
  16. /* USER CODE BEGIN FunctionPrototypes */
  17. /* USER CODE END FunctionPrototypes */
  18. void StartTaskLed1(void const * argument);
  19. void StartTaskLed2(void const * argument);
  20. void StartTaskKey1(void const * argument);
  21. void StartTaskKey2(void const * argument);
  22. void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
  23. /* GetIdleTaskMemory prototype (linked to static allocation support) */
  24. void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
  25. /* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
  26. static StaticTask_t xIdleTaskTCBBuffer;
  27. static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
  28. void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
  29. {
  30. *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  31. *ppxIdleTaskStackBuffer = &xIdleStack[0];
  32. *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  33. /* place for user code */
  34. }
  35. /*cubeMX配置生成---------------------------------↑*/
  36. /*需要手写代码------------------------------------↓*/
  37. void StartTaskLed1(void const * argument)
  38. {
  39. /* USER CODE BEGIN StartTaskLed1 */
  40. /* Infinite loop */
  41. for(;;)
  42. {
  43. HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
  44. osDelay(500);//MS
  45. }
  46. /* USER CODE END StartTaskLed1 */
  47. }
  48. void StartTaskLed2(void const * argument)
  49. {
  50. /* USER CODE BEGIN StartTaskLed2 */
  51. /* Infinite loop */
  52. for(;;)
  53. {
  54. HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
  55. osDelay(700);
  56. }
  57. /* USER CODE END StartTaskLed2 */
  58. }
  59. void StartTaskKey1(void const * argument)
  60. {
  61. /* USER CODE BEGIN StartTaskKey1 */
  62. /* Infinite loop */
  63. for(;;)
  64. {
  65. if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)
  66. {
  67. osDelay(20);
  68. if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)//消抖
  69. {
  70. printf("Key1\r\n");
  71. if(taskLed1Handle == NULL)//Led任务进程不存在,所以创建任务进程
  72. {
  73. printf("chuanjianrenwu1\r\n");
  74. osThreadDef(taskLed1, StartTaskLed1, osPriorityNormal, 0, 128);
  75. taskLed1Handle = osThreadCreate(osThread(taskLed1), NULL);
  76. if(taskLed1Handle != NULL)
  77. printf("success\r\n");
  78. }else if(taskLed1Handle != NULL)//Led任务存在,删除任务
  79. {
  80. printf("delect\r\n");
  81. osThreadTerminate(taskLed1Handle);
  82. taskLed1Handle = NULL;
  83. printf("over\r\n");
  84. }
  85. }
  86. while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);//避免连续按下,等到抬起后才开始下一次扫描
  87. }
  88. osDelay(10);
  89. }
  90. /* USER CODE END StartTaskKey1 */
  91. }
  92. void StartTaskKey2(void const * argument)
  93. {
  94. /* USER CODE BEGIN StartTaskKey2 */
  95. /* Infinite loop */
  96. static int flag = 0;
  97. for(;;)
  98. {
  99. if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)
  100. {
  101. osDelay(20);
  102. if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)//消抖
  103. {
  104. printf("Key2\r\n");
  105. if(flag == 0)
  106. {
  107. osThreadSuspend(taskLed2Handle);//挂起任务2
  108. printf("suspend success\r\n");
  109. flag = 1;
  110. }else if(flag != 0)
  111. {
  112. osThreadResume(taskLed2Handle);//恢复任务2
  113. flag = 0;
  114. printf("resume success\r\n");
  115. }
  116. }
  117. while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET);//避免连续按下,等到抬起后才开始下一次扫描
  118. }
  119. osDelay(10);
  120. }
  121. /* USER CODE END StartTaskKey2 */
  122. }
  123. /*需要手写代码-----------------------------------↑*/
  124. /*cubeMX配置生成---------------------------------↓*/
  125. void MX_FREERTOS_Init(void) {
  126. /* USER CODE BEGIN Init */
  127. /* USER CODE END Init */
  128. /* USER CODE BEGIN RTOS_MUTEX */
  129. /* add mutexes, ... */
  130. /* USER CODE END RTOS_MUTEX */
  131. /* USER CODE BEGIN RTOS_SEMAPHORES */
  132. /* add semaphores, ... */
  133. /* USER CODE END RTOS_SEMAPHORES */
  134. /* USER CODE BEGIN RTOS_TIMERS */
  135. /* start timers, add new ones, ... */
  136. /* USER CODE END RTOS_TIMERS */
  137. /* USER CODE BEGIN RTOS_QUEUES */
  138. /* add queues, ... */
  139. /* USER CODE END RTOS_QUEUES */
  140. /* Create the thread(s) */
  141. /* definition and creation of taskLed1 */
  142. osThreadDef(taskLed1, StartTaskLed1, osPriorityNormal, 0, 128);
  143. taskLed1Handle = osThreadCreate(osThread(taskLed1), NULL);
  144. /* definition and creation of taskLed2 */
  145. osThreadDef(taskLed2, StartTaskLed2, osPriorityNormal, 0, 128);
  146. taskLed2Handle = osThreadCreate(osThread(taskLed2), NULL);
  147. /* definition and creation of taskKey1 */
  148. osThreadDef(taskKey1, StartTaskKey1, osPriorityNormal, 0, 128);
  149. taskKey1Handle = osThreadCreate(osThread(taskKey1), NULL);//创建任务会返回一个句柄,如果是NULL就说明任务没有创建成功
  150. /* definition and creation of taskKey2 */
  151. osThreadDef(taskKey2, StartTaskKey2, osPriorityNormal, 0, 128);
  152. taskKey2Handle = osThreadCreate(osThread(taskKey2), NULL);
  153. /* USER CODE BEGIN RTOS_THREADS */
  154. /* add threads, ... */
  155. /* USER CODE END RTOS_THREADS */
  156. }
  157. /*cubeMX配置生成---------------------------------↑*/

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/398074
推荐阅读
相关标签
  

闽ICP备14008679号