FreeRTOS 簡單內核實現8 時間片輪詢

来源:https://www.cnblogs.com/lc-guo/p/18250554
-Advertisement-
Play Games

0、思考與回答 0.1、思考一 為什麼要增加時間片輪詢? 目前的 RTOS 內核已經支持搶占優先順序,即高優先順序的任務會搶占低優先順序的任務得到執行,但是對於同等優先順序的任務,如果不支持時間片輪詢,則只能有一個任務運行,並且由於優先順序相同所以除延時阻塞到期外也不會發生任務調度,因此需要增加時間片輪詢保證 ...


0、思考與回答

0.1、思考一

為什麼要增加時間片輪詢?

目前的 RTOS 內核已經支持搶占優先順序,即高優先順序的任務會搶占低優先順序的任務得到執行,但是對於同等優先順序的任務,如果不支持時間片輪詢,則只能有一個任務運行,並且由於優先順序相同所以除延時阻塞到期外也不會發生任務調度,因此需要增加時間片輪詢保證同等優先順序的任務能得到輪流執行

1、內核程式修改

1.1、xTaskIncrementTick( )

在該函數中除了任務延時阻塞時間到期產生任務調度外,增加支持時間片輪詢的任務切換,具體如下所示

/*task.c*/
BaseType_t xTaskIncrementTick(void)
{
	// 省略未修改的程式
	......
#if((configUSE_PREEMPTION == 1) && (configUSE_TIME_SLICING == 1))
	// 支持時間片輪詢
	if(listCURRENT_LIST_LENGTH(&(pxReadyTasksLists[pxCurrentTCB->uxPriority])) > 1)
	{
		xSwitchRequired = pdTRUE;
	}
#endif
	return xSwitchRequired;
}
/* FreeRTOSConfig.h */
// 支持時間片輪詢
#define configUSE_TIME_SLICING                  1

1.2、原理

假設當前系統中只存在兩個優先順序相同的任務,時間片輪詢任務切換流程如下

xTaskIncrementTick()
-> vTaskSwitchContext()
-> taskSELECT_HIGHEST_PRIORITY_TASK()
-> listGET_OWNER_OF_NEXT_ENTRY()

當進入滴答定時器中斷服務函數時,如果發現就緒鏈表數組中的某個鏈表中鏈表項的數量大於 1 ,則表示該優先順序下有不止一個任務,此時就可以產生任務調度

當有任務調度產生的時候,會調用 vTaskSwitchContext()taskSELECT_HIGHEST_PRIORITY_TASK() 兩個函數尋找當前的最高優先順序任務,但是系統中只有兩個優先順序相同的任務,因此最高優先順序仍然沒變,但是在這個優先順序下返回的任務卻變成了下一個

為什麼呢?

關鍵在於 listGET_OWNER_OF_NEXT_ENTRY() 函數,這個巨集函數每次調用會獲取鏈表中下一個鏈表項的 pvOwner 參數,由於是雙向鏈表,因此會不斷的迴圈鏈表中的鏈表項(兩個同等優先順序的任務),每次發生任務調度就會切換一次任務,所以就實現了時間片輪詢

3、實驗

3.1、測試

參考 FreeRTOS 簡單內核實現6 優先順序 "3.1、測試" 小節內容,將兩個任務的優先順序修改為一樣,然後在兩個任務中均使用軟體延時模擬任務連續運行,具體程式如下所示

/* main.c */
/* USER CODE BEGIN Includes */
#include "FreeRTOS.h"
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
// 軟體延時
void delay(uint32_t count)
{
	for(;count!=0;count--);
}

TaskHandle_t Task1_Handle;
#define TASK1_STACK_SIZE                    128
StackType_t Task1Stack[TASK1_STACK_SIZE];
TCB_t Task1TCB;
UBaseType_t Task1Priority = 2;

TaskHandle_t Task2_Handle;
#define TASK2_STACK_SIZE                    128
StackType_t Task2Stack[TASK2_STACK_SIZE];
TCB_t Task2TCB;
UBaseType_t Task2Priority = 2;

// 任務 1 入口函數
void Task1_Entry(void *parg)
{
	for(;;)
	{
		HAL_GPIO_TogglePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin);
		delay(10000000);
	}
}
// 任務 2 入口函數
void Task2_Entry(void *parg)
{
	for(;;)
	{
		HAL_GPIO_TogglePin(ORANGE_LED_GPIO_Port, ORANGE_LED_Pin);
		delay(10000000);
	}
}
/* USER CODE END PV */

/* USER CODE BEGIN 2 */
// 創建任務 1 和 2
Task1_Handle = xTaskCreateStatic((TaskFunction_t)Task1_Entry,
								 (char *)"Task1",
								 (uint32_t)TASK1_STACK_SIZE,
								 (void *)NULL,
								 (UBaseType_t)Task1Priority,
								 (StackType_t *)Task1Stack,
								 (TCB_t *)&Task1TCB);
														
