FreeRTOS【4】線程掛起和恢復

1.開發背景

? ? ? ?基于上一篇指引,成功創建并啟動線程后,線程已經開始運行了,但是有時我們需要線程暫停運行,例如某個線程是控制 LED 閃燈的,如果現在需要讓 LED 停止工作,單純的關閉 LED 是沒用的,因為下一時刻線程可能就會重新打開 LED 導致程序沒有達到預期,所以線程引入了一個掛起的狀態,如下圖,FreeRTOS 引入了線程的多個狀態。

????????其中包含 Running、Ready、Suspended、Blocked 等狀態。

Running:即運行態,是成功獲取了 CPU 使用權的線程。

Ready:即準備態,單核 CPU 在同一時刻只能做一件事情,所以如果當前有其他線程獲取了 CPU 的使用權(一般是高優先級線程),這個時候等待運行的線程就是準備態。

Suspended:即掛起態,正如上文說到的,如果我們想讓某個線程暫時停止工作,就可以掛起對應線程,被掛起的線程就是掛起態。

Blocked:即阻塞態,因為線程存在高低優先級,如果高優先級線程一直運行會導致低優先級線程一直搶占不到 CPU 的使用權,如果使用掛起的方式去掛起高優先級線程,那么高優先級線程的實時性就會大打折扣,所以就引入了阻塞的概念,高優先級線程可以一直阻塞在某個事件,在阻塞期間會讓出 CPU 的使用權,但是一旦高優先級線程滿足指定事件就會立刻搶占低優先級線程的 CPU 使用權,這樣就保證了高優先級線程的實時性。

????????上述純粹個人理解,如有誤請見諒,可以參考鏈接:FreeRTOS task states and state transitions described

2.開發需求

? ? ? ? 掛起、恢復和刪除已有線程

3.開發環境

? ? ? ? window10 + MDK + STM32F429 + FreeRTOS10.3.1

4.實現步驟

4.1 線程掛起其他線程

1)創建控制線程和 2 個測試線程

/* 測試初始化 */
void aTest_Init(void)
{/* 創建動態任務 */xTaskCreate(TaskCtrl, "TaskCtrl", 500, NULL, 5, &p->taskCtrl);/* 共用一個任務函數 創建多個任務 */static char whichTask[TASK_LIST_SIZE][3] = {0};for (int i = 0; i < TASK_LIST_SIZE; i++){snprintf(whichTask[i], 2, "%d", i);xTaskCreate(TaskList, "TaskList", 500, (void*)whichTask[i], 5, &p->taskList[i]);}
}

2)測試線程循環打印

/* 動態任務組 */
static void TaskList(void *pvParameters)
{int count = 0;int whichTask = atoi(pvParameters);Log_Debug("%s [%d]\r\n", __func__, whichTask);for ( ; ; ){vTaskDelay(1000);Log_Debug("%s [%d] count = %d\r\n", __func__, whichTask, count++);}
}

3)控制線程間斷掛起和恢復,使用 vTaskSuspend 掛起線程,vTaskResume 恢復線程。

/* 動態任務 */
static void TaskCtrl(void *pvParameters)
{Log_Debug("%s\r\n", __func__);/* 掛起線程 0 */vTaskDelay(3000);vTaskSuspend(p->taskList[0]);vTaskDelay(3000);vTaskResume(p->taskList[0]);for ( ; ; ){vTaskDelay(1000);}
}

4)測試結果

如圖所示,可以看出線程0 中間有 3 個周期是停止工作的。

4.2 線程掛起線程本身

1)基于上面試驗的基礎上,修改測試線程為打印日志后掛起自身,這里做這個試驗是為了驗證?vTaskSuspend 如果傳入參數為 NULL,即指向線程本身。

/* 動態任務組 */
static void TaskList(void *pvParameters)
{int count = 0;int whichTask = atoi(pvParameters);Log_Debug("%s [%d]\r\n", __func__, whichTask);for ( ; ; ){vTaskDelay(1000);Log_Debug("%s [%d] count = %d\r\n", __func__, whichTask, count++);vTaskSuspend(NULL);}
}

