系列文章目录
FreeRTOS实时操作系统(一)RTOS的基本概念
FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库)
文章目录
- 系列文章目录
- 前言
- 任务挂起与恢复
- 普通挂起恢复实例
- 中断恢复实例
前言
继续跟着正点原子学习FreeRTOS之任务挂起与恢复
任务挂起与恢复
挂起任务类似暂停任务,不是删除任务。
利用的API函数:
 挂起任务:vTaskSuspend()
 恢复被挂起的任务:vTaskResume()
 在中断中恢复被挂起的任务:xTaskResumeFromISR() (一般带FromISR后缀是在中断函数中专用的API函数)
1.任务挂起:
void vTaskSuspend(TaskHandle_t xTaskToSuspend) 
传回的参数是任务句柄,当是NULL时,挂起当前正在运行的任务。
使用时需将宏 INCLUDE_vTaskSuspend 配置为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的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管理的优先级,我们使用的外部中断要比5-15数值之间,优先级上看是小于等于FreeRTOS管理的最高优先级。
 官网说明链接:在 ARM Cortex-M Core 上运行 RTOS
 
注意2:
 在官网中说明了:
 
 HAl库中,自动就是设置对的:
 
 下面以正点原子的程序为例子:
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()函数会自己判断当前值,是否执行任务切换。



















