版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第13章嵌入式實時操作系統(tǒng)FreeRTOSSTM32本章知識與能力要求了解FreeRTOS功能特點、應(yīng)用場合;理解和掌握FreeRTOS任務(wù)調(diào)度的基本原理、實現(xiàn)機(jī)制以及任務(wù)優(yōu)先級;理解和掌握FreeRTOS的任務(wù)管理、信號量、事件組、消息隊列等同步通信機(jī)制。第13章嵌入式實時操作系統(tǒng)FreeRTOS13.313.413.213.1FreeRTOS概述FreeRTOS的任務(wù)信號量事件組消息隊列13.513.1FreeRTOS概述13.1.1FreeRTOS概述13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范FreeRTOS是一個開源的嵌入式實時操作系統(tǒng)(RTOS:RealTimeOperatingSystem),實時意味著能夠滿足系統(tǒng)對任務(wù)響應(yīng)時間的要求,強(qiáng)調(diào)的是實時性,這里的實時性并不意味著快,而是具有嚴(yán)苛的截止時限(Deadline)。FreeRTOS提供輕量級的資源管理、任務(wù)調(diào)度和管理機(jī)制,通過任務(wù)劃分和模塊化設(shè)計,能夠?qū)崿F(xiàn)多任務(wù)的并發(fā)處理,提供實時操作系統(tǒng)所需的基本功能。第9章定時器13.1.1FreeRTOS概述FreeRTOS是一個多任務(wù)、搶占式、可裁剪的實時內(nèi)核,以系統(tǒng)函數(shù)形式提供時間、內(nèi)存、任務(wù)調(diào)度、任務(wù)同步與通信等各類管理功能,以任務(wù)為單位進(jìn)行應(yīng)用程序的開發(fā),任務(wù)之間相對獨(dú)立,各任務(wù)通過信號量、消息隊列等機(jī)制進(jìn)行同步與通信。第9章定時器13.1.1FreeRTOS概述FreeRTOS
內(nèi)核支持搶占式、合作式和時間片調(diào)度,且可裁剪,大小可擴(kuò)展,可用程序內(nèi)存占用低至9KB免費(fèi)開源,根據(jù)MIT許可用于任何目的靈活的任務(wù)優(yōu)先級分配,可創(chuàng)建任務(wù)的數(shù)量沒有限制,任務(wù)的優(yōu)先級也沒有限制
具有低功耗模式,支持中斷嵌套
支持40多種MCU架構(gòu)和15多種工具鏈,包括RISC-V和ARMv8-M(ARMCortex-M33)微控制器。支持多種擴(kuò)展庫和組件,提供網(wǎng)絡(luò)、文件系統(tǒng)、安全、OTA更新等功能13.1.1FreeRTOS概述FreeRTOS具有豐富的生態(tài)系統(tǒng),比如STM32微控制器的開發(fā)平臺STM32CubeMX集成了FreeRTOS內(nèi)核軟件包,使得開發(fā)人員能夠快速構(gòu)建基于STM32+FreeRTOS的應(yīng)用系統(tǒng),利用各種現(xiàn)有的軟件生態(tài)資源,加速應(yīng)用程序的開發(fā),F(xiàn)reeRTOS作為微控制器和小型微處理器的實時操作系統(tǒng),被廣泛應(yīng)用于嵌入式系統(tǒng)和物聯(lián)網(wǎng)設(shè)備中。第9章定時器13.1.1FreeRTOS概述1.FreeRTOS的數(shù)據(jù)類型STM32的HAL庫有一個頭文件stdint.h,里面定義了一些基礎(chǔ)的數(shù)據(jù)類型,比如uint8_t、uint32_t等。第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范stdint.h/*exact-widthsignedintegertypes*/typedefsignedcharint8_t;typedefsignedshort
intint16_t;typedefsignedintint32_t;typedefsigned__INT64int64_t;/*exact-widthunsignedintegertypes*/typedefunsignedcharuint8_t;typedefunsignedshortintuint16_t;typedefunsignedintuint32_t;typedefunsigned__INT64uint64_t;portmacro.h頭文件中定義的基礎(chǔ)數(shù)據(jù)類型源碼如下:第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范portmacro.h/*Typedefinitions.*/#define portCHAR char//int8_t#define portFLOAT float //4字節(jié)浮點數(shù)#define portDOUBLEdouble //8字節(jié)浮點數(shù)#define portLONG long//int32_t#define portSHORT short//int16_t#define portSTACK_TYPEuint32_t//棧數(shù)據(jù)類型#define portBASE_TYPElong//int32_ttypedefportSTACK_TYPEStackType_t;//棧數(shù)據(jù)類型StackType_t,32位微處理器中是uint32_ttypedeflong BaseType_t; //基礎(chǔ)數(shù)據(jù)類型BaseType_t,32位微處理器中是int32_ttypedefunsignedlongUBaseType_t; //基礎(chǔ)數(shù)據(jù)類型UBaseType,32位微處理器中是uint32_ttypedefuint32_tTickType_t;//節(jié)拍數(shù)據(jù)類型TickType_t,32位微處理器為uint32_tBaseType_t
作為FreeRTOS自定義的基礎(chǔ)數(shù)據(jù)類型,通常用作簡單的返回值的類型以及通用宏定義的邏輯值,比如pdTRUE為1,pdFALSE值為0,pdPASS為1,pdFAIL為0。定義在projdefs.h頭文件中,源碼如下:第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范projdefs.h#definepdFALSE ((BaseType_t)0)#definepdTRUE ((BaseType_t)1)#definepdPASS (pdTRUE)#definepdFAIL (pdFALSE)#defineerrQUEUE_EMPTY ((BaseType_t)0)#defineerrQUEUE_FULL ((BaseType_t)0)StackType_t棧變量數(shù)據(jù)類型定義,這個數(shù)量類型由系統(tǒng)架構(gòu)決定,對于16位系統(tǒng)架構(gòu),StackType_t定義的是16位變量,對于32位系統(tǒng)架構(gòu),StackType_t定義的是32位變量。TickType_tFreeRTOS的任務(wù)調(diào)度是基于一個周期性的時鐘中斷TickInterrupt,Tick中斷次數(shù)累加稱為TickCount,這個變量的類型就是TickType_t。如果用戶在FreeRTOSConfig.h頭文件中使能了configUSE_16_BIT_TICKS這個宏定義,那么TickType_t定義的就是16位無符號數(shù)uint16_t,否則TickType_t定義的就是32位無符號數(shù)uint32_t。對于32位架構(gòu)的處理器,建議把TickType_t配置為uint32_t,即設(shè)置此宏定義數(shù)值為0即可。UBaseType_t該數(shù)據(jù)類型是BaseType_t類型的有符號版本。第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范2.FreeRTOS的編程規(guī)范FreeRTOS和uC/OS-III都遵循MISRA-C編碼標(biāo)準(zhǔn)(MISRA-C是由汽車工業(yè)軟件可靠性協(xié)會(MISRA)提出的C語言開發(fā)標(biāo)準(zhǔn)),支持各種編譯器,了解FreeRTOS的變量、函數(shù)以及相關(guān)宏定義的命名規(guī)律有助于理解其意義。第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范·變量名FreeRTOS中,定義變量時通常將變量的類型作為前綴,通過變量名的前綴就可以判斷變量的類型第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范變量名前綴含義cchar類型sint16_t(short)lint32_t(long)x復(fù)雜的結(jié)構(gòu)體、句柄等定義的變量名的前綴為x;BaseType_t類型以及其他非標(biāo)準(zhǔn)的類型,比如結(jié)構(gòu)體變量、任務(wù)句柄TaskHandle、隊列句柄QueueHandle等,使用前綴x。u表示無符號整數(shù)unsigned,比如uc表示uint8_t(unsignedchar)類型,us表示uint16_t類型,ul表示uint32_t類型。p指針類型變量使用前綴ppcchar*類型uxUBaseType_t類型,比如uxCurrentPriority,uxPriority表13-1FreeRTOS常見的變量名類型前綴·函數(shù)名FreeRTOS中函數(shù)名是由返回值類型和函數(shù)功能組成,包含了函數(shù)返回值、函數(shù)所在的文件名和函數(shù)的功能,如果是私有的函數(shù)則加prv(private)前綴。
若返回值為void類型,則函數(shù)命名規(guī)則為:“v+函數(shù)功能”,以FreeRTOS中隊列刪除函數(shù)為例,該函數(shù)定義在task.c文件中,F(xiàn)reeRTOS將其命名為vQueueDelete(),其中v表示該函數(shù)的返回值為void類型。第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范表13-2FreeRTOS常見的函數(shù)名前綴及其所在位置第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范函數(shù)名前綴含義v返回值類型:void比如vTaskPrioritySet定義在task.c文件中x返回值類型:BaseType_t比如xQueueReceive定義在queue.c文件中pv返回值類型:pointertovoid比如pvTimerGetTimerID定義在timer.c文件中pc返回值為char*比如pcTimeGetName定義在timer.h文件中CMSIS-RTOS接口CMSIS-RTOS是ARM公司為運(yùn)行于Cortex-M系列微控制器上的操作系統(tǒng)專門設(shè)計的一種接口標(biāo)準(zhǔn),它提供了一種標(biāo)準(zhǔn)化的API接口讓開發(fā)者可以調(diào)用嵌入式操作系統(tǒng)的功能而不必理會底層到底采用的是哪種操作系統(tǒng),這就意味著凡是采用CMSIS-RTOS編寫的程序可以無縫移植到其它操作系統(tǒng)上運(yùn)行,因為CMSIS-RTOS提供一個通用的操作系統(tǒng)API接口會調(diào)用其它操作系統(tǒng)的相關(guān)功能。STM32CubeMX軟件集成的CMSIS_V1是對FreeRTOS進(jìn)行了上層封裝,適用于基于Cortex-M內(nèi)核的微控制器,比如Cortex-M0/M0+/M3/M4/M7,最新的CMSIS_V2是在CMSIS_V1的基礎(chǔ)上進(jìn)行了擴(kuò)展,增加了對Armv8-M內(nèi)核和多核芯片的操作系統(tǒng)的支持,比如Cortex-M,Cortex-A5/A7/A9。這里推薦選擇CMSIS_V2,方便以后移植切換到性能更強(qiáng)大的芯片上。第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范CMSIS-RTOS接口相關(guān)的宏定義、數(shù)據(jù)類型及封裝后的功能函數(shù)定義在cmsis_os.h、cmsis_os2.h文件中,前綴為“os”。比如#defineosWaitForever0xFFFFFFFFU//WaitforevertimeoutvalueosStatus_tosDelay(uint32_tticks);//FreeRTOS的相對延時函數(shù)osStatus_tosDelayUntil(uint32_tticks);//FreeRTOS的絕對延時函數(shù)第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范表13-3
FreeRTOS的API函數(shù)及CMSIS-RTOS封裝后的API函數(shù)對比第9章定時器13.1.2FreeRTOS的數(shù)據(jù)類型和編程規(guī)范API類別FreeRTOS的API函數(shù)CMSIS-RTOSV2封裝后的API函數(shù)說明內(nèi)核控制vTaskStartSchedulerosKernelStart啟動RTOS內(nèi)核調(diào)度程序任務(wù)管理xTaskCreateosThreadNew創(chuàng)建一個任務(wù)信號量xSemaphoreCreateBinaryxSemaphoreCreateCountingosSemaphoreNew創(chuàng)建并初始化信號量對象互斥量xSemaphoreCreateMutexStaticxSemaphoreCreateMutexosMutexNew創(chuàng)建并初始化一個互斥量對象消息隊列xQueueCreateosMessageQueueNew創(chuàng)建并初始化消息隊列對象軟件定時器xTimerCreateosTimerNew創(chuàng)建一個軟件定時器內(nèi)存管理pvPortMallocosMemoryPoolNewosMemoryPoolAlloc在任務(wù)堆上動態(tài)申請內(nèi)存延時函數(shù)vTaskDelayvTaskDelayUntilosDelayosDelayUntil相對延時函數(shù)絕對延時函數(shù)13.2FreeRTOS的任務(wù)13.2.1任務(wù)13.2.2任務(wù)調(diào)度13.2.3任務(wù)的實現(xiàn)機(jī)制13.2.4任務(wù)相關(guān)API函數(shù)13.2.5任務(wù)創(chuàng)建步驟13.2.6FreeRTOS創(chuàng)建任務(wù)案例1.任務(wù)的概念嵌入式實時操作系統(tǒng)將整個系統(tǒng)功能分解為一個個相對獨(dú)立且具有完整功能的程序模塊,稱為任務(wù)(Task)。任務(wù)是一個簡單的程序或具有完整邏輯含義的程序段。Linux操作系統(tǒng)以及CMSIS中將任務(wù)又稱為線程(Thread)。任務(wù)本質(zhì)上就是一個無限循環(huán)且無返回值的函數(shù),每個函數(shù)內(nèi)部都是和裸機(jī)程序中的main函數(shù)一樣是一個無限循環(huán),所以任務(wù)不能有返回值。第9章定時器13.2.1任務(wù)任務(wù)的一般結(jié)構(gòu)如下:VoidvTaskFunction(void*pvParameters){for(;;)//任務(wù)主體,無限循環(huán)且不能返回
{......//任務(wù)實現(xiàn)代碼
}}2.任務(wù)的特性(1)獨(dú)立性嵌入式操作系統(tǒng)中各任務(wù)之間互相獨(dú)立,不存在互相調(diào)用的關(guān)系,所有任務(wù)在邏輯上都是平等的。操作系統(tǒng)環(huán)境下,任務(wù)在某一時刻是獨(dú)占CPU資源的,任務(wù)之間互不交叉沒有交集,各任務(wù)之間無法像裸機(jī)的功能模塊之間進(jìn)行信息傳輸,任務(wù)間的通信就需要用到各種通信機(jī)制如信號量、事件組、隊列等來實現(xiàn)。第9章定時器13.2.1任務(wù)2.任務(wù)的特性(2)并發(fā)性多任務(wù)系統(tǒng)中,任務(wù)是并發(fā)處理的,這里的“并發(fā)”并不是說同一時刻一起執(zhí)行多個任務(wù),而是由于每個任務(wù)執(zhí)行的時間很短,從宏觀上看起來像是同一時刻執(zhí)行了很多任務(wù)。將微處理器運(yùn)行時間劃分為固定長度的時間段,按一定的規(guī)則將這些小的時間段分配給各個任務(wù)進(jìn)行使用,從宏觀上看,有多個任務(wù)在微處理器上同時在運(yùn)行,這就是多任務(wù)機(jī)制的原理。第9章定時器13.2.1任務(wù)任務(wù)所具有的獨(dú)立性和并發(fā)特性是與裸機(jī)編程中的“功能模塊”的本質(zhì)區(qū)別。實時多任務(wù)操作系統(tǒng)中,任務(wù)(或線程)是構(gòu)成多任務(wù)系統(tǒng)的基本單元,實時操作系統(tǒng)內(nèi)核(Kernel)負(fù)責(zé)管理線程,用于管理和分配CPU資源,以便有效地執(zhí)行各種任務(wù)和進(jìn)程,這一過程稱為調(diào)度(Scheduling)。一般來說,一個系統(tǒng)會同時處理多個請求,由于計算機(jī)資源有限,調(diào)度就是用來協(xié)調(diào)每個請求對資源的使用的方法。多任務(wù)系統(tǒng)中,根據(jù)一定的策略和算法,為任務(wù)分配CPU資源,以實現(xiàn)任務(wù)的按時完成和系統(tǒng)資源的最優(yōu)利用,這一過程稱為任務(wù)調(diào)度(Taskscheduling)。第9章定時器13.2.2任務(wù)調(diào)度1.任務(wù)的狀態(tài)(State)反映任務(wù)當(dāng)前在系統(tǒng)中所處的情形,由內(nèi)核維護(hù);基本狀態(tài)有五種:休眠態(tài)就緒態(tài)運(yùn)行態(tài)掛起態(tài)中斷服務(wù)態(tài)第9章定時器13.2.2任務(wù)調(diào)度運(yùn)行態(tài)(Running):一個運(yùn)行態(tài)的任務(wù)是一個正在使用CPU資源的任務(wù)。任何時刻有且只有一個運(yùn)行著的任務(wù)。就緒態(tài)(Ready):隨時可以運(yùn)行但因為當(dāng)前有同優(yōu)先級或更高優(yōu)先級的任務(wù)正在運(yùn)行,需要等待任務(wù)調(diào)度,等占有CPU資源的任務(wù)釋放CPU就可以由就緒狀態(tài)轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞態(tài)(Blocked):任務(wù)由于某種原因無法被執(zhí)行而被阻塞,可能的原因如等待某個事件的觸發(fā)或等待資源的釋放。掛起態(tài)(Suspended):某些條件不滿足而掛起不能運(yùn)行的狀態(tài),掛起后任務(wù)將不被運(yùn)行。第9章定時器13.2.2任務(wù)調(diào)度2.任務(wù)優(yōu)先級任務(wù)優(yōu)先級(TaskPriority)用于安排系統(tǒng)中各個任務(wù)的執(zhí)行次序,任務(wù)優(yōu)先級是任務(wù)的重要參數(shù),每個任務(wù)都有其優(yōu)先級,可以作為任務(wù)的標(biāo)識。任務(wù)的功能在應(yīng)用程序中越重要,賦予的優(yōu)先級應(yīng)越高。根據(jù)任務(wù)的優(yōu)先級不同,高優(yōu)先級的任務(wù)可以打斷低優(yōu)先級任務(wù)的運(yùn)行而取得CPU的使用權(quán),高優(yōu)先級的任務(wù)執(zhí)行完后重新把CPU的使用權(quán)歸還給低優(yōu)先級的任務(wù),這樣就保證了那些重要的緊急任務(wù)的運(yùn)行。FreeRTOS中,數(shù)值越大優(yōu)先級越高。第9章定時器13.2.2任務(wù)調(diào)度這里要注意的是configMAX_PRIORITIES參數(shù)配置越大,所需要的內(nèi)存空間越大,實際應(yīng)用中根據(jù)實際情況酌情配置此參數(shù)。第9章定時器13.2.2任務(wù)調(diào)度CMSIS-RTOS封裝后的優(yōu)先級定義在cmsis_os2.h文件中,CubeMX中Normal對應(yīng)的優(yōu)先級值為24,優(yōu)先級數(shù)字越低,優(yōu)先級別越低,0表示沒有優(yōu)先級,最高優(yōu)先級是56,為osPriorityISR,即中斷的優(yōu)先級最高,創(chuàng)建任務(wù)時必須為任務(wù)設(shè)置初始的優(yōu)先級。FreeRTOSConfig.h#defineconfigUSE_PREEMPTION1#defineconfigSUPPORT_STATIC_ALLOCATION1#defineconfigSUPPORT_DYNAMIC_ALLOCATION1#defineconfigUSE_IDLE_HOOK0#defineconfigUSE_TICK_HOOK0#defineconfigCPU_CLOCK_HZ(SystemCoreClock)#defineconfigTICK_RATE_HZ((TickType_t)1000)#defineconfigMAX_PRIORITIES(56)3.任務(wù)調(diào)度任務(wù)調(diào)度(TaskScheduling)就是操作系統(tǒng)根據(jù)調(diào)度規(guī)則按一定的算法從就緒隊列中選擇一個任務(wù)并分配CPU資源,以實現(xiàn)任務(wù)的并發(fā)執(zhí)行。任務(wù)調(diào)度作為操作系統(tǒng)的核心功能之一。第9章定時器13.2.2任務(wù)調(diào)度任務(wù)調(diào)度方式基于優(yōu)先級的搶占式調(diào)度內(nèi)核總是將CPU分配給處于就緒態(tài)的優(yōu)先級最高的任務(wù)運(yùn)行,保證重要的突發(fā)事件及時得到處理。優(yōu)點是可以滿足實時系統(tǒng)的響應(yīng)時間要求,可以實現(xiàn)任務(wù)的優(yōu)先級管理,缺點是低優(yōu)先級任務(wù)可能會被長時間阻塞。時間片輪轉(zhuǎn)調(diào)度將CPU的執(zhí)行時間劃分為固定長度的時間片,每個任務(wù)分配一個時間片,在一個時間片內(nèi)執(zhí)行一定的指令,當(dāng)時間片用完后,任務(wù)就會被掛起,等待下一次調(diào)度。優(yōu)點是公平地分配CPU時間片,確保每個任務(wù)都能獲得一定的執(zhí)行時間,可以避免低優(yōu)先級任務(wù)被長時間阻塞,缺點是無法滿足實時系統(tǒng)的響應(yīng)時間要求。FreeRTOS使用SysTick定時器產(chǎn)生固定間隔的中斷,兩次中斷的間隔時間稱為時間片(TimeSlice)。時鐘節(jié)拍是一個周期性的定時中斷,其時間間隔一般在1ms~10ms時間節(jié)拍可以為操作系統(tǒng)提供延時功能,將任務(wù)延時若干整數(shù)倍的時鐘節(jié)拍,以及當(dāng)任務(wù)等待事件發(fā)生時,提供超時判斷的依據(jù)。不同的系統(tǒng)其任務(wù)調(diào)度的實現(xiàn)方法不同,F(xiàn)reeRTOS默認(rèn)使用固定優(yōu)先級的搶占式調(diào)度策略,對同等優(yōu)先級的任務(wù)執(zhí)行時間片輪轉(zhuǎn)調(diào)度。搶占式調(diào)度算法,任務(wù)優(yōu)先級越高,被調(diào)度的機(jī)會就越大,任務(wù)優(yōu)先級相同時,采用時間片輪轉(zhuǎn)調(diào)度。第9章定時器13.2.2任務(wù)調(diào)度4.任務(wù)的上下文實時操作系統(tǒng)中,當(dāng)一個任務(wù)執(zhí)行時,CPU需要知道該任務(wù)從哪里加載、又從哪里開始運(yùn)行,這時就會用到CPU的寄存器和程序計數(shù)器(ProgramCounter,PC),并像其他程序一樣能夠訪問RAM和ROM,這些資源(CPU中的寄存器數(shù)據(jù)、堆棧等)一起組成了任務(wù)的上下文(Context)。任務(wù)上下文(Context)是任務(wù)運(yùn)行所依賴的環(huán)境,主要包括CPU中的寄存器數(shù)據(jù)、程序計數(shù)器、堆??臻g等。它是任務(wù)調(diào)度中的一個重要概念,定義了執(zhí)行一個任務(wù)時需要具備的條件,操作系統(tǒng)根據(jù)調(diào)度規(guī)則從眾多任務(wù)中找到符合執(zhí)行條件的任務(wù)進(jìn)行執(zhí)行,當(dāng)內(nèi)核將執(zhí)行其它任務(wù)時,需將正在運(yùn)行任務(wù)的上下文保存在任務(wù)自身的任務(wù)棧中。第9章定時器13.2.2任務(wù)調(diào)度5.任務(wù)棧RTOS調(diào)度器的職責(zé)是確保當(dāng)一個任務(wù)開始執(zhí)行時其上下文的內(nèi)容和上一次任務(wù)退出時的上下文內(nèi)容一致,為做到這一點,需要將與當(dāng)前任務(wù)的上下文(任務(wù)相關(guān)CPU寄存器中的內(nèi)容)按“先進(jìn)后出”的規(guī)則保存在內(nèi)存區(qū)域中(Task'sContextStorageArea),這個內(nèi)存保存區(qū)稱為棧(Stack)。每個任務(wù)都會在任務(wù)創(chuàng)建時分配屬于自己的??臻g。通過上下文,操作系統(tǒng)可以隨時打斷任務(wù)的運(yùn)行,當(dāng)優(yōu)先級更高的任務(wù)打斷低優(yōu)先級任務(wù)運(yùn)行時,將當(dāng)前任務(wù)的上下文入棧,即保存當(dāng)前正在運(yùn)行任務(wù)的狀態(tài)信息(寄存器的內(nèi)容)到當(dāng)前任務(wù)的棧中,并從新任務(wù)的任務(wù)棧中取出上下文重新裝入CPU的寄存器,加載并運(yùn)行新的任務(wù),從而實現(xiàn)不同任務(wù)的切換運(yùn)行,因此任務(wù)切換又稱作任務(wù)上下文切換。第9章定時器13.2.2任務(wù)調(diào)度任務(wù)主要由任務(wù)控制塊、任務(wù)棧和任務(wù)函數(shù)三個核心要素組成第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制任務(wù)函數(shù)任務(wù)函數(shù)是任務(wù)要實現(xiàn)的具體功能,任務(wù)棧是RAM中的一塊連續(xù)區(qū)域,用于保存任務(wù)在調(diào)度時的上下文信息及任務(wù)內(nèi)部定義的局部變量,任務(wù)控制塊是內(nèi)核定義的一種數(shù)據(jù)結(jié)構(gòu),用于記錄任務(wù)的各個屬性,內(nèi)核通過任務(wù)控制塊實現(xiàn)對任務(wù)的管理和調(diào)度。第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制voidvTaskFunction(void*pvParameters){for(;;)//任務(wù)函數(shù)的主體{......//任務(wù)的代碼}
vTaskDelete(NULL);}1.任務(wù)函數(shù)任務(wù)函數(shù)的主體通常為一個無限循環(huán),并且不允許以返回等任何方式從實現(xiàn)函數(shù)中退出程序循環(huán),即任務(wù)函數(shù)不能有return語句;任務(wù)不能自行結(jié)束,如果任務(wù)需要退出,則需通過任務(wù)調(diào)度的方式進(jìn)行刪除,即必須調(diào)用函數(shù)vTaskDelete(NULL)刪除該任務(wù)。任務(wù)函數(shù)的一般寫法如下:任務(wù)是嵌入式實時操作系統(tǒng)最基本的執(zhí)行單元,用于執(zhí)行特定的功能。任務(wù)函數(shù)是任務(wù)的實際執(zhí)行代碼,也稱作任務(wù)入口函數(shù)(EntryFunction)2.任務(wù)棧任務(wù)棧是任務(wù)的私有內(nèi)存空間,用于保存任務(wù)的局部變量、上下文信息等,任務(wù)棧是在創(chuàng)建任務(wù)時進(jìn)行設(shè)置的。FreeRTOS中使用STM32CubeMX創(chuàng)建任務(wù)時,需設(shè)置任務(wù)棧的大小(StackSize),單位為Words(4個字節(jié)),如圖13-1所示。第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制圖13-1FreeRTOS任務(wù)棧大小任務(wù)棧其實就是一個預(yù)先定義好的全局?jǐn)?shù)據(jù),數(shù)據(jù)類型為StackType_t,定義在protmacro.h文件中,實際為uint32_t類型,默認(rèn)為128,單位為字,即512字節(jié),這也是FreeRTOS推薦的最小的任務(wù)棧。第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制#defineportSTACK_TYPE uint32_ttypedefportSTACK_TYPEStackType_t;其源碼如下:3.任務(wù)控制塊FreeRTOS通過任務(wù)控制塊(TaskControlBlock,TCB)來定義和管理任務(wù),任務(wù)控制塊是FreeRTOS中用于描述和管理任務(wù)的一種數(shù)據(jù)結(jié)構(gòu),包含了任務(wù)的名稱、任務(wù)的狀態(tài)、優(yōu)先級、堆棧等信息,用結(jié)構(gòu)體表示。創(chuàng)建任務(wù)時,系統(tǒng)會為任務(wù)分配相應(yīng)的內(nèi)存空間,用于保存任務(wù)的所有信息,比如棧指針、任務(wù)名稱、任務(wù)狀態(tài)等。FreeRTOS中任務(wù)控制塊定義在task.c文件中,由結(jié)構(gòu)體structtskTaskControlBlock表示,指向任務(wù)控制塊的指針稱為任務(wù)句柄,用TaskHandle_t表示。舊版本的結(jié)構(gòu)體類型名為tskTCB,新版本的類型名為TCB_t。第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制FreeRTOS中在tasks.c文件中定義了任務(wù)控制塊的數(shù)據(jù)結(jié)構(gòu),結(jié)構(gòu)如下:typedefstructtskTaskControlBlock {volatileStackType_t*pxTopOfStack; /*任務(wù)棧棧頂指針*/ListItem_txStateListItem;/*任務(wù)狀態(tài)列表(就緒,阻塞,掛起)*/ListItem_txEventListItem;/*事件列表*/UBaseType_tuxPriority; /*任務(wù)優(yōu)先級*/StackType_t*pxStack; /*任務(wù)棧起始地址*/charpcTaskName[configMAX_TASK_NAME_LEN];/*任務(wù)名稱*/}tskTCB;typedeftskTCBTCB_t;
typedefstructtskTaskControlBlock*TaskHandle_t;//任務(wù)句柄第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制任務(wù)句柄(TaskHandle)是RTOS中用于標(biāo)識和引用任務(wù)的數(shù)據(jù)類型。多任務(wù)系統(tǒng)中,每個任務(wù)在創(chuàng)建時都會分配一個唯一的任務(wù)句柄,任務(wù)句柄是一個指向任務(wù)控制塊的指針,用于指向一個任務(wù),通過任務(wù)句柄可以對任務(wù)進(jìn)行操作和管理,比如掛起任務(wù)、刪除任務(wù)、恢復(fù)任務(wù)或查詢?nèi)蝿?wù)的狀態(tài)等,此外,任務(wù)句柄還可以用于任務(wù)的同步和通信機(jī)制,比如向任務(wù)發(fā)送信號量或消息?!拘≠N士】句柄(Handle),英文有操作、處理、控制等含義,作為一個名詞時,是指某個中間媒介,通過這個中間媒介可以控制、操作某樣?xùn)|西。比如門把手(doorhandle),通過門把手可以去控制門;刀柄(knifehandle),通過刀柄可以使用刀。第9章定時器13.2.3任務(wù)的實現(xiàn)機(jī)制
任務(wù)的創(chuàng)建有兩種方法,一種是使用動態(tài)創(chuàng)建,一種是使用靜態(tài)創(chuàng)建。動態(tài)創(chuàng)建時,任務(wù)控制塊和棧的內(nèi)存是創(chuàng)建任務(wù)時動態(tài)分配的,任務(wù)刪除時,內(nèi)存可以釋放;靜態(tài)創(chuàng)建任務(wù)時,任務(wù)控制塊和棧的內(nèi)存需要事先定義好,是靜態(tài)的內(nèi)存,任務(wù)刪除時,內(nèi)存不能釋放。第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)FreeRTOS中關(guān)于任務(wù)和任務(wù)管理的API函數(shù)及經(jīng)CMSIS-RTOSV2封裝后的常用接口函數(shù)如表13-4所示。CMSIS-RTOSV2封裝后的API函數(shù)位于CMSIS_RTOS_V2/cmsis_os2.c文件中。第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)API類別FreeRTOS原生API函數(shù)CMSIS-RTOSV2封裝后的API函數(shù)函數(shù)功能任務(wù)管理xTaskCreate()xTaskCreateStatic()osThreadNew()創(chuàng)建任務(wù)vTaskSuspend()osThreadSuspend()掛起任務(wù)vTaskDelete()osThreadExit()osThreadTerminate()刪除任務(wù)pcTaskGetName()osThreadGetName()獲取當(dāng)前任務(wù)名稱xTaskGetHandle()osThreadGetId()獲取當(dāng)前任務(wù)句柄eTaskGetState()osThreadGetState()獲取任務(wù)的狀態(tài)vTaskPrioritySet()osThreadSetPriority()設(shè)置任務(wù)的優(yōu)先級uxTaskPriorityGet()osThreadGetPriority()獲取任務(wù)的優(yōu)先級
任務(wù)調(diào)度vTaskStartScheduler()osKernelStart()開啟任務(wù)調(diào)度器vTaskDelay()osDelay()任務(wù)延時taskYIKLD()osThreadYield()任務(wù)進(jìn)行上下文切換(1)任務(wù)創(chuàng)建函數(shù)osThreadNewosThreadId_tosThreadNew(osThreadFunc_tfunc,void*argument,constosThreadAttr_t*attr);函數(shù)功能:創(chuàng)建一個任務(wù)第1個參數(shù):func,是一個函數(shù)指針,指向執(zhí)行任務(wù)的函數(shù)。第2個參數(shù):argument,是傳遞給任務(wù)的參數(shù),不用時設(shè)為NULL。第3個參數(shù):attr,任務(wù)的屬性,聲明了一個名為osThreadAttr_t的線程屬性結(jié)構(gòu)體類型,該結(jié)構(gòu)體定義在cmsis_os2.h文件中,包含線程名稱、棧的大小、線程優(yōu)先級等成員變量。第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)
返回值:創(chuàng)建成功,返回任務(wù)的句柄。osThreadId_t的類型定義在cmsis_os2.h文件中,定義如下所示。typedefvoid*osThreadId_t;//使用typedef定義了一個新的類型(變量)示例:osThreadId_tTaskCOMHandle;//定義任務(wù)句柄constosThreadAttr_tTaskCOM_attributes={//任務(wù)的屬性.name="TaskCOM",//任務(wù)名稱.priority=(osPriority_t)osPriorityLow,//設(shè)置任務(wù)優(yōu)先級.stack_size=128*4,//任務(wù)棧的大小};//該屬性由STM32CubeMX自動生成TaskCOMHandle=osThreadNew(StartTaskCOM,NULL,&TaskCOM_attributes);cmsis_os2.htypedefstruct{ constchar*name;//線程名稱
uint32_tattr_bits;//屬性位
void*cb_mem;//線程控制塊內(nèi)存空間指針
uint32_tcb_size;//提供給線程控制塊內(nèi)存的大小void*stack_mem;//棧內(nèi)存空間指針
uint32_tstack_size;//棧內(nèi)存大小
osPriority_tpriority;//初始化線程優(yōu)先級(默認(rèn)值:osPriorityNormal) TZ_ModuleId_ttz_module;//信任模塊標(biāo)識
uint32_treserved;//保留(必須為0)}osThreadAttr_t;注意:主線程的創(chuàng)建就是通過設(shè)置一個線程屬性結(jié)構(gòu)體來傳遞相關(guān)參數(shù),若線程屬性結(jié)構(gòu)體為空,則試圖創(chuàng)建一個默認(rèn)的線程,從系統(tǒng)內(nèi)存池中為其分配內(nèi)存空間。任務(wù)刪除函數(shù)osThreadTerminate函數(shù)原型:osStatus_tosThreadTerminate(osThreadId_tthread_id)函數(shù)功能:刪除一個任務(wù)入口參數(shù):thread_id,是一個函數(shù)指針,指向執(zhí)行任務(wù)的函數(shù)。返回值: 刪除成功,返回osOK,否則返回osError。osStatus_t為枚舉類型,在cmsis_os2.h頭文件中,定義了函數(shù)返回值的狀態(tài)和錯誤代碼,用于說明函數(shù)的執(zhí)行情況第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)typedefenum{ osOK =0,//成功 osError =-1,//失敗 osErrorTimeout =-2,//等待超時失敗 osErrorResource =-3,//資源錯誤 osErrorParameter =-4,//參數(shù)錯誤 osErrorNoMemory =-5,//沒有足夠的內(nèi)存空間錯誤 osErrorISR=-6,//在中斷調(diào)用時設(shè)置的超時時間非零 osStatusReserved=0x7FFFFFFF,//狀態(tài)保留}osStatus_t;源碼如下:示例:osThreadId_tTaskCOMHandle;//定義任務(wù)句柄constosThreadAttr_tTaskCOM_attributes={//任務(wù)的屬性
.name="TaskCOM", //任務(wù)名稱
.priority=(osPriority_t)osPriorityLow,//設(shè)置任務(wù)優(yōu)先級
.stack_size=128*4,//任務(wù)棧的大小};//該屬性由STM32CubeMX自動生成
osThreadTerminate(TaskCOMHandle);注意,CMSIS-RTOS提供了兩個刪除任務(wù)的函數(shù)osThreadTerminate和osThreadExit,根據(jù)傳遞的參數(shù)不同,osThreadTerminate用于刪除另外一個任務(wù),osThreadExit用于刪除當(dāng)前任務(wù),其函數(shù)原型如下:voidosThreadExit(void);第9章定時器13.2.4任務(wù)相關(guān)API函數(shù)FreeRTOS任務(wù)的創(chuàng)建有相對固定的操作步驟,以SMT32CubeMX創(chuàng)建任務(wù)為例,包括以下4個步驟:(1)定義任務(wù)(或線程)的句柄
osThreadId_tTaskCOMHandle;//定義任務(wù)句柄constosThreadAttr_tTaskCOM_attributes={//任務(wù)的屬性
.name="TaskCOM", //任務(wù)名稱
.priority=(osPriority_t)osPriorityLow,//設(shè)置任務(wù)優(yōu)先級
.stack_size=128*4,//任務(wù)棧的大小};//任務(wù)屬性,該屬性由STM32CubeMX自動生成第9章定時器13.2.5任務(wù)創(chuàng)建步驟(2)創(chuàng)建任務(wù)(或線程)TaskCOMHandle=osThreadNew(StartTaskCOM,NULL,&TaskCOM_attributes);(3)編寫任務(wù)函數(shù)voidStartCOMTask(void*argument){/*USERCODEBEGINStartCOMTask*//*Infiniteloop*/ for(;;) { ......osDelay(1); }/*USERCODEENDStartCOMTask*/}第9章定時器13.2.5任務(wù)創(chuàng)建步驟(4)啟動內(nèi)核任務(wù)調(diào)度osKernelStart();實踐目標(biāo):掌握FreeRTOS的任務(wù)創(chuàng)建方法。實踐內(nèi)容:基于STM32CubeMX+FreeRTOS創(chuàng)建兩個任務(wù):LED指示燈閃爍任務(wù),每隔100ms進(jìn)行狀態(tài)轉(zhuǎn)換;蜂鳴器任務(wù),每隔100ms鳴叫。硬件設(shè)計引腳分配:LED指示燈連接在PE5引腳上,蜂鳴器連接在PB8引腳上,低電平有效。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例實踐步驟:1.打開STM32CubeMX,新建一個工程,選擇MCU。這里采用STM32F103ZET6。2.STM32CubeMX功能參數(shù)設(shè)置(1)RCC和時鐘配置。在RCC選項中,設(shè)置HSE作為系統(tǒng)的外部時鐘源,在HSE下列選項中選擇“Crystal/CeramicResonator”選項。時鐘系統(tǒng)配置。在“ClockConfiguration”選項卡進(jìn)行時鐘系統(tǒng)配置,這里采用HSE外部晶振,頻率為8MHz,通過PLL的倍頻使系統(tǒng)時鐘SYSCLK的頻率為72MHz。如圖13-2所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例圖13-2STM32時鐘配置第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例(2)設(shè)置HAL庫的時間基準(zhǔn)。在主界面點擊SYS,在SYSModeandConfiguration配置頁中,設(shè)置Debug為SerialWire;在TimebaseSource中選擇TIM8作為HAL庫的時間基準(zhǔn)。這是因為FreeRTOS使用SysTick(嘀嗒定時器)作為基礎(chǔ)時鐘,而HAL庫也使用SysTick作為基礎(chǔ)時鐘,兩者產(chǎn)生沖突,這時就需要為HAL庫的時間基準(zhǔn)更換和配置另一個定時器供HAL庫中的一些函數(shù)使用,比如HAL_Delay()延時函數(shù)等,如圖13-3所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例圖13-3HAL庫時間基準(zhǔn)設(shè)置(3)MCU引腳分配在GPIO選項卡中,設(shè)置PE5、PB8為GPIO_Output,UserLabel分別為LED、BEEP。(4)FreeRTOS任務(wù)創(chuàng)建。在主界面的Middleware中選中FREERTOS選項卡,在配置窗口上方的Mode欄中選擇Interface為CMSIS_V2,這是ARM公司為運(yùn)行于Cortex-M系列微控制器上的操作系統(tǒng)定義的CMSIS-RTOS接口,它提供了一種標(biāo)準(zhǔn)化的API接口。如圖13-4所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例圖13-4FreeRTOS創(chuàng)建任務(wù)第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例CMSIS_V1適用于Cortex-M0/M0+/M3/M4/M7等系列微控制器,CMSIS_V2在CMSIS_V1的基礎(chǔ)上進(jìn)行了擴(kuò)展,不僅適用于所有的Cortex-M系列微控制器,還支持Cortex-A5/A7/A9系列微處理器,這里建議選擇最新的版本CMSIS_V2。FreeRTOS的Configuration頁面中,有以下選項卡用于參數(shù)配置。詳細(xì)如表13-5所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例表13-5FreeRTOS的配置選項FreeRTOS選項卡功能Configureparameters用于FreeRTOS參數(shù)配置,定義一些相關(guān)的宏定義在FreeRTOSConfig.h文件中。Includeparameters包含參數(shù),用于配置相關(guān)函數(shù)的條件編譯,定義在FreeRTOSConfig.h文件中。Advancedsettings高級設(shè)置TasksandQueues任務(wù)和隊列TimersandSemaphores軟件定時器和信號量Mutexes互斥量FreeRTOSHeapUsageFreeRTOS堆內(nèi)存空間使用情況統(tǒng)計UserContants用戶常數(shù)在配置窗口下方的Configuration欄中,選擇TasksandQueues選項卡,雙擊defaultTask,在彈出的defaultTask任務(wù)窗口中,將其修改為LEDTask任務(wù),設(shè)置參數(shù)如下:
·任務(wù)名稱TaskName:LEDTask·優(yōu)先級Priority:osPriorityNormal·任務(wù)函數(shù)EntryFunction:StartLEDTask
其余參數(shù)使用默認(rèn)值。如圖13-5所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例圖13-5LEDTask任務(wù)設(shè)置FreeRTOS的Task選項卡中,相關(guān)參數(shù)的作用如下表13-6所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例Task選項卡參數(shù)功能TaskName任務(wù)名稱,用戶自定義Priority優(yōu)先級,每個任務(wù)都需要設(shè)置一個優(yōu)先級,F(xiàn)reeRTOS默認(rèn)有56個等級,定義在FreeRTOSConfig.h文件中的宏定義configMAX_PRIORITIES,數(shù)字越小,優(yōu)先級越低。默認(rèn)優(yōu)先級為osPriorityBelowNormal。StackSize任務(wù)棧空間大小。每個任務(wù)都需要分配一個??臻g,單位為字(Words,32位微控制器的1個Words=4個字節(jié))。EntryFunction入口函數(shù),也即任務(wù)函數(shù)。一個任務(wù)就是一個無限循環(huán)函數(shù),這個參數(shù)為實現(xiàn)此任務(wù)的函數(shù)名稱。CodeGenerationOption生成代碼選項。有Default和Asweak兩個選項,Asweak為__weak,即將任務(wù)函數(shù)定義為一個弱函數(shù);Default為生成正常的任務(wù)函數(shù)。Parameter參數(shù)。為任務(wù)函數(shù)傳遞的參數(shù),設(shè)置為NULL意味著所定義的任務(wù)函數(shù)沒有參數(shù)。Allocation內(nèi)存分配方式。有動態(tài)Dynamic和靜態(tài)Static兩種。BufferName緩沖器名稱ControlBlockName任務(wù)控制塊名稱點擊Add,創(chuàng)建BEEPTask任務(wù),在BEEPTask任務(wù)窗口中,設(shè)置參數(shù)如下:
·任務(wù)名稱TaskName:BEEPTask·優(yōu)先級Priority:osPriorityLow·任務(wù)函數(shù)EntryFunction:StartBEEPTask其余參數(shù)使用默認(rèn)值。如圖13-6所示。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例圖13-6BEEPTask任務(wù)設(shè)置(5)生成工程代碼。在主界面中的ProjectManager選項卡中,單擊Project選項頁,設(shè)置工程名稱、工程存放的位置,以及工程所使用的編譯器,這里選擇“MDK-ARM”。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例3.編寫任務(wù)程序。利用STM32CubeMX自動生成工程代碼后,在MDK-ARM中打開工程,先進(jìn)行編譯,確保程序代碼無錯誤后,編寫應(yīng)用程序。(1)在freertos.c文件中,找到voidStartLEDTask(void*argument)函數(shù),在for循環(huán)中輸入以下程序代碼:第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例voidStartLEDTask(void*argument){/*USERCODEBEGINStartLEDTask*//*Infiniteloop*/for(;;){
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); osDelay(100);}/*USERCODEENDStartLEDTask*/}(2)在voidStartBEEPTask(void*argument)函數(shù)中輸入以下程序代碼。voidStartBEEPTask(void*argument){/*USERCODEBEGINStartBEEPTask*//*Infiniteloop*/for(;;){
HAL_GPIO_TogglePin(BEEP_GPIO_Port,BEEP_Pin);osDelay(100);}/*USERCODEENDStartBEEPTask*/}第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例4.下載及驗證實驗現(xiàn)象:LED燈以每隔100ms進(jìn)行閃爍,蜂鳴器以每隔100ms進(jìn)行鳴叫。第9章定時器13.2.6FreeRTOS創(chuàng)建任務(wù)案例5.小結(jié)基于嵌入式操作系統(tǒng)進(jìn)行應(yīng)用程序開發(fā),關(guān)鍵在于如何將系統(tǒng)功能進(jìn)行模塊化分解,將每個功能模塊轉(zhuǎn)化為可并發(fā)執(zhí)行的任務(wù),由操作系統(tǒng)執(zhí)行多任務(wù)的調(diào)度,從而實現(xiàn)應(yīng)用功能。13.3信號量信號量概念13.3.1信號量實現(xiàn)機(jī)制13.3.2信號量應(yīng)用步驟13.3.3信號量應(yīng)用案例13.3.4
信號量(Semaphore)是實現(xiàn)任務(wù)與任務(wù)之間、任務(wù)與中斷之間同步問題的機(jī)制,用于對共享資源的有序訪問,與裸機(jī)編程中的標(biāo)志(flag)類似。信號,現(xiàn)實中常用旗或燈發(fā)出的識別信號,如海上求救的SOS燈光信號,鐵路上使用的臂板信號機(jī)就是利用不同顏色的燈光來顯示指揮行車命令的,因此使用信號的目的是實現(xiàn)通知的作用。量,數(shù)量,表示資源可以利用和使用的數(shù)量。第9章定時器13.3.1信號量概念FreeRTOS中信號量主要有二值信號量和計數(shù)信號量。1.二值信號量(BinarySemphores)當(dāng)“量”只有0和1兩種取值時,就是二值信號量,取值為0時表示沒有資源可用,取值為1時表示有可使用的資源。創(chuàng)建時其初始值一般設(shè)置為0,即沒有資源可供使用,多任務(wù)系統(tǒng)中一個任務(wù)釋放信號量,另一個任務(wù)通過獲取信號量達(dá)到任務(wù)之間的同步或互斥的目的。第9章定時器13.3.1信號量概念2.計數(shù)信號量(CountingSemphores)當(dāng)“量”的數(shù)量沒有限制時,用于計數(shù)的,就是計數(shù)信號量,其初值一般設(shè)定為可用資源的數(shù)量。計數(shù)信號量用于實現(xiàn)資源管理,比如停車場的停車位、圖書館的座位等都是計數(shù)信號量的典型應(yīng)用場景。多任務(wù)系統(tǒng)中,一個任務(wù)想要獲取資源的使用權(quán),需要先獲取計數(shù)信號量,獲取成功后,計數(shù)信號量的值減一,當(dāng)其值減到0時表示沒有資源了,想要獲取該資源的任務(wù)就由運(yùn)行態(tài)轉(zhuǎn)到阻塞狀態(tài),等待資源可用,此時就需要一個任務(wù)在使用完資源時釋放信號量,釋放成功,計數(shù)信號量的值加一。第9章定時器13.3.1信號量概念FreeRTOS中信號量實現(xiàn)機(jī)制是基于消息隊列實現(xiàn)的,信號量是消息隊列中的消息只有0和1兩種數(shù)據(jù)的特殊形式,二值信號量是長度為1的隊列,計數(shù)信號量就是長度大于1的隊列。FreeRTOS通過消息隊列控制塊管理信號量,消息隊列控制塊是一種數(shù)據(jù)結(jié)構(gòu),用結(jié)構(gòu)體表示,定義在event_groups.c文件中,詳細(xì)介紹請見本書13.5一節(jié)。FreeRTOS中用于創(chuàng)建、釋放、刪除信號量的函數(shù)定義在semphr.c文件中,經(jīng)CMSIS-V2封裝后的信號量函數(shù)在cmsis_os2.c文件中實現(xiàn)。第9章定時器13.3.2信號量實現(xiàn)機(jī)制第9章定時器13.3.2信號量實現(xiàn)機(jī)制表13-7FreeRTOS的API函數(shù)與CMSIS-RTOS封裝后的API函數(shù)對比功能分類FreeRTOS原生API函數(shù)CMSIS-RTOSV2封裝后的API函數(shù)說明創(chuàng)建xSemaphoreCreateBinary(二值信號量)osSemaphoreNew動態(tài)創(chuàng)建并初始化信號量對象xSemaphoreCreateCounting(計數(shù)信號量)獲取uxSemaphoreGetCountosSemaphoreGetCount獲取當(dāng)前信號量的計數(shù)值xSemaphoreTakeosSemaphoreAcquire獲取信號量xSemaphoreTakeFromISR在中斷服務(wù)程序(ISR)中獲取信號量釋放xSemaphoreGiveosSemaphoreRelease釋放信號量xSemaphoreGiveFromISR在中斷服務(wù)程序(ISR)中釋放信號量刪除vSemaphoreDeleteosSemaphoreDelete刪除一個信號量第9章定時器13.3.2信號量實現(xiàn)機(jī)制(1)信號量創(chuàng)建函數(shù)osSemaphoreNewosSemaphoreId_tosSemaphoreNew(uint32_tmax_count,uint32_tinitial_count,constosSemaphoreAttr_t*attr);函數(shù)功能:創(chuàng)建一個信號量。第1個參數(shù):max_count,信號量的最大計數(shù)值。其值為1時,表示二值信號量。第2個參數(shù):initial_count,信號量初值。第3個參數(shù):attr,指向信號量屬性的指針,默認(rèn)值為NULL。聲明了一個名為osSemaphoreAttr_t的結(jié)構(gòu)體,該結(jié)構(gòu)體包括信號量的名稱、大小等成員變量,定義在cmsis_os2.h文件中,如下所示。第9章定時器13.3.2信號量實現(xiàn)機(jī)制typedefstruct{constchar*name;//信號量的名稱uint32_tattr_bits;//信號量的屬性位void*cb_mem;//為信號量控制塊分配的內(nèi)存首地址uint32_tcb_size;//為信號量控制塊分配的內(nèi)存大小}osSemaphoreAttr_t;返回值:創(chuàng)建成功,返回信號量的句柄,用于標(biāo)識信號量。 創(chuàng)建失敗,返回NULL。示例:osSemaphoreId_t BinarySem01Handle;//定義二值信號量的句柄ConstosSemaphoreAttr_tBinarySem01_attributes={.name="BinarySem01",};//該屬性由STM32CubeMX自動生成BinarySem01Handle=osSemaphoreNew(1,1,&BinarySem01_attributes);第9章定時器13.3.2信號量實現(xiàn)機(jī)制(2)信號量獲取函數(shù)osSemaphoreAcquireosStatus_tosSemaphoreAcquire(osSemaphoreId_tsemaphore_id,uint32_ttimeout);函數(shù)功能:獲取一個信號量。第1個參數(shù):semaphore_id,信號量的句柄。第2個參數(shù):timeout,等待信號量可用資源時的超時等待時間,以時鐘節(jié)拍為單位。該參數(shù)為32位,類型為uint32_t,取值范圍為0~osWaitForever,設(shè)置為0時,該函數(shù)立刻返回;設(shè)置為osWaitForever,則會一直等待到信號量有可用資源。返回值:獲取成功,返回osOK;否則返回osError。第9章定時器13.3.2信號量實現(xiàn)機(jī)制在cmsis_os2.h頭文件中,定義了函數(shù)返回值的狀態(tài)和錯誤代碼,用于說明函數(shù)的執(zhí)行情況。typedefenum{osOK=0,//成功osError=-1,//失敗osErrorTimeout=-2,//等待超時失敗,在給定的超時時間內(nèi)無法獲取消息osErrorResource=-3,//無法從信號量中獲取信息錯誤osErrorParameter=-4,//mq_id參數(shù)錯誤osErrorNoMemory=-5,//沒有足夠的內(nèi)存空間錯誤osErrorISR=-6,//在中斷調(diào)用時設(shè)置的超時時間非零osStatusReserved=0x7FFFFFFF,//狀態(tài)保留}osStatus_t;示例:osSemaphoreAcquire(BinarySem01Handle,osWaitForever);第9章定時器13.3.2信號量實現(xiàn)機(jī)制(3)信號量釋放函數(shù)osStatus_tosSemaphoreRelease(osSemaphoreId_tsemaphore_id);函數(shù)功能:釋放一個信號量。入口參數(shù):semaphore_id,信號量的句柄。返回值:釋放成功,返回osOK;否則返回錯誤狀態(tài)代碼。示例:osSemaphoreRelease(BinarySem01Handle);第9章定時器13.3.3信號量應(yīng)用步驟FreeRTOS信號量的應(yīng)用有相對固定的操作步驟,以SMT32CubeMX創(chuàng)建信號量為例,包括以下4個步驟:(1)定義信號量句柄
osSemaphoreId_tBinarySem01Handle;//定義信號量句柄constosSemaphoreAttr_tBinarySem01_attributes={.name="BinarySem01"};//信號量屬性,由SMT32CubeMX自動生成(2)創(chuàng)建信號量
BinarySem01Handle=osSemaphoreNew(1,0,&BinarySem01_attributes);(3)釋放信號量
osSemaphoreAcquire(BinarySem01Handle,osWaitForever);(4)獲取信號量
osSemaphoreRelease(BinarySem01Handle);第9章定時器13.3.4信號量應(yīng)用案例一、功能描述本案例通過二值信號量實現(xiàn)任務(wù)與任務(wù)之間的同步。通過按鍵任務(wù)利用兩個二值信號量分別觸發(fā)蜂鳴器任務(wù)和串口打印任務(wù)。按鍵按一次,蜂鳴器響一次,然后通過串口打印按鍵按下的次數(shù)。二、硬件設(shè)計按鍵KEY1連接在STM32的PE3引腳上,低電平有效;蜂鳴器BEEP連接在STM32的PB8引腳上,低電平有效,通過PC機(jī)上的串口調(diào)試助手顯示信息。第9章定時器13.3.4信號量應(yīng)用案例三、軟件設(shè)計本實例需要設(shè)計三個任務(wù),分別是:任務(wù)1:按鍵任務(wù),命名為KEYTask,優(yōu)先級為2,用于釋放任務(wù)與任務(wù)之間同步的二值信號量BinarySem_a和BinarySem_b。任務(wù)2:蜂鳴器任務(wù),命名為BEEPTask,優(yōu)先級為1,通過二值信號量BinarySem_a實現(xiàn)按鍵任務(wù)與蜂鳴器任務(wù)之間的同步。任務(wù)3:串口打印任務(wù),命名為COMTask,優(yōu)先級為3,通過二值信號量BinarySem_b實現(xiàn)按鍵任務(wù)與串口打印任務(wù)之間的同步。本實例還需要定義兩個二值信號量,分別命名為BinarySem_a和BinarySem_b。第9章定時器13.3.4信號量應(yīng)用案例實施步驟如下。1.STM32CubeMX參數(shù)配置。打開STM32CubeMX,新建一個工程,這里采用STM32F103ZET6,讀者可根據(jù)自己的開發(fā)板進(jìn)行設(shè)置。(1)配置系統(tǒng)時鐘和FreeRTOS的時間基準(zhǔn)在RCC選項中,設(shè)置HSE作為系統(tǒng)的外部時鐘源,在HSE下列選項中選擇“Crystal/CeramicResonator”選項。時鐘系統(tǒng)配置。在“ClockConfiguration”選項卡進(jìn)行時鐘系統(tǒng)配置,這里采用HSE外部晶振,頻率為8MHz,通過PLL的倍頻使系統(tǒng)時鐘SYSCLK的頻率為72MHz。第9章定時器13.3.4信號量應(yīng)用案例修改HAL庫的時間基準(zhǔn),由于FreeRTOS使用SysTick系統(tǒng)嘀嗒定時器產(chǎn)生所需的時鐘節(jié)拍,而HAL庫默認(rèn)也使用SysTick產(chǎn)生時間基準(zhǔn),如HAL的延時函數(shù)HAL_Delay(),所以為避免產(chǎn)生沖突,需要修改HAL庫的時間基準(zhǔn),將其時間基準(zhǔn)改為其他定時器產(chǎn)生。這里選擇TIM8作為HAL庫的時間基準(zhǔn)。在SYS配置頁面中,選擇TimebaseSource(時基源)為TIM8,如圖13-6所示。圖13-6修改HAL庫的時間基準(zhǔn)第9章定時器13.3.4信號量應(yīng)用案例(2)MCU引腳設(shè)置在GPIO選項卡中,設(shè)置PE3為GPIO_Input模式,UserLabel為KEY1;PB8為GPIO_Output模式,UserLabel設(shè)置為BEEP,設(shè)置USART1的Mode為Asynchronous,基本參數(shù)設(shè)置保持默認(rèn)即可。(3)FreeRTOS任務(wù)創(chuàng)建。在主界面的Middleware中選中FREERTOS選項卡,在配置窗口上方的Mode欄中選擇Interface為CMSIS_V2。在“TasksandQueues”中將系統(tǒng)默認(rèn)的任務(wù)defaultTask中的參數(shù)進(jìn)行修改,參數(shù)如下:·任務(wù)名稱TaskName:KEYTask·優(yōu)先級Priority:osPriorityNormal·任務(wù)函數(shù)EntryFunction:StartKEYTask圖13-7KEYTask任務(wù)創(chuàng)建第9章定時器13.3.4信號量應(yīng)用案例然后在配置窗口下方的Configuration欄中,選擇TasksandQueues選項卡,點擊Add,新建兩個任務(wù):BEEPTask和COMTask。在LED1Task任務(wù)窗口中,設(shè)置參數(shù)如下:·任務(wù)名稱TaskName:BEEPTask·優(yōu)先級Priority:osPriorityLow·任務(wù)函數(shù)EntryFunction:StartBEEPTask圖13-8BEEPTask任務(wù)創(chuàng)建第9章定時器13.3.4信號量應(yīng)用案例在COMTask任務(wù)窗口中,設(shè)置參數(shù)如下:·任務(wù)名稱TaskName:COMTask·優(yōu)先級Priority:osPriorityLow2·任務(wù)函數(shù)EntryFunction:StartCOMTask其余參數(shù)使用默認(rèn)值。如圖13-9所示。圖13-9COMTask任務(wù)創(chuàng)建第9章定時器13.3.4信號量應(yīng)用案例(4)創(chuàng)建二值信號量在FREERTOS配置窗口下方的Configuration欄中,選擇TimersandSemaphores選項卡,在BinarySemaphores選項頁中點擊Add,新建一
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 46857.1-2025醫(yī)療裝備運(yùn)維服務(wù)第1部分:通用要求
- 廣東省惠州市惠城區(qū)2025~2026學(xué)年第一學(xué)期期末七年級地理試題(含答案)
- 養(yǎng)老院入住老人社會交往與精神慰藉制度
- 企業(yè)招聘與選拔標(biāo)準(zhǔn)制度
- 統(tǒng)編版高一語文必修上、下冊期末復(fù)習(xí):理解性默寫 專項練習(xí)題匯編(含答案)
- 飛機(jī)鉚裝工創(chuàng)新實踐模擬考核試卷含答案
- 脫脂工安全強(qiáng)化知識考核試卷含答案
- 我國上市公司獨(dú)立董事制度的困境與突破:基于實踐與理論的雙重視角
- 制鞋工崗前技術(shù)基礎(chǔ)考核試卷含答案
- 汽車貨運(yùn)理貨員安全防護(hù)考核試卷含答案
- 礦井突水機(jī)理研究-洞察及研究
- 2025-2026秋“1530”安全教育記錄表
- 執(zhí)法中心設(shè)計方案(3篇)
- 藥物警戒基礎(chǔ)知識全員培訓(xùn)
- 骨密度檢測的臨床意義
- 鉆探原始班報表試行版
- 腸菌移植治療炎癥性腸病專家共識(2025)解讀
- T/CPPC 1032-2021建筑生產(chǎn)資源分供商評價規(guī)范
- 機(jī)耕合同協(xié)議書范本簡單
- 送車免責(zé)合同協(xié)議書模板
- 外科學(xué)重癥監(jiān)測治療與復(fù)蘇
評論
0/150
提交評論