2)控制線程只需定期恢復線程即可

/* 動態任務 */
static void TaskCtrl(void *pvParameters)
{Log_Debug("%s\r\n", __func__);/* 掛起線程 0 */vTaskDelay(3000);vTaskResume(p->taskList[0]);for ( ; ; ){vTaskDelay(1000);}
}

3)測試結果

如圖所示,測試線程執行了一次就掛起了本身,控制線程間隔 3s 之后喚醒了一次測試線程0

4)源碼解析

vTaskSuspend

????????->?prvGetTCBFromHandle

/** Several functions take an TaskHandle_t parameter that can optionally be NULL,* where NULL is used to indicate that the handle of the currently executing* task should be used in place of the parameter.  This macro simply checks to* see if the parameter is NULL and returns a pointer to the appropriate TCB.*/
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )

如源碼所示,如果傳入指針為空,即獲取當前控制塊?pxCurrentTCB

4.3 中斷中恢復線程

1)基于上面的實驗使用中斷來代替控制線程來恢復已掛起的測試線程

/* Key2 PC13   Key0 PH3 Key1 PH2 */
void Exti13_TriggerInterrupt(void)
{if (mspGpio_GetInput("PC13") == 0){Log_Debug("%s 按鍵執行測試線程0 恢復\r\n", __func__);BaseType_t xYieldRequired;xYieldRequired = xTaskResumeFromISR(p->taskList[0]);portYIELD_FROM_ISR(xYieldRequired);mspExti_Close(13);}
}

在中斷中使用 FreeRTOS 接口需要帶 FromISR 后綴的,如 xTaskResumeFromISR,需要portYIELD_FROM_ISR 切換上下文,否則實時性會收到一定的影響,為了調試和演示方便在中斷中打印了數據,在實際項目中切記不要在中斷中停留,特別是打印等高延時操作。

2)測試結果

如圖所示,在中斷中恢復已經掛起的線程也是可以的。

4.4 線程刪除

1)線程刪除后會釋放內存,由于現在的線程都是在系統堆棧動態開辟的,所以線程刪除后內存會回歸系統內存堆棧。

/* 動態任務 */
static void TaskCtrl(void *pvParameters)
{Log_Debug("%s\r\n", __func__);/* 掛起線程 0 */vTaskDelay(3000);Log_Info("FreeRTOS Remain Space = %d Bytes\r\n", xPortGetFreeHeapSize());vTaskDelete(p->taskList[0]);Log_Info("Delete Task0 And FreeRTOS Remain Space = %d Bytes\r\n", xPortGetFreeHeapSize());vTaskDelete(p->taskList[1]);Log_Info("Delete Task1 And FreeRTOS Remain Space = %d Bytes\r\n", xPortGetFreeHeapSize());for ( ; ; ){vTaskDelay(1000);
//        Log_Debug("%s\r\n", __func__);}
}

2)測試結果

如圖所示,刪除2個任務后,系統內存由 49472Bytes -> 51584Bytes -> 53696Bytes

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

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

相關文章

Python中json數據的常用操作函數:dump load dumps和loads

文章目錄 dump函數load函數dumps函數loads函數 dump函數 功能&#xff1a;將Python對象序列化為JSON格式的字符串&#xff0c;并寫入到文件中。這個方法用于將數據保存到文件中。語法&#xff1a;json.dump(需要進行json序列化的Python對象, 寫入的文件路徑) load函數 功能&…

文科生在三本院校,讀計算機專業

6歲&#xff0c;進入村小&#xff0c;一年級&#xff0c;老師問我的夢想是什么&#xff0c;我說我長大了我要成為科學家。 9歲&#xff0c;三年級&#xff0c;知道科學家不現實&#xff0c;開始學習英語。又因為科學家英語不好發音&#xff0c;于是我的夢想變了&#xff0c;長…

