FreeRTOS实时操作系统(三)任务挂起与恢复

系列文章目录

FreeRTOS实时操作系统(一)RTOS的基本概念

FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库)


文章目录

  • 系列文章目录
  • 前言
  • 任务挂起与恢复
  • 普通挂起恢复实例
  • 中断恢复实例


前言

继续跟着正点原子学习FreeRTOS之任务挂起与恢复


任务挂起与恢复

挂起任务类似暂停任务,不是删除任务。

利用的API函数:
挂起任务:vTaskSuspend()
恢复被挂起的任务:vTaskResume()
在中断中恢复被挂起的任务:xTaskResumeFromISR() (一般带FromISR后缀是在中断函数中专用的API函数)

1.任务挂起:

void vTaskSuspend(TaskHandle_t xTaskToSuspend) 

传回的参数是任务句柄,当是NULL时,挂起当前正在运行的任务。

使用时需将宏 INCLUDE_vTaskSuspend 配置为1。

无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复 。

FreeRTOS实时操作系统(三)任务挂起与恢复_第1张图片
在默认生成的HAl库中是打开的。

2.任务恢复:

void vTaskResume(TaskHandle_t xTaskToResume) 

传回参数是待恢复的任务句柄,任务即使被 vTaskSuspend() 挂起多次,只需在任务中调用 vTakResume() 一次,就可以继续运行,且被恢复的任务会进入就绪态。

使用时,宏INCLUDE_vTaskSuspend必须定义为 1

3.中断中任务恢复:

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)  

参数是待恢复任务的句柄

返回值:

pdTRUE 任务恢复后需要进行任务切换
pdFALSE 任务恢复后不需要进行任务切换

任务切换是指恢复的任务优先级比目前的高,需要调用一个函数来实现抢占。

使用时需要将宏INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须定义为1,HAl库不知道为啥要放在FreeRTOS.h文件,现在还不是很懂。
FreeRTOS实时操作系统(三)任务挂起与恢复_第2张图片

中断服务程序中要调用freeRTOS的API函数,中断优先级不能高于FreeRTOS所管理的最高优先级

普通挂起恢复实例

使用起来很简单:

/* 任务三,判断按键KEY0,按下KEY0删除task1 */
void task3( void * pvParameters )
{
    uint8_t key = 0;
    while(1)
    {
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            printf("挂起task1\r\n");
            vTaskSuspend(task1_handler);
        }else if(key == KEY1_PRES)
        {
            printf("在任务中恢复task1\r\n");
            vTaskResume(task1_handler);
        }
        vTaskDelay(10);
    }
}

中断恢复实例

注意1:
FreeRTOS实时操作系统(三)任务挂起与恢复_第3张图片
上面是FreeRTOS管理的优先级,我们使用的外部中断要比5-15数值之间,优先级上看是小于等于FreeRTOS管理的最高优先级。
官网说明链接:在 ARM Cortex-M Core 上运行 RTOS
FreeRTOS实时操作系统(三)任务挂起与恢复_第4张图片

注意2:
在官网中说明了:
FreeRTOS实时操作系统(三)任务挂起与恢复_第5张图片
HAl库中,自动就是设置对的:
FreeRTOS实时操作系统(三)任务挂起与恢复_第6张图片
下面以正点原子的程序为例子:

void extix_init(void)
{
    GPIO_InitTypeDef gpio_init_struct; 
    key_init();    
    gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct);    /* KEY2配置为下降沿触发中断 */
    HAL_NVIC_SetPriority(KEY2_INT_IRQn, 5, 0);               /* 抢占5,子优先级0 */
    HAL_NVIC_EnableIRQ(KEY2_INT_IRQn);                       /* 使能中断线2 */
}

/**
 * @brief       中断服务程序中需要做的事情
                在HAL库中所有的外部中断服务函数都会调用此函数
 * @param       GPIO_Pin:中断引脚号
 * @retval      无
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(20);      /* 消抖 */
    switch(GPIO_Pin)
    {
        BaseType_t xYieldRequired;//重点
        case KEY2_INT_GPIO_PIN:
            if (KEY2 == 0)
            {
                xYieldRequired = xTaskResumeFromISR(task1_handler);//重点
                printf("在中断中恢复task1\r\n");//重点
                portYIELD_FROM_ISR(xYieldRequired);//重点
             }
            break;
        default : break;
    }
}

用的是按键外部中断的例子,需要注意的是外部中断初始化的时候,中断优先级设置的是5。

这里需要注意,我们需要对返回值判断是否需要切换任务,但是无需我们自己判断:
在这里插入图片描述
如上图所示portYIELD_FROM_ISR()函数会自己判断当前值,是否执行任务切换。

你可能感兴趣的:(FreeRTOS,FreeRTOS,stm32,单片机)