Task2_Handle = xTaskCreateStatic((TaskFunction_t)Task2_Entry,
								 (char *)"Task2",
								 (uint32_t)TASK2_STACK_SIZE,
								 (void *) NULL,
								 (UBaseType_t)Task2Priority,
								 (StackType_t *)Task2Stack,
								 (TCB_t *)&Task2TCB );
// 啟動任務調度器,永不返回
vTaskStartScheduler();
/* USER CODE END 2 */

configUSE_TIME_SLICING 調整為 0 ,然後燒錄程式,仍然使用邏輯分析儀捕獲兩個 LED 的引腳電平,結果如下圖所示

可以發現在不啟用時間片輪詢時,由於兩個任務優先順序一致,並且兩個任務模擬連續運行,因此只有任務 Task2 被運行 (為什麼是 Task2 ?)

configUSE_TIME_SLICING 調整為 1,然後燒錄程式,仍然使用邏輯分析儀捕獲兩個 LED 的引腳電平,結果如下圖所示

可以發現,對於優先順序相同且連續運行的任務幾乎是在同時運行,其實是因為每個時間片(滴答定時器間隔)都發生了一次任務調度

3.2、待改進

當前 RTOS 簡單內核已實現的功能有

  1. 靜態方式創建任務
  2. 手動切換任務
  3. 臨界段保護
  4. 任務阻塞延時
  5. 支持任務優先順序
  6. 阻塞鏈表
  7. 時間片輪詢

後續 RTOS 簡單內核可以增加

  1. 任務間通信機制
    1. 信號量
    2. 互斥鎖
    3. 消息隊列
    4. ......
  2. 其他功能
    1. 軟體定時器
    2. ......

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SQLSugar是什麼 **1. 輕量級ORM框架,專為.NET CORE開發人員設計,它提供了簡單、高效的方式來處理資料庫操作,使開發人員能夠更輕鬆地與資料庫進行交互 2. 簡化資料庫操作和數據訪問,允許開發人員在C#代碼中直接操作資料庫,而不需要編寫複雜的SQL語句 3. 支持多種資料庫,包括但 ...
  • PasteSpider是什麼? 一款使用.net編寫的開源的Linux容器部署助手,支持一鍵發佈,平滑升級,自動伸縮, Key-Value配置,項目網關,環境隔離,運行報表,差量升級,私有倉庫,集群部署,版本管理等! 30分鐘上手,讓開發也可以很容易的學會在linux上部署你得項目! [從需求角度介 ...
  • 痞子衡嵌入式半月刊: 第 102 期 這裡分享嵌入式領域有用有趣的項目/工具以及一些熱點新聞,農曆年分二十四節氣,希望在每個交節之日準時發佈一期。 本期刊是開源項目(GitHub: JayHeng/pzh-mcu-bi-weekly),歡迎提交 issue,投稿或推薦你知道的嵌入式那些事兒。 上期回 ...
  • 本文是IMX6ULL開發板spi OLED驅動學習筆記,方便後面查看時快速的回顧,而不需要一點點的看視頻 視頻地址: https://www.bilibili.com/video/BV1Yb4y1t7Uj?p=144&spm_id_from=pageDriver&vd_source=1d93d6a5 ...
  • 在嵌入式Linux設備中,經常使用jffs2文件系統來作為參數區的文件系統格式。至於為什麼要使用jffs2來作為參數區的文件系統,我猜大部分人都沒有做過多的思考。 jffs2在2001年被設計出來,距今已過二十多年,現在在嵌入式設備中它還在被大量使用、說明這套設計本身是沒有問題。 但是,你是否有... ...
  • 為了更好的閱讀體驗,請點擊這裡 先學習一下 zsh 的配置吧~ 參考資料 從 0 開始:教你如何配置 zsh powerlevel10k 如何給 Xshell 配置呢 當我安裝完 oh-my-zsh、powerlevel10k、fast-syntax-highlighting、以及若幹(powerl ...
  • 腳本工具可以幫助我們完成一些需要重覆勞動的工作; 基礎語法: "#"為註釋符號 1:#指定腳本運行環境為 /bin/bash #! /bin/bash 2:輸入參數,xxx為變數名,多個變數名用空格隔開read xxx 輸出參數echo xxx 3: 變數和運算符的定義:這是每個編程語言必不缺少的部 ...
  • 在伺服器linux系統環境下,想要上傳和下載文件到本地PC通常是比較麻煩的, 在這個過程中,將層級複雜的文件夾壓縮成壓縮包再進行上傳/下載更為方便, 其中常用到的linux指令就是 zip / unzip, 文件壓縮指令 zip 個人認為,在日常科研中,常用的參數有兩個: -q 不顯示指令執行過程( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...