FreeRTOS學(xué)習(xí)_第1頁(yè)
FreeRTOS學(xué)習(xí)_第2頁(yè)
FreeRTOS學(xué)習(xí)_第3頁(yè)
FreeRTOS學(xué)習(xí)_第4頁(yè)
FreeRTOS學(xué)習(xí)_第5頁(yè)
已閱讀5頁(yè),還剩15頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、FREE RToS操作系統(tǒng)學(xué)習(xí)筆記-主要函數(shù)記錄1.2 任務(wù)函數(shù)原型:void ATaskFunction( void *pvParameters );一般來(lái)說(shuō)每個(gè)任務(wù)都會(huì)運(yùn)行在自己的死循環(huán)中。每個(gè)任務(wù)不允許從函數(shù)實(shí)現(xiàn)中返回,絕對(duì)不能有return語(yǔ)句,當(dāng)一個(gè)任務(wù)不再需要時(shí)可以將其刪除。一個(gè)任務(wù)函數(shù)可以用來(lái)創(chuàng)建若干個(gè)任務(wù)創(chuàng)建出的任務(wù)均是獨(dú)立的執(zhí)行實(shí)例,擁有屬于自己的??臻g,以及屬于自己的自動(dòng)變量(棧變量),即任務(wù)函數(shù)本身定義的變量。1.3任務(wù)刪除函數(shù)vTaskDelete( NULL );傳入NULL參數(shù)表示刪除當(dāng)前任務(wù)FreeRTOS 的調(diào)度器是能讓任務(wù)切入切出的唯一實(shí)體。1.4 創(chuàng)建任務(wù)創(chuàng)

2、建任務(wù)使用 FreeRTOS 的API 函數(shù)xTaskCreate()。函數(shù)原型portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,const signed portCHAR * const pcName,unsigned portSHORT usStackDepth,void *pvParameters,unsigned portBASE_TYPE uxPriority,xTaskHandle *pxCreatedTask );參數(shù)pvTaskCode參數(shù):一個(gè)指向任務(wù)的實(shí)現(xiàn)函數(shù)的指針(效果上僅僅是函數(shù)名)。pcName 具有描述性的任務(wù)名-應(yīng)

3、用程序可以通過(guò)定義常量config_MAX_TASK_NAME_LEN 來(lái)定義任務(wù)名的最大長(zhǎng)度包括0結(jié)束符。如果傳入的字符串長(zhǎng)度超過(guò)了這個(gè)最大值,字符串將會(huì)自動(dòng)被截?cái)?。usStackDepth 參數(shù)值用于告訴內(nèi)核為它分配多大的棧空間。-這個(gè)值指定的是??臻g可以保存多少個(gè)字(word),而不是多少個(gè)字節(jié)(byte)。-棧深度乘以棧寬度的結(jié)果千萬(wàn)不能超過(guò)一個(gè)size_t 類型變量所能表達(dá)的最大值。pvParameters 任務(wù)函數(shù)接受一個(gè)指向void 的指針(void*)。pvParameters 的值即是傳遞到任務(wù)中的值。uxPriority 指定任務(wù)執(zhí)行的優(yōu)先級(jí)。優(yōu)先級(jí)的取值范圍可以從最低優(yōu)先

4、級(jí)0 到最高優(yōu)先級(jí)(configMAX_PRIORITIES 1)。-如果uxPriority 的值超過(guò)了(configMAX_PRIORITIES 1),將會(huì)導(dǎo)致實(shí)際賦給任務(wù)的優(yōu)先級(jí)被自動(dòng)封頂?shù)阶畲蠛戏ㄖ?。pxCreatedTask 用于傳出任務(wù)的句柄。這個(gè)句柄將在API 調(diào)用中對(duì)該創(chuàng)建出來(lái)的任務(wù)進(jìn)行引用,比如改變?nèi)蝿?wù)優(yōu)先級(jí),或者刪除任務(wù)。如果應(yīng)用程序中不會(huì)用到這個(gè)任務(wù)的句柄,則pxCreatedTask 可以被設(shè)為NULL。-一般應(yīng)用程序中不會(huì)再次改變?nèi)蝿?wù)的優(yōu)先級(jí),或者刪除任務(wù)(除非任務(wù)死掉,刪除后重新建立任務(wù))返回值 有兩個(gè)可能的返回值:1. pdTRUE-表明任務(wù)創(chuàng)建成功。2. err

5、COULD_NOT_ALLOCATE_REQUIRED_MEMORY-由于內(nèi)存堆空間不足,F(xiàn)reeRTOS 無(wú)法分配足夠的空間來(lái)保存任務(wù)結(jié)構(gòu)數(shù)據(jù)和任務(wù)棧,因此無(wú)法創(chuàng)建任務(wù)。int main( void )/* 創(chuàng)建第一個(gè)任務(wù)。需要說(shuō)明的是一個(gè)實(shí)用的應(yīng)用程序中應(yīng)當(dāng)檢測(cè)函數(shù)xTaskCreate()的返回值,以確保任務(wù)創(chuàng)建成功。 */xTaskCreate( vTask1, /* 指向任務(wù)函數(shù)的指針 */Task 1, /* 任務(wù)的文本名字,只會(huì)在調(diào)試中用到 */1000, /* 棧深度 大多數(shù)小型微控制器會(huì)使用的值會(huì)比此值小得多 */NULL, /* 沒(méi)有任務(wù)參數(shù) */1, /* 此任務(wù)運(yùn)行在優(yōu)

6、先級(jí)1上. */NULL ); /* 不會(huì)用到任務(wù)句柄 */xTaskCreate( vTask2, Task 2, 1000, NULL, 1, NULL );/* 啟動(dòng)調(diào)度器,任務(wù)開(kāi)始執(zhí)行 */vTaskStartScheduler();/* 如果一切正常,main()函數(shù)不應(yīng)該會(huì)執(zhí)行到這里。但如果執(zhí)行到這里,很可能是內(nèi)存堆空間不足導(dǎo)致空閑任務(wù)無(wú)法創(chuàng)建。第五章有講述更多關(guān)于內(nèi)存管理方面的信息 */for( ; );1.5 任務(wù)優(yōu)先級(jí)任務(wù)優(yōu)先級(jí)修改函數(shù)vTaskPrioritySet() 應(yīng) 用 程 序 在 文 件 FreeRTOSConfig.h 中設(shè)定的編譯時(shí)配置常量configMAX_

7、PRIORITIES 的值,即是最多可具有的優(yōu)先級(jí)數(shù)目。FreeRTOS 本身并沒(méi)有限定這個(gè)常量的最大值,但這個(gè)值越大,則內(nèi)核花銷的內(nèi)存空間就越多。所以總是建議將此常量設(shè)為能夠用到的最小值。低優(yōu)先級(jí)號(hào)表示任務(wù)的優(yōu)先級(jí)低,優(yōu)先級(jí)號(hào)0 表示最低優(yōu)先級(jí)。有效的優(yōu)先級(jí)號(hào)范圍從0 到(configMAX_PRIORITES 1)。如果被選中的優(yōu)先級(jí)上具有不止一個(gè)任務(wù),調(diào)度器會(huì)讓這些任務(wù)輪流執(zhí)行時(shí)間片的長(zhǎng)度通過(guò)心跳中斷的頻率進(jìn)行設(shè)定,心跳中斷頻率由FreeRTOSConfig.h 中的編譯時(shí)配置常量configTICK_RATE_HZ 進(jìn)行配置。比如說(shuō),如果configTICK_RATE_HZ 設(shè)為100

