劉火良FreeRTOS內核實現與應用學習之7——任務延時列表

????????在《劉火良FreeRTOS內核實現與應用學習之6——多優先級》的基礎上:關鍵是添加了全局變量:xNextTaskUnblockTime? ,與延時列表(xDelayedTaskList1、xDelayedTaskList2)來高效率的實現延時。

? ? ? ? 以前需要在掃描就緒列表中所有任務的xTicksToDelay值,進行任務就緒與否的操作;現在修改之后只需根據xNextTaskUnblockTime 值判斷延時列表中的任務是否就緒,進行相應的操作;

重要數據結構及數據

0.? 全局變量? xNextTaskUnblockTime?? ??? ?

位置:在task.c文件中定義;靜態變量;

static volatile TickType_t xNextTaskUnblockTime?? ??? ?= ( TickType_t ) 0U;

1.? 全局變量 任務延時列表

位置:在task.c文件中定義;靜態變量;

static List_t xDelayedTaskList1;? ?//xTickCount沒有溢出時,使用一個列表
static List_t xDelayedTaskList2;? ?//xTickCount? ? ? ?溢出時,使用另外一個列表

static List_t * volatile pxDelayedTaskList;???//xTickCount沒有溢出時,使用一個列表
static List_t * volatile pxOverflowDelayedTaskList;? ?//xTickCount? ? ? ?溢出時,使用另外一個列表

a. 列表中的每一個節點代表了正在延時的任務;

b. 且節點按照延時時間大小做升序排列;

c. 當時基中斷(SysTick中斷)來臨時,就用系統時基計數器的值xTickCount 與xNextTaskUnblockTime? ?進行比較:相等則任務就緒;否則,更新系統時基計數器xTickCount,任務切換;

有關任務操作重要函數

1.? 任務延時列表初始化

/* 初始化任務相關的列表 */
void prvInitialiseTaskLists( void )
{
? ? UBaseType_t uxPriority;
? ??
? ? /* 初始化就緒列表 */
? ? for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
?? ?{
?? ??? ?vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
?? ?}
? ??
? ? vListInitialise( &xDelayedTaskList1 );
?? ?vListInitialise( &xDelayedTaskList2 );
? ??
? ? pxDelayedTaskList = &xDelayedTaskList1;
?? ?pxOverflowDelayedTaskList = &xDelayedTaskList2;

}

2. 修改延時函數

void vTaskDelay( const TickType_t xTicksToDelay )
{
? ? TCB_t *pxTCB = NULL;
? ??
? ? /* 獲取當前任務的TCB */
? ? pxTCB = pxCurrentTCB;
? ??
? ? /* 設置延時時間 */
? ? //pxTCB->xTicksToDelay = xTicksToDelay;
? ??
? ? /* 將任務插入到延時列表 */
? ? prvAddCurrentTaskToDelayedList( xTicksToDelay );

? ??
? ? /* 任務切換 */
? ? taskYIELD();
}

實現將任務插入延時列表;

在?prvAddCurrentTaskToDelayedList函數中實現
a. 把當前任務從就緒列表中移除;

? ? /* 將任務從就緒列表中移除 */
?? ?if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
?? ?{
?? ??? ?/* 將任務在優先級位圖中對應的位清除 */
? ? ? ? portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
?? ?}

b. 計算xNextTaskUnblockTime? 值:

? ? /* 計算延時到期時,系統時基計數器xTickCount的值是多少 */
? ? xTimeToWake= xConstTickCount + xTicksToWait;

c. 把延時任務插入延時列表(xDelayedTaskList1 或者 xDelayedTaskList2)中

i. 由于《節點按照延時時間大小做升序排列》,在插入前需要設置節點的xItemValue值:用于幫助節點做順序排列;

?/* 將延時到期的值設置為節點的排序值 */
? ? listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );

ii. 根據剛才計算的?xTimeToWake是否溢出,決定把延時任務是放到延時列表(非溢出xDelayedTaskList1 或者 溢出xDelayedTaskList2)中;

? ? /* 溢出 */
? ? if( xTimeToWake < xConstTickCount )
? ? {
? ? ? ? vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
? ? }
? ? else /* 沒有溢出 */
? ? {

? ? ? ? vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );

? ? ? ? /* 更新下一個任務解鎖時刻變量xNextTaskUnblockTime的值 */
? ? ? ? if( xTimeToWake < xNextTaskUnblockTime )
? ? ? ? {
? ? ? ? ? ? xNextTaskUnblockTime = xTimeToWake;
? ? ? ? }
? ? }