ZCC5503 18V 1A 6uA低靜態功耗 同步降壓控制器

1. 概要 ZCC5503R 是一款基準電壓源、振蕩電路、 比較器 PWM/PFM 控制器構成的 CMOS 降壓電路調整器&#xff0c;利用 PWM/PFM 自動切換控制電路達到可調占空比&#xff0c;具有全輸入電壓范圍&#xff08;3~18V &#xff09;內的低紋波、高效率及大電流輸出等特點. 2. 產品特性…

【智能優化算法】雁群優化算法(Wild Geese Algorithm,WGA)

雁群優化算法(Wild Geese Algorithm,WGA)是期刊“Array”的2021年智能優化算法 01.引言 雁群優化算法(Wild Geese Algorithm,WGA)用于大規模全局優化&#xff0c;并利用IEEE CEC 2008和CEC 2010高維D100、500、1000特別會議的大規模測試函數驗證了該算法的效率和性能。WGA的靈…

OceanBase v4.3特性解析:新功能“租戶克隆”的場景與應用指南

熟悉或曾用過OceanBase的朋友&#xff0c;對于“多租戶”這一理念定不陌生。OceanBase的租戶概念&#xff0c;與我們熟知的傳統數據庫實例頗為相似。舉例來說&#xff0c;OceanBase的租戶支持MySQL兼容模式&#xff0c;對于用戶而言&#xff0c;選用一個MySQL兼容模式的租戶&am…

IT行業的現狀與未來發展趨勢:探索無限可能

隨著技術的不斷進步&#xff0c;IT行業已成為推動全球經濟和社會發展的關鍵力量。從云計算、大數據、人工智能到物聯網、5G通信和區塊鏈&#xff0c;這些技術正在重塑我們的生活和工作方式。在本篇博客中&#xff0c;我們將探討IT行業的現狀以及未來發展趨勢&#xff0c;展望這…

DOM操作---刪除元素,刪除指定的元素,循環刪除元素

刪除DOM元素 remove()方法可以刪除自身節點&#xff0c;要注意一個元素被刪除時&#xff0c;它的子元素也會跟著全部刪除 let bt document.getElementById("bt"); bt.remove(); removeChild ()方法可以刪除指定的子元素 let bt document.getElementById("…

Git 倉庫的常用命令 遠程倉庫 本地倉庫

初始化倉庫&#xff1a; git init克隆&#xff08;Clone&#xff09;一個遠程倉庫到本地&#xff1a; git clone <遠程倉庫地址>添加&#xff08;Add&#xff09;文件到暫存區&#xff1a; git add <文件名>提交&#xff08;Commit&#xff09;文件到本地倉庫&a…

589.N叉樹的前序遍歷

刷算法題&#xff1a; 第一遍&#xff1a;1.看5分鐘&#xff0c;沒思路看題解 2.通過題解改進自己的解法&#xff0c;并且要寫每行的注釋以及自己的思路。 3.思考自己做到了題解的哪一步&#xff0c;下次怎么才能做對(總結方法) 4.整理到自己的自媒體平臺。 5.再刷重復的類…

【C++風云錄】提升設計效率:建筑工程與結構優化

優化你的工程設計&#xff1a;全面解析六大軟件庫 前言 本文將對六種廣泛使用于建筑工程設計的軟件工具進行深入探討&#xff0c;這些工具各自都有獨特的特性和應用場景。我們將詳細介紹并比較這些工具的設計流程&#xff0c;還將通過實例分析來進一步解釋它們在現實世界中的…

C++類與對象的兩個案例

1.立方體 #include <iostream> using namespace std;//立方體類設計 //1.創建立方體類 //2.設計屬性 //3.設計行為 獲取立方體面積和體積 //4.分別利用全局函數和成員函數 判斷兩個立方體是否相等class Cube { public:int getL(){return m_L;}void setL(int L){m_L L;}…