8、(HZ),則時(shí)間片長(zhǎng)度為10ms常量portTICK_RATE_MS 用于將以心跳為單位的時(shí)間值轉(zhuǎn)化為以毫秒為單位的時(shí)間值。有效精度依賴于系統(tǒng)心跳頻率。1.6 擴(kuò)充“非運(yùn)行態(tài)”阻塞狀態(tài)-如果一個(gè)任務(wù)正在等待某個(gè)事件,則稱這個(gè)任務(wù)處于”阻塞態(tài)(blocked)”。阻塞態(tài)是非運(yùn)行態(tài)的一個(gè)子狀互斥信號(hào)量,因?yàn)槠渲饕糜趯?shí)現(xiàn)互斥訪問(wèn))和互斥量都可以用來(lái)實(shí)現(xiàn)同步事件。掛起狀態(tài)-“掛起(suspended)”也是非運(yùn)行狀態(tài)的子狀態(tài)。處于掛起狀態(tài)的任務(wù)對(duì)調(diào)度器而言是不可見(jiàn)的。讓一個(gè)任務(wù)進(jìn)入掛起狀態(tài)的唯一辦法就是調(diào)用vTaskSuspend() API 函數(shù);而把一個(gè)掛起狀態(tài)的任務(wù)喚醒的唯一途徑就是調(diào)用vTa

9、skResume() 或vTaskResumeFromISR() API 函數(shù)。大多數(shù)應(yīng)用程序中都不會(huì)用到掛起狀態(tài)。就緒狀態(tài)-如果任務(wù)處于非運(yùn)行狀態(tài),但既沒(méi)有阻塞也沒(méi)有掛起,則這個(gè)任務(wù)處于就(ready,準(zhǔn)備或就緒)狀態(tài)。處于就緒態(tài)的任務(wù)能夠被運(yùn)行,但只是”準(zhǔn)備(ready)”運(yùn)行,而當(dāng)前尚未運(yùn)行。void vTaskDelay( portTickType xTicksToDelay )xTicksToDelay 延遲多少個(gè)心跳周期。調(diào)用該延遲函數(shù)的任務(wù)將進(jìn)入阻塞態(tài),經(jīng)延遲指定的心跳周期數(shù)后,再轉(zhuǎn)移到就緒態(tài)。-常數(shù) portTICK_RATE_MS 可以用來(lái)將以毫秒為單位的時(shí)間值轉(zhuǎn)換為以心跳周

10、期為單位的時(shí)間值??臻e任務(wù)是在調(diào)度器啟動(dòng)時(shí)自動(dòng)創(chuàng)建的,以保證至少有一個(gè)任務(wù)可運(yùn)行(至少有一個(gè)任務(wù)處于就緒態(tài))。vTaskDelayUntil() API 函數(shù)原型void vTaskDelayUntil( portTickType * pxPreviousWakeTime, portTickType xTimeIncrement );vTaskDelayUntil()類似于vTaskDelay()。函數(shù)vTaskDelay()的參數(shù)用來(lái)指定任務(wù)在調(diào)用vTaskDelay()到切出阻塞態(tài)整個(gè)過(guò)程包含多少個(gè)心跳周期。任務(wù)保持在阻塞態(tài)的時(shí)間量由vTaskDelay()的入口參數(shù)指定,但任務(wù)離開(kāi)阻塞態(tài)

11、的時(shí)刻實(shí)際上是相對(duì)于vTaskDelay()被調(diào)用那一刻的。vTaskDelayUntil()的參數(shù)就是用來(lái)指定任務(wù)離開(kāi)阻塞態(tài)進(jìn)入就緒態(tài)那一刻的精確心跳計(jì)數(shù)值。API 函數(shù)vTaskDelayUntil()可以用于實(shí)現(xiàn)一個(gè)固定執(zhí)行周期的需求(當(dāng)你需要讓你的任務(wù)以固定頻率周期性執(zhí)行的時(shí)候)。由于調(diào)用此函數(shù)的任務(wù)解除阻塞的時(shí)間是絕對(duì)時(shí)刻,比起相對(duì)于調(diào)用時(shí)刻的相對(duì)時(shí)間更精確(即比調(diào)用vTaskDelay()可以實(shí)現(xiàn)更精確的周期性)。pxPreviousWakeTime 此參數(shù)命名時(shí)假定vTaskDelayUntil()用于實(shí)現(xiàn)某個(gè)任務(wù)以固定頻率周期性執(zhí)行。這種情況下pxPreviousWakeTim

12、e保存了任務(wù)上一次離開(kāi)阻塞態(tài)(被喚醒)的時(shí)刻。這個(gè)時(shí)刻被用作一個(gè)參考點(diǎn)來(lái)計(jì)算該任務(wù)下一次離開(kāi)阻塞態(tài)的時(shí)刻。pxPreviousWakeTime 指向的變量值會(huì)在API 函數(shù)vTaskDelayUntil()調(diào)用過(guò)程中自動(dòng)更新,應(yīng)用程序除了該變量第一次初始化外,通常都不要修改它的值。void vTaskFunction( void *pvParameters )char *pcTaskName;portTickType xLastWakeTime;/* The string to print out is passed in via the parameter. Cast this to ach

13、aracter pointer. */pcTaskName = ( char * ) pvParameters;/* 變量xLastWakeTime需要被初始化為當(dāng)前心跳計(jì)數(shù)值。說(shuō)明一下,這是該變量唯一一次被顯式賦值。之后,xLastWakeTime將在函數(shù)vTaskDelayUntil()中自動(dòng)更新。 */xLastWakeTime = xTaskGetTickCount();/* As per most tasks, this task is implemented in an infinite loop. */for( ; )/* Print out the name of this t

14、ask. */vPrintString( pcTaskName );/* 本任務(wù)將精確的以250毫秒為周期執(zhí)行。同vTaskDelay()函數(shù)一樣,時(shí)間值是以心跳周期為單位的,可以使用常量portTICK_RATE_MS將毫秒轉(zhuǎn)換為心跳周期。變量xLastWakeTime會(huì)在vTaskDelayUntil()中自動(dòng)更新,因此不需要應(yīng)用程序進(jìn)行顯示更新。 */vTaskDelayUntil( &xLastWakeTime, ( 250 / portTICK_RATE_MS ) );1.7 空閑任務(wù)與空閑任務(wù)鉤子函數(shù)當(dāng)調(diào)用vTaskStartScheduler()時(shí),調(diào)度器會(huì)自動(dòng)創(chuàng)建一個(gè)空閑任務(wù)。

