STM32任务调度

目录

什么是任务调度?

FreeRTOS的任务调度规则是怎样的?

抢占式调度运行过程

时间片调度运行过程

任务的状态

任务综合小实验

实验需求

cubeMX配置


什么是任务调度?

调度器就是使用相关的调度算法来决定当前需要执行的哪个任务。
FreeRTOS 中开启任务调度的函数是 vTaskStartScheduler() ,但在 CubeMX 中被封装为
osKernelStart()

FreeRTOS的任务调度规则是怎样的?

FreeRTOS 是一个实时操作系统,它所奉行的调度规则:
1. 高优先级抢占低优先级任务,系统永远执行最高优先级的任务(即 抢占式调度
2. 同等优先级的任务轮转调度(即 时间片调度
还有一种调度规则是协程式调度,但官方已明确表示不更新,主要是用在小容量的芯片上,用得
也不多。

抢占式调度运行过程

STM32任务调度_第1张图片

Task 1 :玩游戏
Task 2 :老妈喊你吃饭
Task 3 :女朋友喊你看电视
总结:
1. 高优先级任务,优先执行;
2. 高优先级任务不停止,低优先级任务无法执行;
3. 被抢占的任务将会进入就绪态

时间片调度运行过程

STM32任务调度_第2张图片

总结:
1. 同等优先级任务,轮流执行,时间片流转;
2. 一个时间片大小,取决为滴答定时器中断周期;
3. 注意没有用完的时间片不会再使用,下次任务 Task3 得到执行,还是按照一个时间片的时钟
节拍运行

任务的状态

FreeRTOS 中任务共存在 4 种状态:
  • Running 运行态
当任务处于实际运行状态称之为运行态,即 CPU 的使用权被这个任务占用(同一时间仅一个任务
处于运行态)。
  • Ready 就绪态
处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同
优先级或更高优先级的任务正在运行。
  • Blocked 阻塞态
如果一个任务因延时,或等待信号量、消息队列、事件标志组等而处于的状态被称之为阻塞态。
  • Suspended 挂起态
类似暂停,通过调用函数 vTaskSuspend() 对指定任务进行挂起,挂起后这个任务将不被执行,
只有调用函数 xTaskResume() 才可以将这个任务从挂起态恢复。

 

总结:
1. 仅就绪态可转变成运行态
2. 其他状态的任务想运行,必须先转变成就绪态

任务综合小实验

实验需求

创建 4 个任务: taskLED1 taskLED2 taskKEY1 taskKEY2 ,任务要求如下:
taskLED1 :间隔 500ms 闪烁 LED1
taskLED2 :间隔 1000ms 闪烁 LED2
taskKEY1 :如果 taskLED1 存在,则按下 KEY1 后删除 taskLED1 ,否则创建 taskLED1
taskKEY2 :如果 taskLED2 正常运行,则按下 KEY2 后挂起 taskLED2 ,否则恢复 taskLED2

cubeMX配置

STM32任务调度_第3张图片

freertos.c 

void StartTskLED1(void const * argument)
{
  /* USER CODE BEGIN StartTskLED1 */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
    osDelay(500);
  }
  /* USER CODE END StartTskLED1 */
}

/* USER CODE BEGIN Header_StartTskLED2 */
/**
* @brief Function implementing the TskLED2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTskLED2 */
void StartTskLED2(void const * argument)
{
  /* USER CODE BEGIN StartTskLED2 */
  /* Infinite loop */
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
    osDelay(1000);
  }
  /* USER CODE END StartTskLED2 */
}

/* USER CODE BEGIN Header_StartTaskKey1 */
/**
* @brief Function implementing the TaskKey1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskKey1 */
void StartTaskKey1(void const * argument)
{
  /* USER CODE BEGIN StartTaskKey1 */
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET){
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET){
				
				printf("KEY1键被按下\r\n");
				if(TskLED1Handle==NULL){
					printf("任务一不存在,准备创建\r\n");
					osThreadDef(TskLED1, StartTskLED1, osPriorityNormal, 0, 128);
					TskLED1Handle = osThreadCreate(osThread(TskLED1), NULL);
					if(TskLED1Handle!=NULL){
						printf("任务一创建成功\r\n");
					}
				}else{
					printf("任务一删除成功\r\n");
					osThreadTerminate(TskLED1Handle);
					TskLED1Handle = NULL;
				}
				
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
		}	
		
    osDelay(10);
  }
  /* USER CODE END StartTaskKey1 */
}

/* USER CODE BEGIN Header_StartTaskKey2 */
/**
* @brief Function implementing the TaskKey2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskKey2 */
void StartTaskKey2(void const * argument)
{
  /* USER CODE BEGIN StartTaskKey2 */
	static int flag = 0;
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET){
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET){
				
				printf("KEY2键被按下\r\n");
				if(flag==0){
					
					osThreadSuspend(TskLED2Handle);
					printf("任务2已暂停\r\n");
					flag = 1;
				}else{
					osThreadResume(TskLED2Handle);
					printf("任务2已恢复\r\n");
					flag = 0;
				}
				
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
		}	
		
    osDelay(10);
  }
  /* USER CODE END StartTaskKey2 */
}

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