iis服务器助手广告广告
返回顶部
首页 > 资讯 > 操作系统 >FreeRTOS实时操作系统空闲任务的阻塞延时实现
  • 744
分享到

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

2024-04-02 19:04:59 744人浏览 泡泡鱼
摘要

目录什么是阻塞延时、为什么需要空闲任务空闲任务的实现阻塞延时的实现xTicksToDelay 递减SysTick初始化仿真什么是阻塞延时、为什么需要空闲任务 RTOS中的延时叫阻塞延

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

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; i<configMAX_PRIORITIES; i++)
	 {
	 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &pxReadyTasksLists[i] ) );
	 if (pxTCB->xTicksToDelay > 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实时操作系统空闲任务的阻塞延时实现的详细内容,更多关于FreeRTOS空闲任务阻塞延时的资料请关注编程网其它相关文章!

--结束END--

本文标题: FreeRTOS实时操作系统空闲任务的阻塞延时实现

本文链接: https://www.lsjlt.com/news/145213.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • FreeRTOS实时操作系统空闲任务的阻塞延时实现
    目录什么是阻塞延时、为什么需要空闲任务空闲任务的实现阻塞延时的实现xTicksToDelay 递减SysTick初始化仿真什么是阻塞延时、为什么需要空闲任务 RTOS中的延时叫阻塞延...
    99+
    2022-11-13
  • FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现
    这篇文章主要介绍“FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现”文章能帮助大家解决问题。...
    99+
    2023-06-29
  • freertos实时操作系统空闲任务阻塞延时示例解析
    目录前言空闲任务阻塞延时SysTick实验现象前言 阻塞态:如果一个任务当前正在等待某个外部事件,则称它处于阻塞态。 rtos中的延时叫阻塞延时,即任务需要延时的时候,会放弃CPU的...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的任务是什么
    这篇文章主要介绍了FreeRTOS实时操作系统的任务是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇FreeRTOS实时操作系统的任务是什么文章都会有所收获,下面我们一起来看看吧。1. 任务和协程(Co-r...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的任务通知怎么实现
    这篇文章主要介绍“FreeRTOS实时操作系统的任务通知怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“FreeRTOS实时操作系统的任务通知怎么实现”文章能帮助大家解决问题。前言注:本文介绍...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的任务通知方法
    目录前言1.发送通知-方法11.1函数描述1.2参数描述1.3返回值2.发送通知-方法22.1函数描述2.2参数描述2.3用法举例3.获取通知3.1函数描述3.2参数描述3.3返回值...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的任务概要讲解
    目录1. 任务和协程(Co-routines)1.1任务的特性1.2任务概要2. 任务状态3.任务优先级4.实现一个任务5.空闲任务和空闲任务钩子(idle task和Idle Ta...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的任务创建与任务切换
    目录任务控制块数据结构任务创建函数定义就绪表就绪表初始化启动调度器任务切换    任务控制块数据结构 任务控制块数据结构在task.c声明 typedef str...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的任务创建和删除
    目录前言 1.任务创建1.1函数描述1.2参数描述1.3返回值1.4用法举例2.任务删除2.1任务描述2.2参数描述前言  在FreeRTOS移植到Cortex-...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的任务应用函数详解
    目录1.获取任务系统状态1.1函数描述1.2参数描述1.3返回值1.4用法举例2.获取当前任务句柄2.1函数描述2.2返回值3.获取空闲任务句柄3.1函数描述3.2返回值4.获取任务...
    99+
    2022-11-13
  • FreeRTOS实时操作系统多任务管理基础知识
    目录什么是多任务系统?FreeRTOS  任务与协程1.任务(Task) 的特性2.协程(Co-routine)的特性任务状态运行态就绪态阻塞态挂起态任务优先级任务实现任务...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的任务怎么创建和删除
    本文小编为大家详细介绍“FreeRTOS实时操作系统的任务怎么创建和删除”,内容详细,步骤清晰,细节处理妥当,希望这篇“FreeRTOS实时操作系统的任务怎么创建和删除”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的任务应用函数是什么
    本文小编为大家详细介绍“FreeRTOS实时操作系统的任务应用函数是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“FreeRTOS实时操作系统的任务应用函数是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的多优先级实现
    目录如何实现任务多优先级软件通用方法和硬件指令方法如何实现任务多优先级 FreeRTOS中,数字优先级越小,逻辑优先级也越小,空闲任务优先级为0.List_t pxReadyTask...
    99+
    2022-11-13
  • FreeRTOS实时操作系统的多优先级怎么实现
    这篇文章主要介绍“FreeRTOS实时操作系统的多优先级怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“FreeRTOS实时操作系统的多优先级怎么实现”文章能帮助大家解决问题。如何实现任务多优...
    99+
    2023-06-29
  • FreeRTOS实时操作系统多任务管理基础知识有哪些
    本篇内容主要讲解“FreeRTOS实时操作系统多任务管理基础知识有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“FreeRTOS实时操作系统多任务管理基础知识有哪些”吧!RTOS 系统的核心...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的内存管理分析
    目录前言1.heap_1.c功能简介:2.heap_2.c功能简介:3.heap_3.c功能简介:4.heap_4.c功能简介:5.heap_5.c(V8.1.0新增)前言 本文介绍...
    99+
    2022-11-13
  • FreeRTOS实时操作系统内核配置的方法
    今天小编给大家分享一下FreeRTOS实时操作系统内核配置的方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。FreeRTO...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的内存怎么管理
    这篇“FreeRTOS实时操作系统的内存怎么管理”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“FreeRTOS实时操作系统的...
    99+
    2023-06-29
  • FreeRTOS实时操作系统队列的API函数讲解
    目录前言1.获取队列入队信息数目1.1函数描述1.2参数描述2.获取队列的空闲数目2.1函数描述2.2参数描述3.删除队列3.1函数描述3.2参数描述4.复位队列4.1函数描述4.2...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作