15、空閑任務(wù)是一個(gè)非常短小的循環(huán)空閑任務(wù)擁有最低優(yōu)先級(jí)(優(yōu)先級(jí)0)以保證其不會(huì)妨礙具有更高優(yōu)先級(jí)的應(yīng)用任務(wù)進(jìn)入運(yùn)行空閑任務(wù)鉤子函數(shù)通過(guò)空閑任務(wù)鉤子函數(shù)(或稱回調(diào),hook, or call-back),可以直接在空閑任務(wù)中添加應(yīng)用程序相關(guān)的功能??臻e任務(wù)鉤子函數(shù)會(huì)被空閑任務(wù)每循環(huán)一次就自動(dòng)調(diào)用一次。通??臻e任務(wù)鉤子函數(shù)被用于: 執(zhí)行低優(yōu)先級(jí),后臺(tái)或需要不停處理的功能代碼。 測(cè)試處系統(tǒng)處理裕量(空閑任務(wù)只會(huì)在所有其它任務(wù)都不運(yùn)行時(shí)才有機(jī)會(huì)執(zhí)行,所以測(cè)量出空閑任務(wù)占用的處理時(shí)間就可以清楚的知道系統(tǒng)有多少富余的處理時(shí)間)。 將處理器配置到低功耗模式提供一種自動(dòng)省電方法,使得在沒(méi)有任何應(yīng)用功能需要處理的時(shí)

16、候,系統(tǒng)自動(dòng)進(jìn)入省電模式空閑任務(wù)鉤子函數(shù)必須遵從以下規(guī)則1. 絕不能阻或掛起??臻e任務(wù)只會(huì)在其它任務(wù)都不運(yùn)行時(shí)才會(huì)被執(zhí)行(除非有應(yīng)用任務(wù)共享空閑任務(wù)優(yōu)先級(jí))。以任何方式阻塞空閑任務(wù)都可能導(dǎo)致沒(méi)有任務(wù)能夠進(jìn)入運(yùn)行態(tài)!2. 如果應(yīng)用程序用到了 vTaskDelete() AP 函數(shù),則空閑鉤子函數(shù)必須能夠盡快返回。因?yàn)樵谌蝿?wù)被刪除后,空閑任務(wù)負(fù)責(zé)回收內(nèi)核資源。如果空閑任務(wù)一直運(yùn)行在鉤子函數(shù)中,則無(wú)法進(jìn)行回收工作??臻e任務(wù)鉤子函數(shù)的函數(shù)名和函數(shù)原型。void vApplicationIdleHook( void );/* Declare a variable that will be increme

17、nted by the hook function. */unsigned long ulIdleCycleCount = 0UL;/* 空閑鉤子函數(shù)必須命名為vApplicationIdleHook(),無(wú)參數(shù)也無(wú)返回值。 */void vApplicationIdleHook( void )/* This hook function does nothing but increment a counter. */ulIdleCycleCount+;FreeRTOSConfig.h 中的配置常量configUSE_IDLE_HOOK 必須定義為1,這樣空閑任務(wù)鉤子函數(shù)才會(huì)被調(diào)用。void v

18、TaskFunction( void *pvParameters )char *pcTaskName;/* The string to print out is passed in via the parameter. Cast this to acharacter pointer. */pcTaskName = ( char * ) pvParameters;/* As per most tasks, this task is implemented in an infinite loop. */for( ; )/* 打印輸出任務(wù)名,以及調(diào)用計(jì)數(shù)器ulIdleCycleCount的值。 */

19、vPrintStringAndNumber( pcTaskName, ulIdleCycleCount );/* Delay for a period for 250 milliseconds. */vTaskDelay( 250 / portTICK_RATE_MS );1.8 改變?nèi)蝿?wù)優(yōu)先級(jí)vTaskPrioritySet() API 函數(shù)API 函數(shù)vTaskPriofitySet()可以用于在調(diào)度器啟動(dòng)后改變?nèi)魏稳蝿?wù)的優(yōu)先級(jí)。void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )

20、;pxTask 被修改優(yōu)先級(jí)的任務(wù)句柄(即目標(biāo)任務(wù))參考xTaskCreate() API函數(shù)的參數(shù)pxCreatedTask 以了解如何得到任務(wù)句柄方面的信息。任務(wù)可以通過(guò)傳入 NULL 值來(lái)修改自己的優(yōu)先級(jí)。uxNewPriority 目標(biāo)任務(wù)將被設(shè)置到哪個(gè)優(yōu)先級(jí)上。如果設(shè)置的值超過(guò)了最大可用優(yōu)先級(jí)(configMAX_PRIORITIES 1),則會(huì)被自動(dòng)封頂為最大值。常量configMAX_PRIORITIES 是在FreeRTOSConfig.h 頭文件中設(shè)置的一個(gè)編譯時(shí)選項(xiàng)。uxTaskPriorityGet() API 函數(shù)uxTaskPriorityGet() API 函數(shù)用于

21、查詢一個(gè)任務(wù)的優(yōu)先級(jí)。unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );pxTask 被查詢?nèi)蝿?wù)的句柄(目標(biāo)任務(wù)) 參考xTaskCreate() API 函數(shù)的參pxCreatedTask 以了解如何得到任務(wù)句柄方面的信息。任務(wù)可以通過(guò)傳入 NULL 值來(lái)查詢自己的優(yōu)先級(jí)。返回值 被查詢?nèi)蝿?wù)的當(dāng)前優(yōu)先級(jí)。1.9 刪除任務(wù)vTaskDelete() API 函數(shù)函數(shù)原型:void vTaskDelete( xTaskHandle pxTaskToDelete );任務(wù)可以使用 API 函數(shù)vTaskDelete()刪除

22、自己或其它任務(wù)。需要說(shuō)明一點(diǎn),只有內(nèi)核為任務(wù)分配的內(nèi)存空間才會(huì)在任務(wù)被刪除后自動(dòng)回收。任務(wù)自己占用的內(nèi)存或資源需要由應(yīng)用程序自己顯式地釋放。pxTaskToDelete 被刪除任務(wù)的句柄(目標(biāo)任務(wù)) 參考xTaskCreate() API 函數(shù)的參數(shù)pxCreatedTask 以了解如何得到任務(wù)句柄方面的信息。任務(wù)可以通過(guò)傳入 NULL 值來(lái)刪除自己。1.10 調(diào)度算法 簡(jiǎn)述優(yōu)先級(jí)搶占式調(diào)度 每個(gè)任務(wù)都賦予了一個(gè)優(yōu)先級(jí)。 每個(gè)任務(wù)都可以存在于一個(gè)或多個(gè)狀態(tài)。 在任何時(shí)候都只有一個(gè)任務(wù)可以處于運(yùn)行狀態(tài)。 調(diào)度器總是在所有處于就緒態(tài)的任務(wù)中選擇具有最高優(yōu)先級(jí)的任務(wù)來(lái)執(zhí)行。搶占式”是指當(dāng)任務(wù)進(jìn)入就緒