2024OD機試卷-找朋友 (java\python\c++)

題目:找朋友 題目描述 在學校中,N個小朋友站成一隊, 第i個小朋友的身高為height[i], 第i個小朋友可以看到的第一個比自己身高更高的小朋友j,那么j是i的好朋友(要求j > i)。 請重新生成一個列表,對應位置的輸出是每個小朋友的好朋友位置,如果沒有看到好朋友,請在該…

達夢sql中參數個數太多導致出現SOH等特殊字符報錯無效的序列號是不是達夢的bug

mybatis的Mapper.xml中如下&#xff1a; in中的參數大概有1萬6千多個&#xff0c;分成每1000個一組拼接成sql&#xff0c;然而在達夢中執行時報如下: Caused by: dm.jdbc.driver.DMException: Invalid sequence noat dm.jdbc.driver.DBError.throwException(DBError.java:710)…

【風變】Python爬蟲精進復習-20240430

參考筆記 下面給出一個巨佬學習風變pyhton基礎語法和爬蟲精進的筆記&#xff08;鏈接&#xff09; 風變編程筆記(一)-Python基礎語法 風變編程筆記(二)-Python爬蟲精進 技術總結 request BeautifulSoup selenium BeautifulSoup 練習0-1&#xff1a;文章下載 import requ…

舜山木業有限公司現已加入2024長三角快遞物流供應鏈與技術裝備展覽會

參展企業介紹 紹興舜山木業有限公司是中華人民共和國出境木質包裝定點企業、浙江省林業重點龍頭企業。2011年起全面導入和開發應用符合木包裝企業生產特點的ERP管理系統&#xff0c;順利通過國家三級安全生產標準化驗收&#xff0c;取得歐標托盤在中國大陸區的生產商執照資格。…

九、e2studio VS STM32CubeIDE之const修飾BSP函數的形參

目錄 一、概述/目的 二、通過串口發送函數對比 2.1 stm32 hal庫 VS renesas FSP 2.2 const修改函數形參的作用 2.2.1 值傳遞-副本 2.2.2 指針傳遞&#xff08;就近原則&#xff09; 2.2.2.1 const修飾&#xff1a;*P 2.2.2.2 const修飾&#xff1a;指針變量P 2.2.2.3 …

手擼XXL-JOB(二)——定時任務管理

在上一節中&#xff0c;我們介紹了SpringBoot中關于定時任務的執行方式&#xff0c;以及ScheduledExecutorService接口提供的定時任務執行方法。假設我們現在要寫類似XXL-JOB這樣的任務調度平臺&#xff0c;那么&#xff0c;對于任務的管理&#xff0c;是尤為重要的。接下來我們…

最新Linux Debian12安裝和使用ImageMagick圖像處理工具 常見圖片png、jpg格式轉webp格式

在Linux系統中&#xff0c;使用ImageMagick可以圖片格式轉換&#xff0c;其中最常用的是通過命令行工具進行。 ImageMagick是一個非常強大的圖像處理工具集&#xff0c;它包含了許多用于圖像轉換的命令。 一、安裝ImageMagick&#xff08;如果尚未安裝&#xff09;&#xff1…

在線音樂系統

文章目錄 在線音樂系統一、項目演示二、項目介紹三、部分功能截圖四、部分代碼展示五、底部獲取項目&#xff08;9.9&#xffe5;帶走&#xff09; 在線音樂系統 一、項目演示 音樂網站 二、項目介紹 基于springbootvue的前后端分離在線音樂系統 登錄角色 : 用戶、管理員 用…

外文文獻查找以及下載渠道

尋找外文文獻的渠道有很多種&#xff1a; 學術數據庫和期刊網站&#xff1a;像PubMed、IEEE Xplore、ScienceDirect等學術數據庫和期刊網站是獲取外文文獻的主要渠道之一。這些平臺通常提供了廣泛的學術資源&#xff0c;包括期刊文章、會議論文等。 學術搜索引擎&#xff1a;…