任务的创建与删除

1. 什么是任务?

任务可以理解为进程/线程,创建一个任务,就会在内存开辟一个空间。

比如: 玩游戏、陪女朋友,都可以视为任务 Windows 系统中的 MarkText 、谷歌浏览器、记事本,都是任务。

任务通常都含有 while(1) 死循环。

2. 任务创建与删除相关函数

 任务动态创建与静态创建的区别: 动态创建任务的堆栈由系统分配,而静态创建任务的堆栈由用户自己传递。 通常情况下使用动态方式创建任务。

 参数说明:

1. pvTaskCode:指向任务函数的指针,任务必须实现为永不返回(即连续循环);

2. pcName:任务的名字,主要是用来调试,默认情况下最大长度是16;

3. pvParameters:指定的任务栈的大小;

4. uxPriority:任务优先级,数值越大,优先级越大;

5. pxCreatedTask:用于返回已创建任务的句柄可以被引用。

删除任务:

void vTaskDelete(TaskHandle_t xTaskToDelete);

只需将待删除的任务句柄传入该函数,即可将该任务删除。 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)。

实操创建任务:

 示例代码:

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


void StartTaskLED2(void const * argument)
{
  /* USER CODE BEGIN StartTaskLED2 */
  /* Infinite loop */
  for(;;)
  {
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
    osDelay(1000);
  }
  /* USER CODE END StartTaskLED2 */
}

3、任务调度

什么是任务调度?

调度器就是使用相关的调度算法来决定当前需要执行的哪个任务。

FreeRTOS中开启任务调度的函数是 vTaskStartScheduler() ,但在 CubeMX 中被封装为 osKernelStart() 。

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

FreeRTOS 是一个实时操作系统,

它所奉行的调度规则:

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

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

还有一种调度规则是协程式调度,但官方已明确表示不更新,主要是用在小容量的芯片上,用得 也不多。

抢占式调度运行过程:

 

总结: 1. 高优先级任务,优先执行;

2. 高优先级任务不停止,低优先级任务无法执行;

3. 被抢占的任务将会进入就绪态

时间片调度运行过程:

 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

代码:

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

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

/* 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(taskLED1Handle==NULL)
				{
					printf("task1不存在,准备创建任务1\r\n");
					osThreadDef(taskLED1, StartTaskLED1, osPriorityNormal, 0, 128);
					taskLED1Handle = osThreadCreate(osThread(taskLED1), NULL);
					if(taskLED1Handle!=NULL)
					{
						printf("任务一创建完成\r\n");
					}
				}
				else
					{
						printf("删除任务1\r\n");
						osThreadTerminate(taskLED1Handle);
						taskLED1Handle = NULL;
					}
				while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
			}
		}
			
    osDelay(1);
  }
  /* 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 */
  /* Infinite loop */
	static int flag=0;
  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(taskLED2Handle);
					printf("task2已经暂停\r\n");
					flag=1;
				}
				else
				{
					osThreadResume(taskLED2Handle);
					printf("task2已经恢复\r\n");
					flag=0;
				}
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
		}
    osDelay(1);
  }
  /* USER CODE END StartTaskKey2 */
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值