23、態(tài)或是優(yōu)先級(jí)被改變時(shí),如果處于運(yùn)行態(tài)的任務(wù)優(yōu)先級(jí)更低,則該任務(wù)總是搶占當(dāng)前運(yùn)行的任務(wù)。選擇任務(wù)優(yōu)先級(jí)作為一種通用規(guī)則,完成硬實(shí)時(shí)功能的任務(wù)優(yōu)先級(jí)會(huì)高于完成軟件時(shí)功能任務(wù)的優(yōu)先級(jí)。實(shí)現(xiàn)混合調(diào)度方案也是可行的,這需要在中斷服務(wù)例程中顯式地進(jìn)行上下文切換,從而允許同步事件產(chǎn)生搶占行為,但時(shí)間事件卻不行。這樣做的結(jié)果是得到了一個(gè)沒(méi)有時(shí)間片機(jī)制的搶占式系統(tǒng)?;蛟S這正是所期望的,因?yàn)楂@得了效率,并且這也是一種常用的調(diào)度器配置。2.1 概覽基于 FreeRTOS 的應(yīng)用程序由一組獨(dú)立的任務(wù)構(gòu)成每個(gè)任務(wù)都是具有獨(dú)立權(quán)限的小程序。這些獨(dú)立的任務(wù)之間很可能會(huì)通過(guò)相互通信以提供有用的系統(tǒng)功能。FreeRTOS 中所

24、有的通信與同步機(jī)制都是基于隊(duì)列實(shí)現(xiàn)的。2.2 隊(duì)列的特性數(shù)據(jù)存儲(chǔ)隊(duì)列可以保存有限個(gè)具有確定長(zhǎng)度的數(shù)據(jù)單元。隊(duì)列可以保存的最大單元數(shù)目被稱為隊(duì)列的“深度”。在隊(duì)列創(chuàng)建時(shí)需要設(shè)定其深度和每個(gè)單元的大小。通常情況下,隊(duì)列被作為FIFO(先進(jìn)先出)使用,即數(shù)據(jù)由隊(duì)列尾寫入,從隊(duì)列首讀出。當(dāng)然,由隊(duì)列首寫入也是可能的。往隊(duì)列寫入數(shù)據(jù)是通過(guò)字節(jié)拷貝把數(shù)據(jù)復(fù)制存儲(chǔ)到隊(duì)列中;從隊(duì)列讀出數(shù)據(jù)使得把隊(duì)列中的數(shù)據(jù)拷貝刪除。可被多任務(wù)存取隊(duì)列是具有自己獨(dú)立權(quán)限的內(nèi)核對(duì)象,并不屬于或賦予任何任務(wù)。所有任務(wù)都可以向同一隊(duì)列寫入和讀出。一個(gè)隊(duì)列由多方寫入是經(jīng)常的事,但由多方讀出倒是很少遇到。讀隊(duì)列時(shí)阻塞當(dāng)某個(gè)任務(wù)試圖讀一個(gè)

25、隊(duì)列時(shí),其可以指定一個(gè)阻塞超時(shí)時(shí)間。在這段時(shí)間中,如果隊(duì)列為空,該任務(wù)將保持阻塞狀態(tài)以等待隊(duì)列數(shù)據(jù)有效。當(dāng)其它任務(wù)或中斷服務(wù)例程往其等待的隊(duì)列中寫入了數(shù)據(jù),該任務(wù)將自動(dòng)由阻塞態(tài)轉(zhuǎn)移為就緒態(tài)。當(dāng)?shù)却臅r(shí)間超過(guò)了指定的阻塞時(shí)間,即使隊(duì)列中尚無(wú)有效數(shù)據(jù),任務(wù)也會(huì)自動(dòng)從阻塞態(tài)轉(zhuǎn)移為就緒態(tài)。由于隊(duì)列可以被多個(gè)任務(wù)讀取,所以對(duì)單個(gè)隊(duì)列而言,也可能有多個(gè)任務(wù)處于阻塞狀態(tài)以等待隊(duì)列數(shù)據(jù)有效。這種情況下,一旦隊(duì)列數(shù)據(jù)有效,只會(huì)有一個(gè)任務(wù)會(huì)被解除阻塞,這個(gè)任務(wù)就是所有等待任務(wù)中優(yōu)先級(jí)最高的任務(wù)。而如果所有等待任務(wù)的優(yōu)先級(jí)相同,那么被解除阻塞的任務(wù)將是等待最久的任務(wù)。寫隊(duì)列時(shí)阻塞同讀隊(duì)列一樣,任務(wù)也可以在寫隊(duì)列時(shí)指

26、定一個(gè)阻塞超時(shí)時(shí)間。這個(gè)時(shí)間是當(dāng)被寫隊(duì)列已滿時(shí),任務(wù)進(jìn)入阻塞態(tài)以等待隊(duì)列空間有效的最長(zhǎng)時(shí)間。由于隊(duì)列可以被多個(gè)任務(wù)寫入,所以對(duì)單個(gè)隊(duì)列而言,也可能有多個(gè)任務(wù)處于阻塞狀態(tài)以等待隊(duì)列空間有效。這種情況下,一旦隊(duì)列空間有效,只會(huì)有一個(gè)任務(wù)會(huì)被解除阻塞,這個(gè)任務(wù)就是所有等待任務(wù)中優(yōu)先級(jí)最高的任務(wù)。而如果所有等待任務(wù)的優(yōu)先級(jí)相同,那么被解除阻塞的任務(wù)將是等待最久的任務(wù)。2.3 使用隊(duì)列xQueueCreate() API 函數(shù)隊(duì)列在使用前必須先被創(chuàng)建。隊(duì)列由聲明為 xQueueHandle 的變量進(jìn)行引用。xQueueCreate()用于創(chuàng)建一個(gè)隊(duì)列,并返回一個(gè)xQueueHandle 句柄以便于對(duì)其創(chuàng)

27、建的隊(duì)列進(jìn)行引用。當(dāng)創(chuàng)建隊(duì)列時(shí),F(xiàn)reeRTOS 從堆空間中分配內(nèi)存空間。分配的空間用于存儲(chǔ)隊(duì)列數(shù)據(jù)結(jié)構(gòu)本身以及隊(duì)列中包含的數(shù)據(jù)單元。如果內(nèi)存堆中沒(méi)有足夠的空間來(lái)創(chuàng)建隊(duì)列,xQueueCreate()將返回NULL。隊(duì)列創(chuàng)建函數(shù)原型xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );uxQueueLength 隊(duì)列能夠存儲(chǔ)的最大單元數(shù)目,即隊(duì)列深度。uxItemSize 隊(duì)列中數(shù)據(jù)單元的長(zhǎng)度,以字節(jié)為單位。返回值 NULL 表示沒(méi)有足夠的堆空間分

28、配給隊(duì)列而導(dǎo)致創(chuàng)建失敗。非 NULL 值表示隊(duì)列創(chuàng)建成功。此返回值應(yīng)當(dāng)保存下來(lái),以作為操作此隊(duì)列的句柄。xQueueSendToBack() 與 xQueueSendToFront() API 函數(shù)xQueueSendToBack()用于將數(shù)據(jù)發(fā)送到隊(duì)列尾;而xQueueSendToFront()用于將數(shù)據(jù)發(fā)送到隊(duì)列首。xQueueSend()完全等同于xQueueSendToBack()。但 切 記 不 要 在 中 斷 服 務(wù) 例 程 中 調(diào) 用 xQueueSendToFront() 或xQueueSendToBack()。系統(tǒng)提供中斷安全版本的xQueueSendToFrontFromI