?iii. 更新xNextTaskUnblockTime值:

? ? ? ? /* 更新下一個任務解鎖時刻變量xNextTaskUnblockTime的值 */
? ? ? ? if( xTimeToWake < xNextTaskUnblockTime )
? ? ? ? {
? ? ? ? ? ? xNextTaskUnblockTime = xTimeToWake;
? ? ? ? }

重要函數 :prvAddCurrentTaskToDelayedList
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait )
{TickType_t xTimeToWake;/* 獲取系統時基計數器xTickCount的值 */const TickType_t xConstTickCount = xTickCount;/* 將任務從就緒列表中移除 */if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ){/* 將任務在優先級位圖中對應的位清除 */portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );}/* 計算延時到期時,系統時基計數器xTickCount的值是多少 */xTimeToWake = xConstTickCount + xTicksToWait;/* 將延時到期的值設置為節點的排序值 */listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );/* 溢出 */if( xTimeToWake < xConstTickCount ){vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );}else /* 沒有溢出 */{vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );/* 更新下一個任務解鎖時刻變量xNextTaskUnblockTime的值 */if( xTimeToWake < xNextTaskUnblockTime ){xNextTaskUnblockTime = xTimeToWake;}}	
}

3. 修改xTaskIncrementTick函數

實現如下功能:

a. 更新xTickCount 值;為何不直接加一?

?? ?const TickType_t xConstTickCount = xTickCount + 1;
?? ?xTickCount = xConstTickCount;

b. 如果 xConstTickCount溢出,則切換延時列表;

?? ?/* 如果xConstTickCount溢出,則切換延時列表 */
?? ?if( xConstTickCount == ( TickType_t ) 0U )
?? ?{
?? ??? ?taskSWITCH_DELAYED_LISTS();
?? ?}

重要宏代碼?taskSWITCH_DELAYED_LISTS

/*?
?* 當系統時基計數器溢出的時候,延時列表pxDelayedTaskList 和
?* pxOverflowDelayedTaskList要互相切換
?*/
#define taskSWITCH_DELAYED_LISTS()\
{\
?? ?List_t *pxTemp;\
?? ?pxTemp = pxDelayedTaskList;\
?? ?pxDelayedTaskList = pxOverflowDelayedTaskList;\
?? ?pxOverflowDelayedTaskList = pxTemp;\
?? ?xNumOfOverflows++;\
?? ?prvResetNextTaskUnblockTime();\
}

當前的延時列表指針切換到溢出延時列表中;

?c. 最近的延時任務延時到期:

直接通過比較xConstTickCount與xNextTaskUnblockTime,大于則進去看誰到期了,無需遍歷所有的;

/* 最近的延時任務延時到期 */
?? ?if( xConstTickCount >= xNextTaskUnblockTime )
?? ?{
?? ??? ?for( ;; )
?? ??? ?{
?? ??? ??? ?if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
?? ??? ??? ?{
?? ??? ??? ??? ?/* 延時列表為空,設置xNextTaskUnblockTime為可能的最大值 */
?? ??? ??? ??? ?xNextTaskUnblockTime = portMAX_DELAY;
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?else /* 延時列表不為空 */
?? ??? ??? ?{
?? ??? ??? ??? ?pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
?? ??? ??? ??? ?xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );

?? ??? ??? ??? ?/* 直到將延時列表中所有延時到期的任務移除才跳出for循環 */
? ? ? ? ? ? ? ? if( xConstTickCount < xItemValue )
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?xNextTaskUnblockTime = xItemValue;
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}

?? ??? ??? ??? ?/* 將任務從延時列表移除,消除等待狀態 */
?? ??? ??? ??? ?( void ) uxListRemove( &( pxTCB->xStateListItem ) );

?? ??? ??? ??? ?/* 將解除等待的任務添加到就緒列表 */
?? ??? ??? ??? ?prvAddTaskToReadyList( pxTCB );
?? ??? ??? ?}
?? ??? ?}
?? ?}/* xConstTickCount >= xNextTaskUnblockTime */

代碼框架為死循環<用于部分遍歷延時到期任務>,設置條件跳出;

i.? 根據列表中的節點計數器判斷,延時列表是否為空,空則跳出;

ii. 編列列表中的任務節點的xItemValue(節點此值是升序的),若xConstTickCount < xItemValue:?表示此任務延時未到,跳出死循環;

若xConstTickCount > xItemValue:?表示此任務延時到,進行如下操作:

  • 從當前延時任務從延時列表中移除;
  • 將當前延時任務加到就緒列表中;

