STM32CubeMX学习笔记23---FreeRTOS(任务的挂起与恢复)

1、硬件设置

本实验通过freertos创建两个任务来分别控制LED2和LED3的亮灭,需要用到的硬件资源

  • LED2和LED3指示灯
  • 串口

2、STM32CubeMX设置

根据上一章的步骤创建两个任务:STM32CubeMX学习笔记22---FreeRTOS(任务创建和删除)-CSDN博客

在 Include parameters 中把 vTaskSuspend 和 vTaskResumeFromISR 选择 Enabled 使能。

 生成代码。

3、程序编程

(1)、单个任务挂起

osThreadSuspend

挂起指定任务。被挂起的任务绝不会得到 CPU 的使用权,不管该任务具有什么优先级。

函数osThreadSuspend (osThreadId thread_id)
参数thread_id: 挂起指定任务的任务ID
返回值错误码(osStatus )

 要想使用该函数必须在 Include parameters 中把 vTaskSuspend 选择 Enabled 来使能。

 例:

/*
* 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄
* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么
* 这个句柄可以为 NULL。
*/
osThreadSuspend (LED2Handle);//挂起LED2
(2)、挂起全部任务

osThreadSuspendAll

函数osThreadSuspendAll (void)
参数
返回值错误码(osStatus )
(3)、单个任务恢复

osThreadResume

让挂起的任务重新进入就绪状态,恢复的任务会保留挂起前的状态信息,在恢复的时候根据挂起时的状态继续运行。如果被恢复任务在所有就绪态任务中,处于最高优先级列表的第一位,那么系统将进行任务上下文的切换。可用在中断服务程序中。

函数osThreadResume (osThreadId thread_id)
参数thread_id: 挂起指定任务的任务ID
返回值错误码(osStatus )

 要想在中断服务程序中使用该函数必须在 Include parameters 中把 vTaskResumeFromISR 选择 Enabled 来使能。

例:

osThreadResume (LED2Handle);//恢复LED2
(4)、全部任务恢复

osThreadResumeAll,将所有的任务都恢复。

函数osStatus osThreadResumeAll (void)
参数
返回值错误码

 osThreadResumeAll 函数的使用方法很简单,但是要注意,调用了多少次 osThreadSuspendAll() 函数就必须同样调用多少次 osThreadResumeAll() 函数。

void vDemoFunction( void )
{
    osThreadSuspendAll();
    /* 处理 xxx 代码 */
    osThreadSuspendAll();
    /* 处理 xxx 代码 */
    osThreadSuspendAll();
    /* 处理 xxx 代码 */
 
    osThreadResumeAll(); 
    osThreadResumeAll(); 
    osThreadResumeAll(); 
}
(5)、中断服务中恢复

使用 xTaskResumeFromISR()的时候有几个需要注意的地方:

  • 当函数的返回值为 pdTRUE 时:恢复运行的任务的优先级等于或高于正在运行的任务,表明在中断服务函数退出后必 须进行一次上下文切换 , 使用 portYIELD_FROM_ISR() 进行上下文切换。当函数的返回值为 pdFALSE 时:恢复运行的任务的优先级低于当前正在运行的任务,表明在中断服务函数退出后不需 要进行上下文切换。
  • xTaskResumeFromISR() 通常被认为是一个危险的函数,因为它的调用并非是固定的,中断可能随时来来临。所以 xTaskResumeFromISR()不能用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用 xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量或者任务通知来同步就可以避免这种情况。
void vAnExampleISR( void )
{
    BaseType_t xYieldRequired;

    /* 恢复被挂起的任务 */ 
    xYieldRequired = xTaskResumeFromISR( xHandle ); 

    if ( xYieldRequired == pdTRUE ) 
    { 
        /* 执行上下文切换, ISR 返回的时候将运行另外一个任务 */ 
        portYIELD_FROM_ISR(xYieldRequired ); 
    } 
}
(6)、获取任务状态

osThreadGetState,获取任务当前状态。

函数osThreadGetState(osThreadId thread_id)
参数thread_id: 任务ID
返回值以下值(osThreadState )
/* Thread state returned by osThreadGetState */
typedef enum {
	osThreadRunning   = 0x0,	      /*线程正在查询自身的状态,因此必须正在运行。*/
	osThreadReady     = 0x1 ,		  /* 正在查询的线程位于已读或挂起的就绪列表中。 */
	osThreadBlocked   = 0x2,		  /* 正在查询的线程处于阻止状态。 */
	osThreadSuspended = 0x3,	      /*被查询的线程处于“挂起”状态,或者处于“阻止”状态,超时时间无限长。 */
	osThreadDeleted   = 0x4,		  /* 正在查询的线程已被删除,但其TCB尚未释放。 */   
  osThreadError     = 0x7FFFFFFF
} osThreadState;
(7)、编写程序

在任务函数中编写程序,让LED1计数到10时挂起LED2,当计数到15时恢复LED2.

void LED1_Task1(void const * argument)
{
  /* USER CODE BEGIN LED1_Task1 */
  /* Infinite loop */
	int i=0;
  for(;;)
  {
		HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);   //LED1状态每500s翻转一次
		printf("this LED1 run %d\r\n",i);
		
		if(i++==10)
		{
			osThreadSuspend (LED2Handle);//挂起LED2
			printf("挂起LED2 \r\n");
		}
		
		if(i==15) 
		{
			printf("恢复LED2 \r\n");
			osThreadResume (LED2Handle);//恢复LED2
			
		}
    osDelay(1001);
  }
  /* USER CODE END LED1_Task1 */
}

/* USER CODE END Header_LED2_Task03 */
void LED2_Task03(void const * argument)
{
  /* USER CODE BEGIN LED2_Task03 */
  /* Infinite loop */
	    /* 用于保存上次时间。调用后系统自动更新 */ 
    static portTickType PreviousWakeTime; 
    /* 设置延时时间,将时间转为节拍数 */ 
    const portTickType TimeIncrement = pdMS_TO_TICKS(1000); 

    /* 获取当前系统时间 */ 
    PreviousWakeTime = osKernelSysTick();
	int i=0;
  for(;;)
  {
		 /* 调用绝对延时函数,任务时间间隔为 1000 个 tick */ 
    osDelayUntil( &PreviousWakeTime,TimeIncrement ); 
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);   //LED1状态每500s翻转一次
		printf("this LED2 run %d \r\n",i++);
   // osDelay(900);
  }
  /* USER CODE END LED2_Task03 */
}

4、下载验证

程序编译无误后下载到板子上,可以看到LED1计数到10时挂起LED2,当计数到15时恢复LED2。

注:在不同任务(任务优先级相同)中同时使用同一个中断会导致任务轮流使用该中断,如LED1和LED2都延时1000ms后同时使用printf,则会出现以下情况,即两个任务轮流使用printf,就导致了中间的遗漏了。(优先级不同则不会出现该情况)

5、参考文献

STM32CubeMX学习笔记(28)——FreeRTOS实时操作系统使用(任务管理)_stm32 rtos 任务固定时间运行-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值