29、SR()與xQueueSendToBackFromISR()用于在中斷服務(wù)中實(shí)現(xiàn)相同的功能。 xQueueSendToFront() API函數(shù)原型portBASE_TYPE xQueueSendToFront( xQueueHandle xQueue,const void * pvItemToQueue, portTickType xTicksToWait );xQueueSendToBack() API 函數(shù)原型portBASE_TYPE xQueueSendToBack( xQueueHandle xQueue,const void * pvItemToQueue, portTickTy

30、pe xTicksToWait );xQueue 目標(biāo)隊(duì)列的句柄。這個(gè)句柄即是調(diào)用xQueueCreate()創(chuàng)建該隊(duì)列時(shí)的返回值。pvItemToQueue 發(fā)送數(shù)據(jù)的指針。其指向?qū)⒁獜?fù)制到目標(biāo)隊(duì)列中的數(shù)據(jù)單元。由于在創(chuàng)建隊(duì)列時(shí)設(shè)置了隊(duì)列中數(shù)據(jù)單元的長(zhǎng)度,所以會(huì)從該指針指向的空間復(fù)制對(duì)應(yīng)長(zhǎng)度的數(shù)據(jù)到隊(duì)列的存儲(chǔ)區(qū)域。xTicksToWait 阻塞超時(shí)時(shí)間。如果在發(fā)送時(shí)隊(duì)列已滿,這個(gè)時(shí)間即是任務(wù)處于阻塞態(tài)等待隊(duì)列空間有效的最長(zhǎng)等待時(shí)間。如 果 xTicksToWait 設(shè)為0 , 并且隊(duì)列已滿, 則xQueueSendToFront()與xQueueSendToBack()均會(huì)立即返回。阻塞時(shí)間

31、是以系統(tǒng)心跳周期為單位的,所以絕對(duì)時(shí)間取決于系統(tǒng)心跳頻率。常量portTICK_RATE_MS 可以用來(lái)把心跳時(shí)間單位轉(zhuǎn)換為毫秒時(shí)間單位。如 果 把 xTicksToWait 設(shè)置為portMAX_DELAY , 并且在FreeRTOSConig.h 中設(shè)定INCLUDE_vTaskSuspend 為1,那么阻塞等待將沒(méi)有超時(shí)限制。返回值 有兩個(gè)可能的返回值:1. pdPASS返回pdPASS 只會(huì)有一種情況,那就是數(shù)據(jù)被成功發(fā)送到隊(duì)列中。如果設(shè)定了阻塞超時(shí)時(shí)間(xTicksToWait 非0),在函數(shù)返回之前任務(wù)將被轉(zhuǎn)移到阻塞態(tài)以等待隊(duì)列空間有效在超時(shí)到來(lái)前能夠?qū)?shù)據(jù)成功寫入到隊(duì)列,函數(shù)則會(huì)

32、返回pdPASS。2. errQUEUE_FULL如果由于隊(duì)列已滿而無(wú)法將數(shù)據(jù)寫入, 則將返回errQUEUE_FULL。如果設(shè)定了阻塞超時(shí)時(shí)間(xTicksToWait 非0),在函數(shù)返回之前任務(wù)將被轉(zhuǎn)移到阻塞態(tài)以等待隊(duì)列空間有效。但直到超時(shí)也沒(méi)有其它任務(wù)或是中斷服務(wù)例程讀取隊(duì)列而騰出空間,函數(shù)則會(huì)返回errQUEUE_FULL。xQueueReceive()與xQueuePeek() API 函數(shù)xQueueReceive()用于從隊(duì)列中接收(讀?。?shù)據(jù)單元。接收到的單元同時(shí)會(huì)從隊(duì)列中刪除。xQueuePeek()也是從從隊(duì)列中接收數(shù)據(jù)單元,不同的是并不從隊(duì)列中刪出接收到的單元。xQueu

33、ePeek()從隊(duì)列首接收到數(shù)據(jù)后,不會(huì)修改隊(duì)列中的數(shù)據(jù),也不會(huì)改變數(shù)據(jù)在隊(duì)列中的存儲(chǔ)序順。切記不要在中斷服務(wù)例程中調(diào)用 xQueueRceive()和xQueuePeek()。中斷安全版本的替代API 函數(shù)xQueueReceiveFromISR()xQueueReceive() API 函數(shù)原型portBASE_TYPE xQueueReceive( xQueueHandle xQueue,const void * pvBuffer, portTickType xTicksToWait );xQueuePeek() API 函數(shù)原型portBASE_TYPE xQueuePeek( xQu

34、eueHandle xQueue,const void * pvBuffer,portTickType xTicksToWait );xQueue 被讀隊(duì)列的句柄。這個(gè)句柄即是調(diào)用xQueueCreate()創(chuàng)建該隊(duì)列時(shí)的返回值。pvBuffer 接收緩存指針。其指向一段內(nèi)存區(qū)域,用于接收從隊(duì)列中拷貝來(lái)的數(shù)據(jù)。數(shù)據(jù)單元的長(zhǎng)度在創(chuàng)建隊(duì)列時(shí)就已經(jīng)被設(shè)定,所以該指針指向的內(nèi)存區(qū)域大小應(yīng)當(dāng)足夠保存一個(gè)數(shù)據(jù)單元。xTicksToWait 阻塞超時(shí)時(shí)間。如果在接收時(shí)隊(duì)列為空,則這個(gè)時(shí)間是任務(wù)處于阻塞狀態(tài)以等待隊(duì)列數(shù)據(jù)有效的最長(zhǎng)等待時(shí)間。FreeRTOSConig.h 中設(shè)定INCLUDE_vTaskSus

35、pend 為1,那么阻塞等待將沒(méi)有超時(shí)限制。返回值 有兩個(gè)可能的返回值:1. pdPASS只有一種情況會(huì)返回pdPASS,那就是成功地從隊(duì)列中讀到數(shù)據(jù)。如果設(shè)定了阻塞超時(shí)時(shí)間(xTicksToWait 非0),在函數(shù)返回之前任務(wù)將被轉(zhuǎn)移到阻塞態(tài)以等待隊(duì)列數(shù)據(jù)有效在超時(shí)到來(lái)前能夠從隊(duì)列中成功讀取數(shù)據(jù),函數(shù)則會(huì)返回pdPASS。2. errQUEUE_FULL如果在讀取時(shí)由于隊(duì)列已空而沒(méi)有讀到任何數(shù)據(jù),則將返回errQUEUE_FULL。如果設(shè)定了阻塞超時(shí)時(shí)間(xTicksToWait 非0),在函數(shù)返回之前任務(wù)將被轉(zhuǎn)移到阻塞態(tài)以等待隊(duì)列數(shù)據(jù)有效。但直到超時(shí)也沒(méi)有其它任務(wù)或是中斷服務(wù)例程往隊(duì)列中寫

