中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

FreeRTOS實時操作系統空閑任務的阻塞延時怎么實現

發布時間:2022-04-07 13:43:01 來源:億速云 閱讀:361 作者:iii 欄目:開發技術

這篇文章主要介紹“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; 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實時操作系統空閑任務的阻塞延時怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

中卫市| 彰化市| 永康市| 类乌齐县| 呼图壁县| 离岛区| 巴中市| 宜昌市| 育儿| 赤峰市| 澄城县| 宁海县| 塔城市| 桐庐县| 云浮市| 浪卡子县| 普兰店市| 涟源市| 东兴市| 三穗县| 鹤庆县| 张家口市| 滕州市| 东平县| 黄梅县| 珠海市| 枞阳县| 德惠市| 西藏| 亚东县| 常宁市| 高雄县| 梁山县| 靖边县| 长宁区| 江口县| 绥化市| 保康县| 旬阳县| 新竹市| 石景山区|