FreeRTOS学习第6篇–任务状态挂起恢复删除等操作

2024-01-07 22:46:09

FreeRTOS学习第6篇–任务状态挂起恢复删除等操作

本文目标:学习与使用FreeRTOS中的几项操作,有挂起恢复删除等操作。

按照本文的描述,应该可以跑通实验并举一反三。

本文实验条件:拥有C语言基础,装有编译和集成的开发环境,比如:Keil uVision5

任务的状态

任务的状态

  • 就绪态(Ready):任务已经准备好运行,只等待调度器分配CPU时间片给它。就绪态的任务按照优先级排列在就绪列表中,优先级越高的任务越靠前。
  • 运行态(Running):任务正在执行,占用CPU资源。同一时刻,只有一个任务处于运行态,除非使用多核处理器。
  • 阻塞态(Blocked):任务因为等待某个事件(如信号量、队列、延时等)而无法运行,被放入阻塞列表中。阻塞态的任务不会占用CPU资源,也不会参与调度。当等待的事件发生时,任务会从阻塞列表中移出,重新进入就绪列表,等待调度。比如:使用函数vTaskDelay()或vTaskDelayUntil()就是进入阻塞状态,或者xSemaphoreTake()等函数也是进阻塞状态。
  • 挂起态(Suspended):任务被主动暂停,无论是否有事件发生,都不会运行,被放入挂起列表中。挂起态的任务不会占用CPU资源,也不会参与调度。只有当任务被主动恢复时,才会从挂起列表中移出,重新进入就绪列表,等待调度。比如:直接调用vTaskSuspend()函数。
  • 删除态:任务被主动删除,不再存在于任何列表中,也不会再运行。删除态的任务的内存资源会被释放,不会占用任何资源。

设计实验

本次实验就是设计一个实验,来实现任务的一些操作,有删除任务,恢复任务。在本次实验中,将使用两个按键,一个按键用作删除任务,一个按键用作挂起和恢复。基于这个实验情况,我在我的硬件平台进行实验。

IRReceiver_Task任务相关代码片段

void IRReceiver_Task(void * pvParameters)
{
        int bRunning;
        uint8_t dev, data;
        OLED_Init();
        IRReceiver_Init();

		while(1)
		{
			OLED_ShowString(0,0,"IR Receiver: ",16);
			OLED_ShowString(0,16,"Device  Data",16);
			if (!IRReceiver_Read(&dev, &data))
			{
					OLED_ShowString(0, 32, "                ",16);
					OLED_ShowNum(0,32,dev,4,16);
					OLED_ShowNum(64,32,data,4,16);
					OLED_ShowString(0, 48, "                ",16);
					OLED_ShowString(0,48,"Key name: ",16);
					OLED_ShowString(80,48,(u8 *)IRReceiver_CodeToString(data),16);
				  // 某个按键值  "1"  
					if(data == 48)
					{
						// 创建闪灯任务
						if( ledTaskHandle == NULL)
						{
							ledTaskHandle = osThreadNew(LedTask, NULL, &ledTask_attributes);
							bRunning = 1;
						}
						else
						{
							/* 要么suspend要么resume */
							if (bRunning)
							{
								vTaskSuspend(ledTaskHandle);  // 挂起LED任务
								bRunning = 0;
							}
							else
							{
								vTaskResume(ledTaskHandle);   // 恢复LED任务
								bRunning = 1;
							}
						}
					}
					// 某个按键 "2"
					if(data == 24) 
					{
						// 删除LED 任务
						if(ledTaskHandle != NULL)
						{
							vTaskDelete(ledTaskHandle);
							ledTaskHandle = NULL;  // 进行清理操作,否则会莫名奇妙的进入HardFault_Handler错误
						}
					}
					
			}
			OLED_Refresh(); // 刷新屏幕
		}

}
xTaskCreate( IRReceiver_Task, "IRReceiver_Task", configMINIMAL_STACK_SIZE, NULL, osPriorityNormal, NULL );
osThreadId_t ledTaskHandle;
const osThreadAttr_t ledTask_attributes = {
  .name = "ledTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
void LedTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
		HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
		HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
	  mdelay(100);
  }
  /* USER CODE END StartDefaultTask */
}

实验现象

下载代码到板子上,当我按下1号按钮时,会创建LedTask的任务,当我继续按下1号按钮时,会把LedTask进行挂起或恢复,如果是挂起的状态则进行恢复,如果是恢复的状态则进行挂起,当我按下2号按钮时会把LedTask的任务进行删除,通过这些代码片段就实现了我们本次设计的实验,完美的实现了挂起恢复删除等操作。

本文中使用的测试工程

文章来源:https://blog.csdn.net/weixin_44317448/article/details/135445248
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。