36、入數(shù)據(jù),函數(shù)則會(huì)返errQUEUE_FULL。uxQueueMessagesWaiting() API 函數(shù)uxQueueMessagesWaiting()用于查詢隊(duì)列中當(dāng)前有效數(shù)據(jù)單元個(gè)數(shù)。切記不要在中斷服務(wù)例程中調(diào)用 uxQueueMessagesWaiting()。應(yīng)當(dāng)在中斷服務(wù)中使用其中斷安全版本uxQueueMessagesWaitingFromISR()。uxQueueMessagesWaiting() API 函數(shù)原型unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle xQueue );xQueue 被查詢隊(duì)列的

37、句柄。這個(gè)句柄即是調(diào)用xQueueCreate()創(chuàng)建該隊(duì)列時(shí)的返回值。返回值 當(dāng)前隊(duì)列中保存的數(shù)據(jù)單元個(gè)數(shù)。返回 0 表明隊(duì)列為空。使用隊(duì)列傳遞復(fù)合數(shù)據(jù)類型一個(gè)任務(wù)從單個(gè)隊(duì)列中接收來(lái)自多個(gè)發(fā)送源的數(shù)據(jù)是經(jīng)常的事。通常接收方收到數(shù)據(jù)后,需要知道數(shù)據(jù)的來(lái)源,并根據(jù)數(shù)據(jù)的來(lái)源決定下一步如何處理。一個(gè)簡(jiǎn)單的方式就是利用隊(duì)列傳遞結(jié)構(gòu)體,結(jié)構(gòu)體成員中就包含了數(shù)據(jù)信息和來(lái)源信息2.4 工作于大型數(shù)據(jù)單元如果隊(duì)列存儲(chǔ)的數(shù)據(jù)單元尺寸較大,那最好是利用隊(duì)列來(lái)傳遞數(shù)據(jù)的指針而不是對(duì)數(shù)據(jù)本身,在隊(duì)列上一字節(jié)一字節(jié)地拷貝進(jìn)或拷貝出。傳遞指針無(wú)論是在處理速度上還是內(nèi)存空間利用上都更有效。但是,當(dāng)你利用隊(duì)列傳遞指針時(shí),一

38、定要十分小心地做到以下兩點(diǎn):1. 指針指向的內(nèi)存空間的所有權(quán)必須明確當(dāng)任務(wù)間通過(guò)指針共享內(nèi)存時(shí),應(yīng)該從根本上保證所不會(huì)有任意兩個(gè)任務(wù)同時(shí)修改共享內(nèi)存中的數(shù)據(jù),或是以其它行為方式使得共享內(nèi)存數(shù)據(jù)無(wú)效或產(chǎn)生一致性問(wèn)題。原則上,共享內(nèi)存在其指針發(fā)送到隊(duì)列之前,其內(nèi)容只允許被發(fā)送任務(wù)訪問(wèn);共享內(nèi)存指針從隊(duì)列中被讀出之后,其內(nèi)容亦只允許被接收任務(wù)訪問(wèn)。2. 指針指向的內(nèi)存空間必須有效,如果指針指向的內(nèi)存空間是動(dòng)態(tài)分配的,只應(yīng)該有一個(gè)任務(wù)負(fù)責(zé)對(duì)其進(jìn)行內(nèi)存釋放。當(dāng)這段內(nèi)存空間被釋放之后,就不應(yīng)該有任何一個(gè)任務(wù)再訪問(wèn)這段空間。3.2 延遲中斷處理在 使 用 信 號(hào) 量 之 前 , 必 須 先 創(chuàng) 建 它 。創(chuàng)

39、建二值信號(hào)量使用vSemaphoreCreateBinary()API 函數(shù)vSemaphoreCreateBinary() API 函數(shù)原型void vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore );xSemaphore 創(chuàng)建的信號(hào)量,需要說(shuō)明的是 vSemaphoreCreateBinary()在實(shí)現(xiàn)上是一個(gè)宏,所以信號(hào)量變量應(yīng)當(dāng)直接傳入,而不是傳址。.xSemaphoreTake() API 函數(shù)“帶走(Taking)”一個(gè)信號(hào)量意為”獲取(Obtain)”或”接收(Receive)”信號(hào)量。只有當(dāng)信號(hào)量有效的時(shí)候才可以被獲取xS

40、emaphoreTake() API 函數(shù)原型portBASE_TYPE xSemaphoreTake( xSemaphoreHandle xSemaphore, portTickType xTicksToWait );xSemaphore 獲取得到的信號(hào)量,信號(hào)量由定義為 xSemaphoreHandle 類型的變量引用。信號(hào)量在使用前必須先創(chuàng)建。xTicksToWait 阻塞超時(shí)時(shí)間。任務(wù)進(jìn)入阻塞態(tài)以等待信號(hào)量有效的最長(zhǎng)時(shí)間。如果xTicksToWait 為0,則xSemaphoreTake()在信號(hào)量無(wú)效時(shí)會(huì)立即返回。阻塞時(shí)間是以系統(tǒng)心跳周期為單位的,所以絕對(duì)時(shí)間取決于系統(tǒng)心跳頻率。常量

41、portTICK_RATE_MS 可以用來(lái)把心跳時(shí)間單位轉(zhuǎn)換為毫秒時(shí)間單位。如 果 把 xTicksToWait 設(shè)置為portMAX_DELAY , 并且在FreeRTOSConig.h 中設(shè)定INCLUDE_vTaskSuspend 為1,那么阻塞等待將沒(méi)有超時(shí)限制。返回值 有兩個(gè)可能的返回值:1. pdPASS只有一種情況會(huì)返回pdPASS,那就是成功獲得信號(hào)量。如果設(shè)定了阻塞超時(shí)時(shí)間(xTicksToWait 非0),在函數(shù)返回之前任務(wù)將被轉(zhuǎn)移到阻塞態(tài)以等待信號(hào)量有效。如果在超時(shí)到來(lái)前信號(hào)量變?yōu)橛行В嗫杀怀晒Λ@取,返回pdPASS。2. pdFALSE未能獲得信號(hào)量。如果設(shè)定了阻塞超

42、時(shí)時(shí)間(xTicksToWait 非0),在函數(shù)返回之前任務(wù)將被轉(zhuǎn)移到阻塞態(tài)以等待信號(hào)量有效。但直到超時(shí)信號(hào)量也沒(méi)有變?yōu)橛行В圆粫?huì)獲得信號(hào)量,返回pdFALSE。除互斥信號(hào)量(Recursive Semaphore,直譯為遞歸信號(hào)量,按通常的說(shuō)法譯為互斥信號(hào)量)外,所有類型的信號(hào)量都可以調(diào)用函數(shù)xSemaphoreTake()來(lái)獲取。xSemaphoreGiveFromISR() API 函數(shù)原型portBASE_TYPE xSemaphoreGiveFromISR( xSemaphoreHandle xSemaphore, portBASE_TYPE *pxHigherPriorityT

43、askWoken );除 互 斥 信 號(hào) 量 外 , FreeRTOS 支持的其它類型的信號(hào)量都可以通過(guò)調(diào)用xSemaphoreGiveFromISR()給出。xSemaphoreGiveFromISR()是xSemaphoreGive()的特殊形式,專門用于中斷服務(wù)例程中。xSemaphore 給出的信號(hào)量信號(hào)量在使用前必須先創(chuàng)建。pxHigherPriorityTaskWoken 對(duì)某個(gè)信號(hào)量而言,可能有不止一個(gè)任務(wù)處于阻塞態(tài)在等待其有效。調(diào)用xSemaphoreGiveFromISR()會(huì)讓信號(hào)量變?yōu)橛行В詴?huì)讓其中一個(gè)等待任務(wù)切出阻塞態(tài)。如果調(diào)用xSemaphoreGiveFromI

