千家信息网

FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍"FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"FreeRTOS实时操作系统空闲任务的阻
千家信息网最后更新 2026年11月02日FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现

这篇文章主要介绍"FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现"文章能帮助大家解决问题。

什么是阻塞延时、为什么需要空闲任务

RTOS中的延时叫阻塞延时,即任务需要延时时,任务会放弃cpu使用权,cpu转而去做其他的事,当任务延时时间到后,任务重新请求获得cpu使用权。
但当所有的任务都处于阻塞后,为了不让cpu空闲没事干就需要一个空闲任务让cpu干活。

空闲任务的实现

空闲任务实现和创建普通任务没区别,空闲任务在调用vTaskStartScheduler函数内部创建,如下

//定义空闲栈 #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE]; //空闲任务任务控制块 TCB_t IdleTaskTCB; //设置空闲任务的参数 void vApplicationGetIdleTaskMemory( TCB_t **ppxIdleTaskTCBBuffer,                                    StackType_t **ppxIdleTaskStackBuffer,                                    uint32_t *pulIdleTaskStackSize ){  *ppxIdleTaskTCBBuffer=&IdleTaskTCB;  *ppxIdleTaskStackBuffer=IdleTaskStack;  *pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;}void vTaskStartScheduler(void){        TCB_t *pxIdleTaskTCBBuffer = NULL;//空闲任务控制块指针        StackType_t *pxIdleTaskStackBuffer = NULL;//空闲任务栈指针        uint32_t ulIdleTaskStackSize;       //空闲任务栈大小                //设置空闲任务参数        vApplicationGetIdleTaskMemory(&pxIdleTaskTCBBuffer,                                                                                                                                &pxIdleTaskStackBuffer,                                                                                                                                &ulIdleTaskStackSize);        //创建空闲任务        xIdleTaskHandle = xTaskCreateStatic((TaskFunction_t)prvIdleTask,                                                                                (char *)"IDLE",                                                                                (uint32_t)ulIdleTaskStackSize,                                                                                (void*)NULL,                                                                                (StackType_t*)pxIdleTaskStackBuffer,                    (TCB_t*)pxIdleTaskTCBBuffer);  //将空闲任务添加到就绪列表  vListInsertEnd(&(pxReadyTasksLists[0]),&(((TCB_t *)pxIdleTaskTCBBuffer)->xStateListItem));        //手动指定第一个要运行的任务        pxCurrentTCB = &Task1TCB;        //启动调度器        if(xPortStartScheduler()!=pdFALSE)        {                //启动成功则不会运行到这里        }}

阻塞延时的实现

阻塞延时需要用xTicksToDelay,这个时TCB中的一个成员,用于记录还要阻塞多久。