d. 任務切換;

xTaskIncrementTick函數由時基函數調用:

時基函數SysTick中斷服務函數:xPortSysTickHandler

位置:在port.c文件中定義;

/*
*************************************************************************
*                             SysTick中斷服務函數
*************************************************************************
*/
void xPortSysTickHandler( void )
{/* 關中斷 */vPortRaiseBASEPRI();/* 更新系統時基 */xTaskIncrementTick();/* 開中斷 */vPortClearBASEPRIFromISR();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/78788.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/78788.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/78788.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

圖像預處理-插值方法

一.插值方法 當我們對圖像進行縮放或旋轉等操作時&#xff0c;需要在新的像素位置上計算出對應的像素值。 而插值算法的作用就是根據已知的像素值來推測未知位置的像素值。 1.1 最近鄰插值 CV2.INTER_NEAREST 其為 warpAffine() 函數的參數 flags 的其一&#xff0c;表示最近…

智能配電保護:公共建筑安全的新 “防火墻”

安科瑞劉鴻鵬 摘要 隨著城市建筑體量的不斷增長和電氣設備的廣泛使用&#xff0c;現代建筑大樓的用電安全問題日益突出。傳統配電方式面臨監測盲區多、響應滯后、火災隱患難發現等問題。為提升建筑電氣系統的安全性和智能化水平&#xff0c;智慧用電系統應運而生。本文結合安…

如何解決DDoS攻擊問題 ?—專業解決方案深度分析

本文深入解析DDoS攻擊面臨的挑戰與解決策略&#xff0c;提供了一系列防御技術和實踐建議&#xff0c;幫助企業加強其網絡安全架構&#xff0c;有效防御DDoS攻擊。從攻擊的識別、防范措施到應急響應&#xff0c;為網絡安全工作者提供了詳細的操作指引。 DDoS攻擊概覽&#xff1a…

構建靈活的接口抽象層:支持多種后端數據存取的實戰指南

構建靈活的接口抽象層:支持多種后端數據存取的實戰指南 引言 在現代軟件開發中,數據存取成為業務邏輯的核心組成部分。然而,由于后端數據存儲方式的多樣性(如關系型數據庫、NoSQL數據庫和文件存儲),如何設計一套能夠適配多種后端數據存取的接口抽象層,成為技術團隊關注…

OpenCV 圖形API(23)圖像和通道合成

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 1.算法描述 在OpenCV的G-API模塊中&#xff0c;圖像和通道合成&#xff08;composition&#xff09;函數允許用戶對圖像進行復雜的操作&#xff0c;如合并…

帝國cms導航淘客新聞下載多功能網站源碼 二次元風格自適應附教程

一、本模板使用帝國cms7.5 utf8版本&#xff0c;二次元導航新聞下載工具淘客自適應響應式帝國cms模板。 1、網站后臺有3個系統模型&#xff0c;新聞系統模型&#xff0c;下載系統模型&#xff0c;導航系統模型&#xff0c;商城系統模型&#xff0c;可以根據自己的需求不同&…

本地部署大模型(ollama模式)

分享記錄一下本地部署大模型步驟。 大模型應用部署可以選擇 ollama 或者 LM Studio。本文介紹ollama本地部署 ollama官網為&#xff1a;https://ollama.com/ 進入官網&#xff0c;下載ollama。 ollama是一個模型管理工具和平臺&#xff0c;它提供了很多國內外常見的模型&…

C# virtual 和 abstract 詳解

簡介 在 C# 中&#xff0c;virtual 和 abstract 關鍵字都用于面向對象編程中的繼承和多態&#xff0c;它們主要用于方法、屬性和事件的定義&#xff0c;但在用法上存在一些重要的區別。 virtual 關鍵字 virtual 表示可重寫的方法&#xff0c;但可以提供默認實現&#xff0c;…

自動駕駛的數據集以及yolov8和yolop

項目背景 網絡全部是分割了沒有檢測。 自動駕駛的車道線和可行駛區域在數據集中的表示 自動駕駛系統中的車道線和可行駛區域的表示方式主要有以下幾種&#xff1a; 基于幾何模型&#xff1a;使用幾何模型來描述車道線和可行駛區域的形狀和位置&#xff0c;例如直線、曲線、多…

Oracle DROP、TRUNCATE 和 DELETE 原理

在 Oracle 11g 中&#xff0c;DROP、TRUNCATE 和 DELETE 是三種不同的數據清理操作&#xff0c;它們的底層原理和適用場景有顯著差異 1. DELETE 的原理 類型&#xff1a;DML&#xff08;數據操作語言&#xff09; 功能&#xff1a;逐行刪除表中符合條件的數據&#xff0c;保留…

PCIe 5.0光學SSD原型問世!

近日&#xff0c;Kioxia Corporation&#xff08;鎧俠&#xff09;、AIO Core Co., Ltd. 和 Kyocera Corporation&#xff08;京瓷&#xff09;聯合宣布成功開發了一款支持 PCIe 5.0 接口的光學 SSD 原型。該技術旨在通過光接口替換傳統的電接口&#xff0c;從而顯著增加計算設…

SQL 查詢中涉及的表及其作用說明

SQL 查詢中涉及的表及其作用說明&#xff1a; 涉及的數據庫表 表名別名/用途關聯關系dbo.s_orderSO&#xff08;主表&#xff09;存儲訂單主信息&#xff08;訂單號、日期、客戶等&#xff09;dbo.s_orderdetailSoD&#xff08;訂單明細&#xff09;通過 billid SO.billid 關…

C++學習之金融類安全傳輸平臺項目git

目錄 1.知識點概述 2.版本控制工具作用 3.git和SVN 4.git介紹 5.git安裝 6.工作區 暫存區 版本庫概念 7.本地文件添加到暫存區和提交到版本庫 8.文件的修改和還原 9.查看提交的歷史版本信息 10.版本差異比較 11.刪除文件 12.本地版本管理設置忽略目錄 13.遠程git倉…

【HCIP】GRE VPN實驗筆記

一、實驗拓撲 二、實驗要求 1、按照圖示配置IP地址 2、在R1和R3上配置默認路由使公網區域互通 3、在R1和R3上配置GRE VPN&#xff0c;使兩端私網能夠互相訪問&#xff0c;Tunnel口IP地址如圖 4、在R1和R3上配置RIPv2或者ospf或者靜態&#xff0c;來傳遞兩端私網路由 三、實…

大模型——Llama Stack快速入門 部署構建AI大模型指南

Llama Stack快速入門 部署構建AI大模型指南 介紹 Llama Stack 是一組標準化和有主見的接口,用于如何構建規范的工具鏈組件(微調、合成數據生成)和代理應用程序。我們希望這些接口能夠在整個生態系統中得到采用,這將有助于更輕松地實現互操作性。 Llama Stack 定義并標準化…

ALOPS智能化運維管理平臺

AIOps&#xff08;Artificial Intelligence for IT Operations&#xff09;即智能運維&#xff0c;是將人工智能技術應用于 IT 運維管理領域&#xff0c;以實現自動化、智能化的運維決策和管理。以下是關于 AIOps 的詳細介紹&#xff1a; 核心能力 數據收集與整合&#xff1a…

C語言超詳細指針知識(二)

在上一篇有關指針的博客中&#xff0c;我們介紹了指針的基礎知識&#xff0c;如&#xff1a;內存與地址&#xff0c;解引用操作符&#xff0c;野指針等&#xff0c;今天我們將更加深入的學習指針的其他知識。 1.指針的使用和傳址調用 1.1strlen的模擬實現 庫函數strlen的功能是…

一種替代DOORS在WORD中進行需求管理的方法 (二)

一、前景 參考&#xff1a; 一種替代DOORS在WORD中進行需求管理的方法&#xff08;基于WORD插件的應用&#xff09;_doors aspice-CSDN博客 二、界面和資源 WORD2013/WORD2016 插件 【已使用該工具通過第三方功能安全產品認證】&#xff1a; 1、 核心功能 1、需求編號和跟…

設計模式 Day 6:深入講透觀察者模式(真實場景 + 回調機制 + 高級理解)

觀察者模式&#xff08;Observer Pattern&#xff09;是一種設計結構中最實用、最常見的行為模式之一。它的魅力不僅在于簡潔的“一對多”事件推送能力&#xff0c;更在于它的解耦能力、模塊協作設計、實時響應能力。 本篇作為 Day 6&#xff0c;將帶你從理論、底層機制到真實…

文獻總結:AAAI2025-UniV2X-End-to-end autonomous driving through V2X cooperation

UniV2X 一、文章基本信息二、文章背景三、UniV2X框架1. 車路協同自動駕駛問題定義2. 稀疏-密集混合形態數據3. 交叉視圖數據融合&#xff08;智能體融合&#xff09;4. 交叉視圖數據融合&#xff08;車道融合&#xff09;5. 交叉視圖數據融合&#xff08;占用融合&#xff09;6…