44、SR()使得一個(gè)任務(wù)解除阻塞,并且這個(gè)任務(wù)的優(yōu)先級(jí)高于當(dāng)前任務(wù)(也就是被中斷的任務(wù)),那么xSemaphoreGiveFromISR()會(huì)在函數(shù)內(nèi)部將*pxHigherPriorityTaskWoken 設(shè)為pdTRUE。如 果 xSemaphoreGiveFromISR() 將此值設(shè)為pdTRUE,則在中斷退出前應(yīng)當(dāng)進(jìn)行一次上下文切換。這樣才能保證中斷直接返回到就緒態(tài)任務(wù)中優(yōu)先級(jí)最高的任務(wù)中。返回值 有兩個(gè)可能的返回值:1. pdPASSxSemaphoreGiveFromISR()調(diào)用成功。2. pdFAIL如果信號(hào)量已經(jīng)有效,無(wú)法給出,則返回pdFAIL。3.3 計(jì)數(shù)信號(hào)量計(jì)數(shù)信號(hào)量有以

45、下兩種典型用法:1事件計(jì)數(shù)在這種用法中,每次事件發(fā)生時(shí),中斷服務(wù)例程都會(huì)“給出(Give)”信號(hào)量信號(hào)量在每次被給出時(shí)其計(jì)數(shù)值加1。延遲處理任務(wù)每處理一個(gè)任務(wù)都會(huì)”獲取(Take)”一次信號(hào)量信號(hào)量在每次被獲取時(shí)其計(jì)數(shù)值減1。信號(hào)量的計(jì)數(shù)值其實(shí)就是已發(fā)生事件的數(shù)目與已處理事件的數(shù)目之間的差值。用于事件計(jì)數(shù)的計(jì)數(shù)信號(hào)量,在被創(chuàng)建時(shí)其計(jì)數(shù)值被初始化為0。2資源管理在這種用法中,信號(hào)量的計(jì)數(shù)值用于表示可用資源的數(shù)目。一個(gè)任務(wù)要獲取資源的控制權(quán),其必須先獲得信號(hào)量使信號(hào)量的計(jì)數(shù)值減1。當(dāng)計(jì)數(shù)值減至0,則表示沒(méi)有可用資源。當(dāng)任務(wù)利用資源完成工作后,將給出(歸還)信號(hào)量使信號(hào)量的計(jì)數(shù)值加1。用于資源管理的

46、信號(hào)量,在創(chuàng)建時(shí)其計(jì)數(shù)值被初始化為可用資源總數(shù)。xSemaphoreCreateCounting() API 函數(shù)FreeRTOS 中所有種類的信號(hào)量句柄都由聲明為xSemaphoreHandle 類型的變量保存。信號(hào)量在使用前必須先被創(chuàng)建。使用xSemaphoreCreateCounting() API 函數(shù)來(lái)創(chuàng)建一個(gè)計(jì)數(shù)信號(hào)量。xSemaphoreCreateCounting() API 函數(shù)原型xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TY

47、PE uxInitialCount );uxMaxCount 最大計(jì)數(shù)值。如果把計(jì)數(shù)信號(hào)量類比于隊(duì)列的話,uxMaxCount 值就是隊(duì)列的最大深度。當(dāng)此信號(hào)量用于對(duì)事件計(jì)數(shù)或鎖存事件的話,uxMaxCount 就是可鎖存事件的最大數(shù)目。當(dāng)此信號(hào)量用于對(duì)一組資源的訪問(wèn)進(jìn)行管理的話,uxMaxCount 應(yīng)當(dāng)設(shè)置為所有可用資源的總數(shù)。uxInitialCount 信號(hào)量的初始計(jì)數(shù)值。當(dāng)此信號(hào)量用于事件計(jì)數(shù)的話,uxInitialCount 應(yīng)當(dāng)設(shè)置為0因?yàn)楫?dāng)信號(hào)量被創(chuàng)建時(shí),還沒(méi)有事件發(fā)生。當(dāng) 此 信 號(hào) 量 用 于 資 源 管 理 的 話 , uxInitialCount 應(yīng)當(dāng)?shù)扔趗xMaxCo

48、unt因?yàn)楫?dāng)信號(hào)量被創(chuàng)建時(shí),所有的資源都是可用的。返回值如果返回 NULL 值,表示堆上內(nèi)存空間不足,所以FreeRTOS 無(wú)法為信號(hào)量結(jié)構(gòu)分配內(nèi)存導(dǎo)致信號(hào)量創(chuàng)建失敗。如果返回非 NULL 值,則表示信號(hào)量創(chuàng)建成功。此值應(yīng)當(dāng)被保存起來(lái)作為這個(gè)的信號(hào)量的句柄。3.4 在中斷服務(wù)例程中使用隊(duì)列xQueueSendToFrontFromISR(),xQueueSendToBackFromISR()與xQueueReceiveFromISR()分別是xQueueSendToFront(),xQueueSendToBack()與xQueueReceive()的中斷安全版本,專門用于中斷服務(wù)例程中。信號(hào)量

49、用于事件通信。而隊(duì)列不僅可以用于事件通信,還可以用來(lái)傳遞數(shù)據(jù)。 xQueueSendToFrontFromISR() API 函數(shù)原型portBASE_TYPE xQueueSendToFrontFromISR( xQueueHandle xQueue,void *pvItemToQueueportBASE_TYPE *pxHigherPriorityTaskWoken );xQueueSendToBackFromISR() API 函數(shù)原型portBASE_TYPE xQueueSendToBackFromISR( xQueueHandle xQueue,void *pvItemToQueu

50、e portBASE_TYPE *pxHigherPriorityTaskWoken); xQueue 目標(biāo)隊(duì)列的句柄。這個(gè)句柄即是調(diào)用xQueueCreate()創(chuàng)建該隊(duì)列時(shí)的返回值。pvItemToQueue 發(fā)送數(shù)據(jù)的指針。其指向?qū)⒁獜?fù)制到目標(biāo)隊(duì)列中的數(shù)據(jù)單元。由于在創(chuàng)建隊(duì)列時(shí)設(shè)置了隊(duì)列中數(shù)據(jù)單元的長(zhǎng)度,所以會(huì)從該指針指向的空間復(fù)制對(duì)應(yīng)長(zhǎng)度的數(shù)據(jù)到隊(duì)列的存儲(chǔ)區(qū)域。pxHigherPriorityTaskWoken 對(duì)某個(gè)隊(duì)列而言,可能有不止一個(gè)任務(wù)處于阻塞態(tài)在等待其數(shù)據(jù)有效。調(diào)用xQueueSendToFrontFromISR()或xQueueSendToBackFromISR()會(huì)使得