typedef struct tskTaskControlBlock{        volatile StackType_t * pxTopOfStack;        ListItem_t xStateListItem;         StackType_t * pxStack; ·        char pcTaskName[configMAX_TASK_NAME_LEN];        TickType_t xTicksToDelay; //用于延时}tskTCB;

所以阻塞延时就是这样实现

void vTaskDelay(const TickType_t xTicksToDelay){          TCB_t *pxTCB = NULL;          pxTCB = pxCurrentTCB;          //设置延时时间          pxTCB->xTicksToDelay = xTicksToDelay;          //进行一次任务切换          taskYIELD();}

由于引入了阻塞延时,所以任务切换函数需要改写,因为当所有任务阻塞后,需要切换至空闲任务运行

void vTaskSwitchContext( void ){   //如果当前时空闲任务,尝试去执行任务1或任务2,如果他们延时时间都没到则继续执行空闲任务        if( pxCurrentTCB == &IdleTaskTCB )        {                        if(Task1TCB.xTicksToDelay == 0)                        {                                  pxCurrentTCB =&Task1TCB;                        }      else if(Task2TCB.xTicksToDelay == 0)                  {                      pxCurrentTCB =&Task2TCB;                  }      else      {          return;      }  } else  //当前任务不是空闲任务会执行到这里 {    //当前任务时任务1或任务2的话,检查另一个任务      //如果另外的任务不在延时中,会切换到该任务      //否则,判断当前任务是否在延时中,是则切换到空闲任务,      //否则,不进行任何切换                 if (pxCurrentTCB == &Task1TCB)                 {                                 if (Task2TCB.xTicksToDelay == 0)                                 {                                                        pxCurrentTCB =&Task2TCB;                                 }                                 else if (pxCurrentTCB->xTicksToDelay != 0)                                 {                                                        pxCurrentTCB = &IdleTaskTCB;                                 }                                 else                                 {                                                        return;                                 }                 }                 else if (pxCurrentTCB == &Task2TCB)                 {                                 if (Task1TCB.xTicksToDelay == 0)                                 {                                         pxCurrentTCB =&Task1TCB;                                 }                                 else if (pxCurrentTCB->xTicksToDelay != 0)                                 {                                         pxCurrentTCB = &IdleTaskTCB;                                 }                                 else                                 {                                         return;                                 }                 } }}

xTicksToDelay 递减

vTaskDelay中设置了xTicksToDelay成员后,是通过SystTick中断来实现递减操作的

void xPortSysTickHandler( void ){ int x = portSET_INTERRUPT_MASK_FROM_ISR(); xTaskIncrementTick(); portCLEAR_INTERRUPT_MASK_FROM_ISR(x);}void xTaskIncrementTick( void ){         TCB_t *pxTCB = NULL;         BaseType_t i = 0;         const TickType_t xConstTickCount = xTickCount + 1;         xTickCount = xConstTickCount;         for (i=0; ixTicksToDelay > 0)         {         pxTCB->xTicksToDelay --; //这里递减         }         }         portYIELD();}

SysTick初始化

//systick控制寄存器#define portNVIC_SYSTICK_CTRL_REG (*((volatile uint32_t *) 0xe000e010 ))//systick重装载寄存器#define portNVIC_SYSTICK_LOAD_REG (*((volatile uint32_t *) 0xe000e014 ))//systick时钟源选择#ifndef configSYSTICK_CLOCK_HZ        #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ    #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )#else    #define portNVIC_SYSTICK_CLK_BIT ( 0 )#endif#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )void vPortSetupTimerInterrupt( void ){    //重装载计数器值        portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;    //设置systick时钟使用内核时钟    //使能systick定时器中断    //使能systick定时器        portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT |        portNVIC_SYSTICK_INT_BIT |        portNVIC_SYSTICK_ENABLE_BIT );}

在FreeRTOSConfig.h中

#define configCPU_CLOCK_HZ (( unsigned long ) 25000000)#define configTICK_RATE_HZ (( TickType_t ) 100)

configSYSTICK_CLOCK_HZ是没有定义的,所以configSYSTICK_CLOCK_HZ使用的是configCPU_CLOCK_HZ

仿真

portCHAR flag1;portCHAR flag2;TaskHandle_t Task1_Handle;StackType_t Task1Stack[128];TCB_t Task1TCB;TaskHandle_t Task2_Handle;StackType_t Task2Stack[128];TCB_t Task2TCB;void Task1_Fntry(void *arg){        while(1)        {                    flag1=1;                  vTaskDelay( 2 );                  flag1=0;                  vTaskDelay( 2 );        }}void Task2_Fntry(void *arg){        while(1)        {                    flag2=1;                  vTaskDelay( 2 );                  flag2=0;                  vTaskDelay( 2 );        }}        int main(void)        {                prvInitialiseTaskLists();                Task1_Handle = xTaskCreateStatic(Task1_Fntry,"task1",128,NULL,Task1Stack,&Task1TCB);                vListInsertEnd(&pxReadyTasksLists[1],&((&Task1TCB)->xStateListItem));                Task2_Handle = xTaskCreateStatic(Task2_Fntry,"task2",128,NULL,Task2Stack,&Task2TCB);                vListInsertEnd(&pxReadyTasksLists[2],&((&Task2TCB)->xStateListItem));                vTaskStartScheduler();                for(;;)                {}        }

可以看到2个task是同步运行的,且延时是20ms

关于"FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

任务 空闲 阻塞 切换 运行 操作系统 实时 系统 时钟 时间 知识 控制 使用权 函数 参数 定时器 寄存器 成员 指针 行业 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技海报 互联网科技公司经营范围 互联网科技公司官网 唐信互联网科技 互联网金融科技创新 互联网科技美容 深圳期待互联网科技 互联网前沿科技 安控科技rtu产品工业互联网 哈尔滨新华互联网科技学院 重庆互联网医院沙龙医盟信息科技 晓花互联网科技有限公司网址 健康食品互联网创新科技园项目 合肥互联网科技公司公章图片 广州千川互联网科技有限公司 黑云互联网科技有限公司 福建互联网展示科技馆设计 互联网界的黑科技 上海万顺科技互联网有限公司招聘 科技和互联网行业的特点 互联网科技企业 小米移动互联网科技园 广州为想互联网科技有限公司 互联网科技官网 天下捷融互联网科技 长亮科技 互联网金融 科技伦理 互联网公司 栖莱科技互联网股份有限公司 互联网科技公司实习生 广东工业互联网大赛深圳学泰科技
0