51、隊(duì)列數(shù)據(jù)變?yōu)橛行?,所以?huì)讓其中一個(gè)等待任務(wù)切出阻塞態(tài)。如果調(diào)用這兩個(gè)API 函數(shù)使得一個(gè)任務(wù)解除阻塞,并且這個(gè)任務(wù)的優(yōu)先級(jí)高于當(dāng)前任務(wù)(也就是被中斷的任務(wù)),那么API 會(huì)在函數(shù)內(nèi)部將*pxHigherPriorityTaskWoken 設(shè)為pdTRUE。如果這兩個(gè) API 函數(shù)將此值設(shè)為pdTRUE,則在中斷退出前應(yīng)當(dāng)進(jìn)行一次上下文切換。這樣才能保證中斷直接返回到就緒態(tài)任務(wù)中優(yōu)先級(jí)最高的任務(wù)中。返回值 有兩個(gè)可能的返回值:1. pdPASS返回pdPASS 只會(huì)有一種情況,那就是數(shù)據(jù)被成功發(fā)送到隊(duì)列中。2. errQUEUE_FULL如果由于隊(duì)列已滿而無(wú)法將數(shù)據(jù)寫入,則將返回errQUEUE

52、_FULL。3.5 中斷嵌套最新的 FreeRTOS 移植中允許中斷嵌套。中斷嵌套需要在FreeRTOSConfig.h 中定義表17 詳細(xì)列出的一個(gè)或兩個(gè)常量。configKERNEL_INTERRUPT_PRIORITY 設(shè)置系統(tǒng)心跳時(shí)鐘的中斷優(yōu)先級(jí)。如 果 在 移 植 中 沒(méi) 有 使 用 常 量configMAX_SYSCALL_INTERRUPT_PRIORITY,那么需要調(diào)用中斷安全版FreeRTOS API的中斷都必須運(yùn)行在此優(yōu)先級(jí)上。configMAX_SYSCALL_INTERRUPT_PRIORITY 設(shè)置中斷安全版本FreeRTOS API 可以運(yùn)行的最高中斷優(yōu)先級(jí)。對(duì) A

53、RM Cortex M3 用戶的一點(diǎn)提示Cortex M3 使用低優(yōu)先級(jí)號(hào)數(shù)值表示邏輯上的高優(yōu)先級(jí)中斷。這顯得不是那么直觀,所以很容易被忘記。如果你想對(duì)某個(gè)中斷賦予低優(yōu)先級(jí),則必須使用一個(gè)高優(yōu)先級(jí)號(hào)數(shù)值。千萬(wàn)不要給它指定優(yōu)先級(jí)號(hào)0(或是其它低優(yōu)先級(jí)號(hào)數(shù)值),因?yàn)檫@將會(huì)使得這個(gè)中斷在系統(tǒng)中擁有最高優(yōu)先級(jí) 如果這個(gè)優(yōu)先級(jí)高于configMAX_SYSCALL_INTERRUPT_PRIRITY,將很可能導(dǎo)致系統(tǒng)崩潰。Cortex M3 內(nèi)核的最低優(yōu)先級(jí)為255,但是不同的Cortex M3 處理器廠商實(shí)現(xiàn)的優(yōu)先級(jí)位數(shù)不盡相同,而各自的配套庫(kù)函數(shù)也使用了不同的方式來(lái)支持中斷優(yōu)先級(jí)。比如STM32,S

54、T 的驅(qū)動(dòng)庫(kù)中將最低優(yōu)先級(jí)指定為15,而最高優(yōu)先級(jí)指定為0。第四章 資源管理3. 函數(shù)重入如果一個(gè)函數(shù)可以安全地被多個(gè)任務(wù)調(diào)用,或是在任務(wù)與中斷中均可調(diào)用,則這個(gè)函數(shù)是可重入的。每個(gè)任務(wù)都單獨(dú)維護(hù)自己的??臻g及其自身在的內(nèi)存寄存器組中的值。如果一個(gè)函數(shù)除了訪問(wèn)自己??臻g上分配的數(shù)據(jù)或是內(nèi)核寄存器中的數(shù)據(jù)外,不會(huì)訪問(wèn)其它任何數(shù)據(jù),則這個(gè)函數(shù)就是可重入的?;コ庠L問(wèn)一個(gè)被多任務(wù)共享,或是被任務(wù)與中斷共享的資源時(shí),需要采用”互斥”技術(shù)以保證數(shù)據(jù)在任何時(shí)候都保持一致性。這樣做的目的是要確保任務(wù)從開(kāi)始訪問(wèn)資源就具有排它性,直至這個(gè)資源又恢復(fù)到完整狀態(tài)。FreeRTOS 提供了多種特性用以實(shí)現(xiàn)互斥,但是最好

55、的互斥方法(如果可能的話,任何時(shí)候都當(dāng)如此)還是通過(guò)精心設(shè)計(jì)應(yīng)用程序,盡量不要共享資源,或者是每個(gè)資源都通過(guò)單任務(wù)訪問(wèn)。4.2 臨界區(qū)與掛起調(diào)度器基本臨界區(qū)是指宏 taskENTER_CRITICAL()與taskEXIT_CRITICAL()之間的代碼區(qū)間,程序清單60 是一段范例代碼。Critical Sections 也被稱作Critical Regions。/* 為了保證對(duì)PORTA寄存器的訪問(wèn)不被中斷,將訪問(wèn)操作放入臨界區(qū)。進(jìn)入臨界區(qū) */taskENTER_CRITICAL();/* 在taskENTER_CRITICAL() 與 taskEXIT_CRITICAL()之間不會(huì)切換

56、到其它任務(wù)。 中斷可以執(zhí)行,也允許嵌套,但只是針對(duì)優(yōu)先級(jí)高于configMAX_SYSCALL_INTERRUPT_PRIORITY的中斷 而且這些中斷不允許訪問(wèn)FreeRTOS API 函數(shù). */PORTA |= 0x01;/* 我們已經(jīng)完成了對(duì)PORTA的訪問(wèn),因此可以安全地離開(kāi)臨界區(qū)了。 */taskEXIT_CRITICAL();臨界區(qū)是提供互斥功能的一種非常原始的實(shí)現(xiàn)方法。臨界區(qū)的工作僅僅是簡(jiǎn)單地把中斷全部關(guān)掉,或是關(guān)掉優(yōu)先級(jí)在configMAX_SYSCAL_INTERRUPT_PRIORITY 及以下的中斷依賴于具體使用的FreeRTOS 移植。搶占式上下文切換只可能在某個(gè)中斷中完成,所以調(diào)用taskENTER_CRITICAL()的任務(wù)可以在中斷關(guān)閉的時(shí)段一直保持運(yùn)行態(tài),直到退出臨界區(qū)。臨界區(qū)必須只具有很短的時(shí)間,否則會(huì)反過(guò)來(lái)影響中斷響應(yīng)時(shí)間。在每次調(diào)用taskENTER_CRITICAL()之后,必須盡

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論