久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

FreeRTOS系列第6篇

 SpaceAllen 2018-07-11

FreeRTOS系列第6篇---FreeRTOS內(nèi)核配置說(shuō)明

2015年12月01日 21:14:21
閱讀數(shù):31125

       FreeRTOS內(nèi)核是高度可定制的,,使用配置文件FreeRTOSConfig.h進(jìn)行定制。每個(gè)FreeRTOS應(yīng)用都必須包含這個(gè)頭文件,,用戶根據(jù)實(shí)際應(yīng)用來(lái)裁剪定制FreeRTOS內(nèi)核,。這個(gè)配置文件是針對(duì)用戶程序的,而非內(nèi)核,,因此配置文件一般放在應(yīng)用程序目錄下,,不要放在RTOS內(nèi)核源碼目錄下。

       在下載的FreeRTOS文件包中,,每個(gè)演示例程都有一個(gè)FreeRTOSConfig.h文件,。有些例程的配置文件是比較舊的版本,可能不會(huì)包含所有有效選項(xiàng),。如果沒(méi)有在配置文件中指定某個(gè)選項(xiàng),,那么RTOS內(nèi)核會(huì)使用默認(rèn)值。典型的FreeRTOSConfig.h配置文件定義如下所示,,隨后會(huì)說(shuō)明里面的每一個(gè)參數(shù),。

  1. #ifndef FREERTOS_CONFIG_H
  2. #define FREERTOS_CONFIG_H
  3. /*Here is a good place to include header files that are required across
  4. yourapplication. */
  5. #include "something.h"
  6. #define configUSE_PREEMPTION 1
  7. #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
  8. #define configUSE_TICKLESS_IDLE 0
  9. #define configCPU_CLOCK_HZ 60000000
  10. #define configTICK_RATE_HZ 250
  11. #define configMAX_PRIORITIES 5
  12. #define configMINIMAL_STACK_SIZE 128
  13. #define configTOTAL_HEAP_SIZE 10240
  14. #define configMAX_TASK_NAME_LEN 16
  15. #define configUSE_16_BIT_TICKS 0
  16. #define configIDLE_SHOULD_YIELD 1
  17. #define configUSE_TASK_NOTIFICATIONS 1
  18. #define configUSE_MUTEXES 0
  19. #define configUSE_RECURSIVE_MUTEXES 0
  20. #define configUSE_COUNTING_SEMAPHORES 0
  21. #define configUSE_ALTERNATIVE_API 0/* Deprecated! */
  22. #define configQUEUE_REGISTRY_SIZE 10
  23. #define configUSE_QUEUE_SETS 0
  24. #define configUSE_TIME_SLICING 0
  25. #define configUSE_NEWLIB_REENTRANT 0
  26. #define configENABLE_BACKWARD_COMPATIBILITY 0
  27. #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
  28. /*Hook function related definitions. */
  29. #define configUSE_IDLE_HOOK 0
  30. #define configUSE_TICK_HOOK 0
  31. #define configCHECK_FOR_STACK_OVERFLOW 0
  32. #define configUSE_MALLOC_FAILED_HOOK 0
  33. /*Run time and task stats gathering related definitions. */
  34. #define configGENERATE_RUN_TIME_STATS 0
  35. #define configUSE_TRACE_FACILITY 0
  36. #define configUSE_STATS_FORMATTING_FUNCTIONS 0
  37. /*Co-routine related definitions. */
  38. #define configUSE_CO_ROUTINES 0
  39. #define configMAX_CO_ROUTINE_PRIORITIES 1
  40. /*Software timer related definitions. */
  41. #define configUSE_TIMERS 1
  42. #define configTIMER_TASK_PRIORITY 3
  43. #define configTIMER_QUEUE_LENGTH 10
  44. #define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
  45. /*Interrupt nesting behaviour configuration. */
  46. #define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
  47. #define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
  48. #define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
  49. /*Define to trap errors during development. */
  50. #define configASSERT( ( x ) ) if( ( x ) == 0) vAssertCalled( __FILE__, __LINE__ )
  51. /*FreeRTOS MPU specific definitions. */
  52. #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
  53. /*Optional functions - most linkers will remove unused functions anyway. */
  54. #define INCLUDE_vTaskPrioritySet 1
  55. #define INCLUDE_uxTaskPriorityGet 1
  56. #define INCLUDE_vTaskDelete 1
  57. #define INCLUDE_vTaskSuspend 1
  58. #define INCLUDE_xResumeFromISR 1
  59. #define INCLUDE_vTaskDelayUntil 1
  60. #define INCLUDE_vTaskDelay 1
  61. #define INCLUDE_xTaskGetSchedulerState 1
  62. #define INCLUDE_xTaskGetCurrentTaskHandle 1
  63. #define INCLUDE_uxTaskGetStackHighWaterMark 0
  64. #define INCLUDE_xTaskGetIdleTaskHandle 0
  65. #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
  66. #define INCLUDE_pcTaskGetTaskName 0
  67. #define INCLUDE_eTaskGetState 0
  68. #define INCLUDE_xEventGroupSetBitFromISR 1
  69. #define INCLUDE_xTimerPendFunctionCall 0
  70. /* Aheader file that defines trace macro can be included here. */
  71. #end if/* FREERTOS_CONFIG_H*/

1.configUSE_PREEMPTION

       為1時(shí)RTOS使用搶占式調(diào)度器,為0時(shí)RTOS使用協(xié)作式調(diào)度器(時(shí)間片),。

      注:在多任務(wù)管理機(jī)制上,,操作系統(tǒng)可以分為搶占式和協(xié)作式兩種。協(xié)作式操作系統(tǒng)是任務(wù)主動(dòng)釋放CPU后,,切換到下一個(gè)任務(wù),。任務(wù)切換的時(shí)機(jī)完全取決于正在運(yùn)行的任務(wù)。

2.configUSE_PORT_OPTIMISED_TASK_SELECTION

       某些運(yùn)行FreeRTOS的硬件有兩種方法選擇下一個(gè)要執(zhí)行的任務(wù):通用方法和特定于硬件的方法(以下簡(jiǎn)稱“特殊方法”),。

       通用方法:

  • configUSE_PORT_OPTIMISED_TASK_SELECTION設(shè)置為0或者硬件不支持這種特殊方法,。
  • 可以用于所有FreeRTOS支持的硬件。
  • 完全用C實(shí)現(xiàn),,效率略低于特殊方法,。
  • 不強(qiáng)制要求限制最大可用優(yōu)先級(jí)數(shù)目

       特殊方法:

  • 并非所有硬件都支持,。
  • 必須將configUSE_PORT_OPTIMISED_TASK_SELECTION設(shè)置為1。
  • 依賴一個(gè)或多個(gè)特定架構(gòu)的匯編指令(一般是類似計(jì)算前導(dǎo)零[CLZ]指令),。
  • 比通用方法更高效,。
  • 一般強(qiáng)制限定最大可用優(yōu)先級(jí)數(shù)目為32。

3.configUSE_TICKLESS_IDLE

       設(shè)置configUSE_TICKLESS_IDLE為1使能低功耗tickless模式,,為0保持系統(tǒng)節(jié)拍(tick)中斷一直運(yùn)行,。

       通常情況下,F(xiàn)reeRTOS回調(diào)空閑任務(wù)鉤子函數(shù)(需要設(shè)計(jì)者自己實(shí)現(xiàn)),,在空閑任務(wù)鉤子函數(shù)中設(shè)置微處理器進(jìn)入低功耗模式來(lái)達(dá)到省電的目的,。因?yàn)橄到y(tǒng)要響應(yīng)系統(tǒng)節(jié)拍中斷事件,因此使用這種方法會(huì)周期性的退出,、再進(jìn)入低功耗狀態(tài),。如果系統(tǒng)節(jié)拍中斷頻率過(guò)快,則大部分電能和CPU時(shí)間會(huì)消耗在進(jìn)入和退出低功耗狀態(tài)上,。

       FreeRTOS的tickless空閑模式會(huì)在空閑周期時(shí)停止周期性系統(tǒng)節(jié)拍中斷,。停止周期性系統(tǒng)節(jié)拍中斷可以使微控制器長(zhǎng)時(shí)間處于低功耗模式。移植層需要配置外部喚醒中斷,,當(dāng)喚醒事件到來(lái)時(shí),,將微控制器從低功耗模式喚醒。微控制器喚醒后,,會(huì)重新使能系統(tǒng)節(jié)拍中斷,。由于微控制器在進(jìn)入低功耗后,系統(tǒng)節(jié)拍計(jì)數(shù)器是停止的,,但我們又需要知道這段時(shí)間能折算成多少次系統(tǒng)節(jié)拍中斷周期,,這就需要有一個(gè)不受低功耗影響的外部時(shí)鐘源,即微處理器處于低功耗模式時(shí)它也在計(jì)時(shí)的,,這樣在重啟系統(tǒng)節(jié)拍中斷時(shí)就可以根據(jù)這個(gè)外部計(jì)時(shí)器計(jì)算出一個(gè)調(diào)整值并寫入RTOS 系統(tǒng)節(jié)拍計(jì)數(shù)器變量中,。

4.configUSE_IDLE_HOOK

       設(shè)置為1使用空閑鉤子(Idle Hook類似于回調(diào)函數(shù)),0忽略空閑鉤子,。

       當(dāng)RTOS調(diào)度器開(kāi)始工作后,,為了保證至少有一個(gè)任務(wù)在運(yùn)行,空閑任務(wù)被自動(dòng)創(chuàng)建,,占用最低優(yōu)先級(jí)(0優(yōu)先級(jí)),。對(duì)于已經(jīng)刪除的RTOS任務(wù),空閑任務(wù)可以釋放分配給它們的堆棧內(nèi)存,。因此,,在應(yīng)用中應(yīng)該注意,,使用vTaskDelete()函數(shù)時(shí)要確??臻e任務(wù)獲得一定的處理器時(shí)間。除此之外,空閑任務(wù)沒(méi)有其它特殊功能,,因此可以任意的剝奪空閑任務(wù)的處理器時(shí)間,。

       應(yīng)用程序也可能和空閑任務(wù)共享同個(gè)優(yōu)先級(jí)。

       空閑任務(wù)鉤子是一個(gè)函數(shù),,這個(gè)函數(shù)由用戶來(lái)實(shí)現(xiàn),,RTOS規(guī)定了函數(shù)的名字和參數(shù),這個(gè)函數(shù)在每個(gè)空閑任務(wù)周期都會(huì)被調(diào)用,。

       要?jiǎng)?chuàng)建一個(gè)空閑鉤子:

  1.  設(shè)置FreeRTOSConfig.h 文件中的configUSE_IDLE_HOOK 為1,;
  2.  定義一個(gè)函數(shù),函數(shù)名和參數(shù)如下所示:

void vApplicationIdleHook(void );

       這個(gè)鉤子函數(shù)不可以調(diào)用會(huì)引起空閑任務(wù)阻塞的API函數(shù)(例如:vTaskDelay(),、帶有阻塞時(shí)間的隊(duì)列和信號(hào)量函數(shù)),,在鉤子函數(shù)內(nèi)部使用協(xié)程是被允許的。

       使用空閑鉤子函數(shù)設(shè)置CPU進(jìn)入省電模式是很常見(jiàn)的,。

5.configUSE_MALLOC_FAILED_HOOK

       每當(dāng)一個(gè)任務(wù),、隊(duì)列、信號(hào)量被創(chuàng)建時(shí),,內(nèi)核使用一個(gè)名為pvPortMalloc()的函數(shù)來(lái)從堆中分配內(nèi)存,。官方的下載包中包含5個(gè)簡(jiǎn)單內(nèi)存分配策略,分別保存在源文件heap_1.c,、heap_2.c,、heap_3.c、heap_4.c,、heap_5.c中,。        僅當(dāng)使用這五個(gè)簡(jiǎn)單策略之一時(shí),宏configUSE_MALLOC_FAILED_HOOK才有意義,。

       如果定義并正確配置malloc()失敗鉤子函數(shù),,則這個(gè)函數(shù)會(huì)在pvPortMalloc()函數(shù)返回NULL時(shí)被調(diào)用。只有FreeRTOS在響應(yīng)內(nèi)存分配請(qǐng)求時(shí)發(fā)現(xiàn)堆內(nèi)存不足才會(huì)返回NULL,。

       如果宏configUSE_MALLOC_FAILED_HOOK設(shè)置為1,,那么必須定義一個(gè)malloc()失敗鉤子函數(shù),如果宏configUSE_MALLOC_FAILED_HOOK設(shè)置為0,,malloc()失敗鉤子函數(shù)不會(huì)被調(diào)用,,即便已經(jīng)定義了這個(gè)函數(shù)。malloc()失敗鉤子函數(shù)的函數(shù)名和原型必須如下所示:

void vApplicationMallocFailedHook( void);

6.configUSE_TICK_HOOK

       設(shè)置為1使用時(shí)間片鉤子(Tick Hook),,0忽略時(shí)間片鉤子,。

       注:時(shí)間片鉤子函數(shù)(Tick Hook Function)

       時(shí)間片中斷可以周期性的調(diào)用一個(gè)被稱為鉤子函數(shù)(回調(diào)函數(shù))的應(yīng)用程序。時(shí)間片鉤子函數(shù)可以很方便的實(shí)現(xiàn)一個(gè)定時(shí)器功能,。

       只有在FreeRTOSConfig.h中的configUSE_TICK_HOOK設(shè)置成1時(shí)才可以使用時(shí)間片鉤子,。一旦此值設(shè)置成1,,就要定義鉤子函數(shù),函數(shù)名和參數(shù)如下所示:

void vApplicationTickHook( void );

       vApplicationTickHook()函數(shù)在中斷服務(wù)程序中執(zhí)行,,因此這個(gè)函數(shù)必須非常短小,,不能大量使用堆棧,不能調(diào)用以”FromISR" 或 "FROM_ISR”結(jié)尾的API函數(shù),。

       在FreeRTOSVx.x.x\FreeRTOS\Demo\Common\Minimal文件夾下的crhook.c文件中有使用時(shí)間片鉤子函數(shù)的例程,。

7.configCPU_CLOCK_HZ

       寫入實(shí)際的CPU內(nèi)核時(shí)鐘頻率,也就是CPU指令執(zhí)行頻率,,通常稱為Fcclk,。配置此值是為了正確的配置系統(tǒng)節(jié)拍中斷周期。

8.configTICK_RATE_HZ

       RTOS 系統(tǒng)節(jié)拍中斷的頻率,。即一秒中斷的次數(shù),,每次中斷RTOS都會(huì)進(jìn)行任務(wù)調(diào)度。

系統(tǒng)節(jié)拍中斷用來(lái)測(cè)量時(shí)間,,因此,,越高的測(cè)量頻率意味著可測(cè)到越高的分辨率時(shí)間。但是,,高的系統(tǒng)節(jié)拍中斷頻率也意味著RTOS內(nèi)核占用更多的CPU時(shí)間,,因此會(huì)降低效率。RTOS演示例程都是使用系統(tǒng)節(jié)拍中斷頻率為1000HZ,,這是為了測(cè)試RTOS內(nèi)核,,比實(shí)際使用的要高。(實(shí)際使用時(shí)不用這么高的系統(tǒng)節(jié)拍中斷頻率)

       多個(gè)任務(wù)可以共享一個(gè)優(yōu)先級(jí),,RTOS調(diào)度器為相同優(yōu)先級(jí)的任務(wù)分享CPU時(shí)間,,在每一個(gè)RTOS 系統(tǒng)節(jié)拍中斷到來(lái)時(shí)進(jìn)行任務(wù)切換。高的系統(tǒng)節(jié)拍中斷頻率會(huì)降低分配給每一個(gè)任務(wù)的“時(shí)間片”持續(xù)時(shí)間,。

9.configMAX_PRIORITIES

       配置應(yīng)用程序有效的優(yōu)先級(jí)數(shù)目,。任何數(shù)量的任務(wù)都可以共享一個(gè)優(yōu)先級(jí),使用協(xié)程可以單獨(dú)的給與它們優(yōu)先權(quán),。見(jiàn)configMAX_CO_ROUTINE_PRIORITIES,。

       在RTOS內(nèi)核中,每個(gè)有效優(yōu)先級(jí)都會(huì)消耗一定量的RAM,,因此這個(gè)值不要超過(guò)你的應(yīng)用實(shí)際需要的優(yōu)先級(jí)數(shù)目,。

注:任務(wù)優(yōu)先級(jí)

       每一個(gè)任務(wù)都會(huì)被分配一個(gè)優(yōu)先級(jí),優(yōu)先級(jí)值從0~ (configMAX_PRIORITIES - 1)之間,。低優(yōu)先級(jí)數(shù)表示低優(yōu)先級(jí)任務(wù),。空閑任務(wù)的優(yōu)先級(jí)為0(tskIDLE_PRIORITY),,因此它是最低優(yōu)先級(jí)任務(wù),。

       FreeRTOS調(diào)度器將確保處于就緒狀態(tài)(Ready)或運(yùn)行狀態(tài)(Running)的高優(yōu)先級(jí)任務(wù)比同樣處于就緒狀態(tài)的低優(yōu)先級(jí)任務(wù)優(yōu)先獲取處理器時(shí)間,。換句話說(shuō),處于運(yùn)行狀態(tài)的任務(wù)永遠(yuǎn)是高優(yōu)先級(jí)任務(wù),。

       處于就緒狀態(tài)的相同優(yōu)先級(jí)任務(wù)使用時(shí)間片調(diào)度機(jī)制共享處理器時(shí)間,。

10.configMINIMAL_STACK_SIZE

       定義空閑任務(wù)使用的堆棧大小,。通常此值不應(yīng)小于對(duì)應(yīng)處理器演示例程文件FreeRTOSConfig.h中定義的數(shù)值,。

       就像xTaskCreate()函數(shù)的堆棧大小參數(shù)一樣,堆棧大小不是以字節(jié)為單位而是以字為單位的,,比如在32位架構(gòu)下,,棧大小為100表示棧內(nèi)存占用400字節(jié)的空間。

11.configTOTAL_HEAP_SIZE

       RTOS內(nèi)核總計(jì)可用的有效的RAM大小,。僅在你使用官方下載包中附帶的內(nèi)存分配策略時(shí),,才有可能用到此值。每當(dāng)創(chuàng)建任務(wù),、隊(duì)列,、互斥量、軟件定時(shí)器或信號(hào)量時(shí),,RTOS內(nèi)核會(huì)為此分配RAM,,這里的RAM都屬于configTOTAL_HEAP_SIZE指定的內(nèi)存區(qū)。后續(xù)的內(nèi)存配置會(huì)詳細(xì)講到官方給出的內(nèi)存分配策略,。

12.configMAX_TASK_NAME_LEN

       調(diào)用任務(wù)函數(shù)時(shí),,需要設(shè)置描述任務(wù)信息的字符串,這個(gè)宏用來(lái)定義該字符串的最大長(zhǎng)度,。這里定義的長(zhǎng)度包括字符串結(jié)束符’\0’,。

13.configUSE_TRACE_FACILITY

       設(shè)置成1表示啟動(dòng)可視化跟蹤調(diào)試,會(huì)激活一些附加的結(jié)構(gòu)體成員和函數(shù),。

14.configUSE_STATS_FORMATTING_FUNCTIONS (V7.5.0新增)

       設(shè)置宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS為1會(huì)編譯vTaskList()和vTaskGetRunTimeStats()函數(shù),。如果將這兩個(gè)宏任意一個(gè)設(shè)置為0,上述兩個(gè)函數(shù)不會(huì)被編譯,。

15.configUSE_16_BIT_TICKS

       定義系統(tǒng)節(jié)拍計(jì)數(shù)器的變量類型,,即定義portTickType是表示16位變量還是32位變量。

       定義configUSE_16_BIT_TICKS為1意味著portTickType代表16位無(wú)符號(hào)整形,,定義configUSE_16_BIT_TICKS為0意味著portTickType代表32位無(wú)符號(hào)整形,。

       使用16位類型可以大大提高8位和16位架構(gòu)微處理器的性能,但這也限制了最大時(shí)鐘計(jì)數(shù)為65535個(gè)’Tick’,。因此,,如果Tick頻率為250HZ(4MS中斷一次),對(duì)于任務(wù)最大延時(shí)或阻塞時(shí)間,,16位計(jì)數(shù)器是262秒,,而32位是17179869秒,。

16.configIDLE_SHOULD_YIELD

       這個(gè)參數(shù)控制任務(wù)在空閑優(yōu)先級(jí)中的行為。僅在滿足下列條件后,,才會(huì)起作用,。

  1. 使用搶占式內(nèi)核調(diào)度
  2. 用戶任務(wù)使用空閑優(yōu)先級(jí)。

         通過(guò)時(shí)間片共享同一個(gè)優(yōu)先級(jí)的多個(gè)任務(wù),,如果共享的優(yōu)先級(jí)大于空閑優(yōu)先級(jí),,并假設(shè)沒(méi)有更高優(yōu)先級(jí)任務(wù),這些任務(wù)應(yīng)該獲得相同的處理器時(shí)間,。

         但如果共享空閑優(yōu)先級(jí)時(shí),,情況會(huì)稍微有些不同。當(dāng)configIDLE_SHOULD_YIELD為1時(shí),,其它共享空閑優(yōu)先級(jí)的用戶任務(wù)就緒時(shí),,空閑任務(wù)立刻讓出CPU,用戶任務(wù)運(yùn)行,,這樣確保了能最快響應(yīng)用戶任務(wù),。處于這種模式下也會(huì)有不良效果(取決于你的程序需要),描述如下:

       圖中描述了四個(gè)處于空閑優(yōu)先級(jí)的任務(wù),,任務(wù)A,、B和C是用戶任務(wù),任務(wù)I是空閑任務(wù),。上下文切換周期性的發(fā)生在T0,、T1…T6時(shí)刻。當(dāng)用戶任務(wù)運(yùn)行時(shí),,空閑任務(wù)立刻讓出CPU,,但是,空閑任務(wù)已經(jīng)消耗了當(dāng)前時(shí)間片中的一定時(shí)間,。這樣的結(jié)果就是空閑任務(wù)I和用戶任務(wù)A共享一個(gè)時(shí)間片,。用戶任務(wù)B和用戶任務(wù)C因此獲得了比用戶任務(wù)A更多的處理器時(shí)間。

       可以通過(guò)下面方法避免:

  • 如果合適的話,,將處于空閑優(yōu)先級(jí)的各單獨(dú)的任務(wù)放置到空閑鉤子函數(shù)中,;
  • 創(chuàng)建的用戶任務(wù)優(yōu)先級(jí)大于空閑優(yōu)先級(jí);
  • 設(shè)置IDLE_SHOULD_YIELD為0,;

       設(shè)置configIDLE_SHOULD_YIELD為0將阻止空閑任務(wù)為用戶任務(wù)讓出CPU,,直到空閑任務(wù)的時(shí)間片結(jié)束。這確保所有處在空閑優(yōu)先級(jí)的任務(wù)分配到相同多的處理器時(shí)間,,但是,,這是以分配給空閑任務(wù)更高比例的處理器時(shí)間為代價(jià)的。

17.configUSE_TASK_NOTIFICATIONS(V8.2.0新增)

       設(shè)置宏configUSE_TASK_NOTIFICATIONS為1(或不定義宏configUSE_TASK_NOTIFICATIONS)將會(huì)開(kāi)啟任務(wù)通知功能,有關(guān)的API函數(shù)也會(huì)被編譯,。設(shè)置宏configUSE_TASK_NOTIFICATIONS為0則關(guān)閉任務(wù)通知功能,,相關(guān)API函數(shù)也不會(huì)被編譯。默認(rèn)這個(gè)功能是開(kāi)啟的,。開(kāi)啟后,,每個(gè)任務(wù)多增加8字節(jié)RAM。

       這是個(gè)很有用的特性,,一大亮點(diǎn),。

       每個(gè)RTOS任務(wù)具有一個(gè)32位的通知值,RTOS任務(wù)通知相當(dāng)于直接向任務(wù)發(fā)送一個(gè)事件,,接收到通知的任務(wù)可以解除任務(wù)的阻塞狀態(tài)(因等待任務(wù)通知而進(jìn)入阻塞狀態(tài)),。相對(duì)于以前必須分別創(chuàng)建隊(duì)列,、二進(jìn)制信號(hào)量,、計(jì)數(shù)信號(hào)量或事件組的情況,使用任務(wù)通知顯然更靈活,。更好的是,,相比于使用信號(hào)量解除任務(wù)阻塞,使用任務(wù)通知可以快45%(使用GCC編譯器,,-o2優(yōu)化級(jí)別),。

18.configUSE_MUTEXES

       設(shè)置為1表示使用互斥量,設(shè)置成0表示忽略互斥量,。讀者應(yīng)該了解在FreeRTOS中互斥量和二進(jìn)制信號(hào)量的區(qū)別,。

       關(guān)于互斥量和二進(jìn)制信號(hào)量簡(jiǎn)單說(shuō):

  • 互斥型信號(hào)量必須是同一個(gè)任務(wù)申請(qǐng),同一個(gè)任務(wù)釋放,,其他任務(wù)釋放無(wú)效,。
  • 二進(jìn)制信號(hào)量,一個(gè)任務(wù)申請(qǐng)成功后,,可以由另一個(gè)任務(wù)釋放,。
  • 互斥型信號(hào)量是二進(jìn)制信號(hào)量的子集

19.configUSE_RECURSIVE_MUTEXES

       設(shè)置成1表示使用遞歸互斥量,設(shè)置成0表示不使用,。

20.configUSE_COUNTING_SEMAPHORES

       設(shè)置成1表示使用計(jì)數(shù)信號(hào)量,,設(shè)置成0表示不使用。

21.configUSE_ALTERNATIVE_API

       設(shè)置成1表示使用“替代”隊(duì)列函數(shù)('alternative' queue functions),,設(shè)置成0不使用,。替代API在queue.h頭文件中有詳細(xì)描述。

        注:“替代”隊(duì)列函數(shù)已經(jīng)被棄用,,在新的設(shè)計(jì)中不要使用它,!

22.configCHECK_FOR_STACK_OVERFLOW

       每個(gè)任務(wù)維護(hù)自己的棧空間,,任務(wù)創(chuàng)建時(shí)會(huì)自動(dòng)分配任務(wù)需要的占內(nèi)存,,分配內(nèi)存大小由創(chuàng)建任務(wù)函數(shù)(xTaskCreate())的一個(gè)參數(shù)指定,。堆棧溢出是設(shè)備運(yùn)行不穩(wěn)定的最常見(jiàn)原因,因此FreeeRTOS提供了兩個(gè)可選機(jī)制用來(lái)輔助檢測(cè)和改正堆棧溢出,。配置宏configCHECK_FOR_STACK_OVERFLOW為不同的常量來(lái)使用不同堆棧溢出檢測(cè)機(jī)制,。

       注意,這個(gè)選項(xiàng)僅適用于內(nèi)存映射未分段的微處理器架構(gòu),。并且,,在RTOS檢測(cè)到堆棧溢出發(fā)生之前,一些處理器可能先產(chǎn)生故障(fault)或異常(exception)來(lái)反映堆棧使用的惡化,。如果宏configCHECK_FOR_STACK_OVERFLOW沒(méi)有設(shè)置成0,,用戶必須提供一個(gè)棧溢出鉤子函數(shù),這個(gè)鉤子函數(shù)的函數(shù)名和參數(shù)必須如下所示:

void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName );

       參數(shù)xTask和pcTaskName為堆棧溢出任務(wù)的句柄和名字,。請(qǐng)注意,,如果溢出非常嚴(yán)重,這兩個(gè)參數(shù)信息也可能是錯(cuò)誤的,!在這種情況下,,可以直接檢查pxCurrentTCb變量。

       推薦僅在開(kāi)發(fā)或測(cè)試階段使用棧溢出檢查,,因?yàn)槎褩R绯鰴z測(cè)會(huì)增大上下文切換開(kāi)銷,。

       任務(wù)切換出去后,該任務(wù)的上下文環(huán)境被保存到自己的堆??臻g,,這時(shí)很可能堆棧的使用量達(dá)到了最大(最深)值。在這個(gè)時(shí)候,,RTOS內(nèi)核會(huì)檢測(cè)堆棧指針是否還指向有效的堆??臻g。如果堆棧指針指向了有效堆??臻g之外的地方,,堆棧溢出鉤子函數(shù)會(huì)被調(diào)用。

       這個(gè)方法速度很快,,但是不能檢測(cè)到所有堆棧溢出情況(比如,,堆棧溢出沒(méi)有發(fā)生在上下文切換時(shí))。設(shè)置configCHECK_FOR_STACK_OVERFLOW為1會(huì)使用這種方法,。

       當(dāng)堆棧首次創(chuàng)建時(shí),,在它的堆棧區(qū)中填充一些已知值(標(biāo)記)。當(dāng)任務(wù)切換時(shí),,RTOS內(nèi)核會(huì)檢測(cè)堆棧最后的16個(gè)字節(jié),,確保標(biāo)記數(shù)據(jù)沒(méi)有被覆蓋。如果這16個(gè)字節(jié)有任何一個(gè)被改變,則調(diào)用堆棧溢出鉤子函數(shù),。

       這個(gè)方法比第一種方法要慢,,但也相當(dāng)快了。它能有效捕捉堆棧溢出事件(即使堆棧溢出沒(méi)有發(fā)生在上下文切換時(shí)),,但是理論上它也不能百分百的捕捉到所有堆棧溢出(比如堆棧溢出的值和標(biāo)記值相同,,當(dāng)然,這種情況發(fā)生的概率極?。?。

       使用這個(gè)方法需要設(shè)置configCHECK_FOR_STACK_OVERFLOW為2.

23.configQUEUE_REGISTRY_SIZE

       隊(duì)列記錄有兩個(gè)目的,都涉及到RTOS內(nèi)核的調(diào)試:

  1. 它允許在調(diào)試GUI中使用一個(gè)隊(duì)列的文本名稱來(lái)簡(jiǎn)單識(shí)別隊(duì)列,;
  2. 包含調(diào)試器需要的每一個(gè)記錄隊(duì)列和信號(hào)量定位信息,;

       除了進(jìn)行內(nèi)核調(diào)試外,隊(duì)列記錄沒(méi)有其它任何目的,。

       configQUEUE_REGISTRY_SIZE定義可以記錄的隊(duì)列和信號(hào)量的最大數(shù)目,。如果你想使用RTOS內(nèi)核調(diào)試器查看隊(duì)列和信號(hào)量信息,則必須先將這些隊(duì)列和信號(hào)量進(jìn)行注冊(cè),,只有注冊(cè)后的隊(duì)列和信號(hào)量才可以使用RTOS內(nèi)核調(diào)試器查看,。查看API參考手冊(cè)中的vQueueAddToRegistry() 和vQueueUnregisterQueue()函數(shù)獲取更多信息,。

24.configUSE_QUEUE_SETS

       設(shè)置成1使能隊(duì)列集功能(可以阻塞,、掛起到多個(gè)隊(duì)列和信號(hào)量),設(shè)置成0取消隊(duì)列集功能,。

25.configUSE_TIME_SLICING(V7.5.0新增)

       默認(rèn)情況下(宏configUSE_TIME_SLICING未定義或者宏configUSE_TIME_SLICING設(shè)置為1),,F(xiàn)reeRTOS使用基于時(shí)間片的優(yōu)先級(jí)搶占式調(diào)度器。這意味著RTOS調(diào)度器總是運(yùn)行處于最高優(yōu)先級(jí)的就緒任務(wù),,在每個(gè)RTOS 系統(tǒng)節(jié)拍中斷時(shí)在相同優(yōu)先級(jí)的多個(gè)任務(wù)間進(jìn)行任務(wù)切換,。如果宏configUSE_TIME_SLICING設(shè)置為0,RTOS調(diào)度器仍然總是運(yùn)行處于最高優(yōu)先級(jí)的就緒任務(wù),,但是當(dāng)RTOS 系統(tǒng)節(jié)拍中斷發(fā)生時(shí),,相同優(yōu)先級(jí)的多個(gè)任務(wù)之間不再進(jìn)行任務(wù)切換。

26.configUSE_NEWLIB_REENTRANT(V7.5.0新增)

       如果宏configUSE_NEWLIB_REENTRANT設(shè)置為1,,每一個(gè)創(chuàng)建的任務(wù)會(huì)分配一個(gè)newlib(一個(gè)嵌入式C庫(kù))reent結(jié)構(gòu),。

27.configENABLE_BACKWARD_COMPATIBILITY

       頭文件FreeRTOS.h包含一系列#define宏定義,用來(lái)映射版本V8.0.0和V8.0.0之前版本的數(shù)據(jù)類型名字,。這些宏可以確保RTOS內(nèi)核升級(jí)到V8.0.0或以上版本時(shí),,之前的應(yīng)用代碼不用做任何修改。在FreeRTOSConfig.h文件中設(shè)置宏configENABLE_BACKWARD_COMPATIBILITY為0會(huì)去掉這些宏定義,,并且需要用戶確認(rèn)升級(jí)之前的應(yīng)用沒(méi)有用到這些名字,。

28.configNUM_THREAD_LOCAL_STORAGE_POINTERS

       設(shè)置每個(gè)任務(wù)的線程本地存儲(chǔ)指針數(shù)組大小。

       線程本地存儲(chǔ)允許應(yīng)用程序在任務(wù)的控制塊中存儲(chǔ)一些值,每個(gè)任務(wù)都有自己獨(dú)立的儲(chǔ)存空間,,宏configNUM_THREAD_LOCAL_STORAGE_POINTERS指定每個(gè)任務(wù)線程本地存儲(chǔ)指針數(shù)組的大小,。API函數(shù)vTaskSetThreadLocalStoragePointer()用于向指針數(shù)組中寫入值,API函數(shù)pvTaskGetThreadLocalStoragePointer()用于從指針數(shù)組中讀取值,。

       比如,,許多庫(kù)函數(shù)都包含一個(gè)叫做errno的全局變量。某些庫(kù)函數(shù)使用errno返回庫(kù)函數(shù)錯(cuò)誤信息,,應(yīng)用程序檢查這個(gè)全局變量來(lái)確定發(fā)生了那些錯(cuò)誤,。在單線程程序中,將errno定義成全局變量是可以的,,但是在多線程應(yīng)用中,,每個(gè)線程(任務(wù))必須具有自己獨(dú)有的errno值,否則,,一個(gè)任務(wù)可能會(huì)讀取到另一個(gè)任務(wù)的errno值,。

       FreeRTOS提供了一個(gè)靈活的機(jī)制,使得應(yīng)用程序可以使用線程本地存儲(chǔ)指針來(lái)讀寫線程本地存儲(chǔ),。具體參見(jiàn)后續(xù)文章《FreeRTOS系列第12篇---FreeRTOS任務(wù)應(yīng)用函數(shù)》,。

29.configGENERATE_RUN_TIME_STATS

       設(shè)置宏configGENERATE_RUN_TIME_STATS為1使能運(yùn)行時(shí)間統(tǒng)計(jì)功能。一旦設(shè)置為1,,則下面兩個(gè)宏必須被定義:

  1. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS():用戶程序需要提供一個(gè)基準(zhǔn)時(shí)鐘函數(shù),,函數(shù)完成初始化基準(zhǔn)時(shí)鐘功能,這個(gè)函數(shù)要被define到宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()上,。這是因?yàn)檫\(yùn)行時(shí)間統(tǒng)計(jì)需要一個(gè)比系統(tǒng)節(jié)拍中斷頻率還要高分辨率的基準(zhǔn)定時(shí)器,,否則,統(tǒng)計(jì)可能不精確,?;鶞?zhǔn)定時(shí)器中斷頻率要比統(tǒng)節(jié)拍中斷快10~100倍?;鶞?zhǔn)定時(shí)器中斷頻率越快,,統(tǒng)計(jì)越精準(zhǔn),但能統(tǒng)計(jì)的運(yùn)行時(shí)間也越短(比如,,基準(zhǔn)定時(shí)器10ms中斷一次,,8位無(wú)符號(hào)整形變量可以計(jì)到2.55秒,但如果是1秒中斷一次,,8位無(wú)符號(hào)整形變量可以統(tǒng)計(jì)到255秒),。
  2. portGET_RUN_TIME_COUNTER_VALUE():用戶程序需要提供一個(gè)返回基準(zhǔn)時(shí)鐘當(dāng)前“時(shí)間”的函數(shù),這個(gè)函數(shù)要被define到宏portGET_RUN_TIME_COUNTER_VALUE()上,。

       舉一個(gè)例子,,假如我們配置了一個(gè)定時(shí)器,,每500us中斷一次。在定時(shí)器中斷服務(wù)例程中簡(jiǎn)單的使長(zhǎng)整形變量ulHighFrequencyTimerTicks自增,。那么上面提到兩個(gè)宏定義如下(可以在FreeRTOSConfig.h中添加):

  1. extern volatile unsigned longulHighFrequencyTimerTicks;
  2. #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ( ulHighFrequencyTimerTicks = 0UL )
  3. #define portGET_RUN_TIME_COUNTER_VALUE() ulHighFrequencyTimerTicks

30.configUSE_CO_ROUTINES

       設(shè)置成1表示使用協(xié)程,,0表示不使用協(xié)程。如果使用協(xié)程,,必須在工程中包含croutine.c文件,。

       注:協(xié)程(Co-routines)主要用于資源發(fā)非常受限的嵌入式系統(tǒng)(RAM非常少),通常不會(huì)用于32位微處理器,。

       在當(dāng)前嵌入式硬件環(huán)境下,,不建議使用協(xié)程,F(xiàn)reeRTOS的開(kāi)發(fā)者早已經(jīng)停止開(kāi)發(fā)協(xié)程,。

31.configMAX_CO_ROUTINE_PRIORITIES

       應(yīng)用程序協(xié)程(Co-routines)的有效優(yōu)先級(jí)數(shù)目,,任何數(shù)目的協(xié)程都可以共享一個(gè)優(yōu)先級(jí)。使用協(xié)程可以單獨(dú)的分配給任務(wù)優(yōu)先級(jí),。見(jiàn)configMAX_PRIORITIES,。

32.configUSE_TIMERS

       設(shè)置成1使用軟件定時(shí)器,為0不使用軟件定時(shí)器功能,。詳細(xì)描述見(jiàn)FreeRTOS software timers ,。

33.configTIMER_TASK_PRIORITY

       設(shè)置軟件定時(shí)器服務(wù)/守護(hù)進(jìn)程的優(yōu)先級(jí)。詳細(xì)描述見(jiàn)FreeRTOS software timers ,。

34.configTIMER_QUEUE_LENGTH

       設(shè)置軟件定時(shí)器命令隊(duì)列的長(zhǎng)度,。詳細(xì)描述見(jiàn)FreeRTOS software timers。

35.configTIMER_TASK_STACK_DEPTH

       設(shè)置軟件定時(shí)器服務(wù)/守護(hù)進(jìn)程任務(wù)的堆棧深度,,詳細(xì)描述見(jiàn)FreeRTOS software timers ,。

36.configKERNEL_INTERRUPT_PRIORITY、configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY

       這是移植和應(yīng)用FreeRTOS出錯(cuò)最多的地方,所以需要打起精神仔細(xì)讀懂,。

       Cortex-M3,、PIC24、dsPIC,、PIC32、SuperH和RX600硬件設(shè)備需要設(shè)置宏configKERNEL_INTERRUPT_PRIORITY;PIC32,、RX600和Cortex-M硬件設(shè)備需要設(shè)置宏configMAX_SYSCALL_INTERRUPT_PRIORITY。

       configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY,,這兩個(gè)宏是等價(jià)的,,后者是前者的新名字,用于更新的移植層代碼,。

       注意下面的描述中,,在中斷服務(wù)例程中僅可以調(diào)用以“FromISR”結(jié)尾的API函數(shù),。

  • 僅需要設(shè)置configKERNEL_INTERRUPT_PRIORITY的硬件設(shè)備(也就是宏configMAX_SYSCALL_INTERRUPT_PRIORITY不會(huì)用到):configKERNEL_INTERRUPT_PRIORITY用來(lái)設(shè)置RTOS內(nèi)核自己的中斷優(yōu)先級(jí)。調(diào)用API函數(shù)的中斷必須運(yùn)行在這個(gè)優(yōu)先級(jí),;不調(diào)用API函數(shù)的中斷,,可以運(yùn)行在更高的優(yōu)先級(jí),所以這些中斷不會(huì)被因RTOS內(nèi)核活動(dòng)而延時(shí),。 
  • configKERNEL_INTERRUPT_PRIORITY和configMAX_SYSCALL_INTERRUPT_PRIORITY都需要設(shè)置的硬件設(shè)備:configKERNEL_INTERRUPT_PRIORITY用來(lái)設(shè)置RTOS內(nèi)核自己的中斷優(yōu)先級(jí),。因?yàn)镽TOS內(nèi)核中斷不允許搶占用戶使用的中斷,因此這個(gè)宏一般定義為硬件最低優(yōu)先級(jí),。configMAX_SYSCALL_INTERRUPT_PRIORITY用來(lái)設(shè)置可以在中斷服務(wù)程序中安全調(diào)用FreeRTOS API函數(shù)的最高中斷優(yōu)先級(jí),。優(yōu)先級(jí)小于等于這個(gè)宏所代表的優(yōu)先級(jí)時(shí),程序可以在中斷服務(wù)程序中安全的調(diào)用FreeRTOS API函數(shù),;如果優(yōu)先級(jí)大于這個(gè)宏所代表的優(yōu)先級(jí),,表示FreeRTOS無(wú)法禁止這個(gè)中斷,在這個(gè)中斷服務(wù)程序中絕不可以調(diào)用任何API函數(shù),。

       通過(guò)設(shè)置configMAX_SYSCALL_INTERRUPT_PRIORITY的優(yōu)先級(jí)級(jí)別高于configKERNEL_INTERRUPT_PRIORITY可以實(shí)現(xiàn)完整的中斷嵌套模式,。這意味著FreeRTOS內(nèi)核不能完全禁止中斷,即使在臨界區(qū),。此外,,這對(duì)于分段內(nèi)核架構(gòu)的微處理器是有利的。請(qǐng)注意,,當(dāng)一個(gè)新中斷發(fā)生后,,某些微處理器架構(gòu)會(huì)(在硬件上)禁止中斷,這意味著從硬件響應(yīng)中斷到FreeRTOS重新使能中斷之間的這段短時(shí)間內(nèi),,中斷是不可避免的被禁止的,。

       不調(diào)用API的中斷可以運(yùn)行在比configMAX_SYSCALL_INTERRUPT_PRIORITY高的優(yōu)先級(jí),這些級(jí)別的中斷不會(huì)被FreeRTOS禁止,,因此不會(huì)因?yàn)閳?zhí)行RTOS內(nèi)核而被延時(shí),。

       例如:假如一個(gè)微控制器有8個(gè)中斷優(yōu)先級(jí)別:0表示最低優(yōu)先級(jí),7表示最高優(yōu)先級(jí)(Cortex-M3和Cortex-M4內(nèi)核優(yōu)先數(shù)和優(yōu)先級(jí)別正好與之相反,,后續(xù)文章會(huì)專門介紹它們),。當(dāng)兩個(gè)配置選項(xiàng)分別為4和0時(shí),下圖描述了每一個(gè)優(yōu)先級(jí)別可以和不可做的事件:

  • configMAX_SYSCALL_INTERRUPT_PRIORITY=4
  • configKERNEL_INTERRUPT_PRIORITY=0

 

       這些配置參數(shù)允許非常靈活的中斷處理:

       在系統(tǒng)中可以像其它任務(wù)一樣為中斷處理任務(wù)分配優(yōu)先級(jí),。這些任務(wù)通過(guò)一個(gè)相應(yīng)中斷喚醒,。中斷服務(wù)例程(ISR)內(nèi)容應(yīng)盡可能的精簡(jiǎn)---僅用于更新數(shù)據(jù)然后喚醒高優(yōu)先級(jí)任務(wù)。ISR退出后,,直接運(yùn)行被喚醒的任務(wù),,因此中斷處理(根據(jù)中斷獲取的數(shù)據(jù)來(lái)進(jìn)行的相應(yīng)處理)在時(shí)間上是連續(xù)的,就像ISR在完成這些工作,。這樣做的好處是當(dāng)中斷處理任務(wù)執(zhí)行時(shí),,所有中斷都可以處在使能狀態(tài),。

       中斷、中斷服務(wù)例程(ISR)和中斷處理任務(wù)是三碼事:當(dāng)中斷來(lái)臨時(shí)會(huì)進(jìn)入中斷服務(wù)例程,,中斷服務(wù)例程做必要的數(shù)據(jù)收集(更新),,之后喚醒高優(yōu)先級(jí)任務(wù)。這個(gè)高優(yōu)先級(jí)任務(wù)在中斷服務(wù)例程結(jié)束后立即執(zhí)行,,它可能是其它任務(wù)也可能是中斷處理任務(wù),,如果是中斷處理任務(wù),那么就可以根據(jù)中斷服務(wù)例程中收集的數(shù)據(jù)做相應(yīng)處理,。

       configMAX_SYSCALL_INTERRUPT_PRIORITY接口有著更深一層的意義:在優(yōu)先級(jí)介于RTOS內(nèi)核中斷優(yōu)先級(jí)(等于configKERNEL_INTERRUPT_PRIORITY)和configMAX_SYSCALL_INTERRUPT_PRIORITY之間的中斷允許全嵌套中斷模式并允許調(diào)用API函數(shù),。大于configMAX_SYSCALL_INTERRUPT_PRIORITY的中斷優(yōu)先級(jí)絕不會(huì)因?yàn)閳?zhí)行RTOS內(nèi)核而延時(shí)。

       運(yùn)行在大于configMAX_SYSCALL_INTERRUPT_PRIORITY的優(yōu)先級(jí)中斷是不會(huì)被RTOS內(nèi)核所屏蔽的,,因此也不受RTOS內(nèi)核功能影響,。這主要用于非常高的實(shí)時(shí)需求中。比如執(zhí)行電機(jī)轉(zhuǎn)向,。但是,,這類中斷的中斷服務(wù)例程中絕不可以調(diào)用FreeRTOS的API函數(shù)。

      為了使用這個(gè)方案,,應(yīng)用程序要必須符合以下規(guī)則:調(diào)用FreeRTOS API函數(shù)的任何中斷,,都必須和RTOS內(nèi)核處于同一優(yōu)先級(jí)(由宏configKERNEL_INTERRUPT_PRIORITY設(shè)置),或者小于等于宏configMAX_SYSCALL_INTERRUPT_PRIORITY定義的優(yōu)先級(jí),。

37.configASSERT

       斷言,,調(diào)試時(shí)可以檢查傳入的參數(shù)是否合法。FreeRTOS內(nèi)核代碼的關(guān)鍵點(diǎn)都會(huì)調(diào)用configASSERT( x )函數(shù),,如果參數(shù)x為0,,則會(huì)拋出一個(gè)錯(cuò)誤。這個(gè)錯(cuò)誤很可能是傳遞給FreeRTOS API函數(shù)的無(wú)效參數(shù)引起的,。定義configASSERT()有助于調(diào)試時(shí)發(fā)現(xiàn)錯(cuò)誤,,但是,定義configASSERT()也會(huì)增大應(yīng)用程序代碼量,,增大運(yùn)行時(shí)間,。推薦在開(kāi)發(fā)階段使用這個(gè)斷言宏。

       舉一個(gè)例子,,我們想把非法參數(shù)所在的文件名和代碼行數(shù)打印出來(lái),可以先定義一個(gè)函數(shù)vAssertCalled,,該函數(shù)有兩個(gè)參數(shù),,分別接收觸發(fā)configASSERT宏的文件名和該宏所在行,然后通過(guò)顯示屏或者串口輸出,。代碼如下:

    #define configASSERT( ( x ) )     if( ( x ) == 0 )vAssertCalled( __FILE__, __LINE__ )

       這里__FILE__和__LINE__是大多數(shù)編譯器預(yù)定義的宏,,分別表示代碼所在的文件名(字符串格式)和行數(shù)(整形),。

       這個(gè)例子雖然看起來(lái)很簡(jiǎn)單,但由于要把整形__LINE__轉(zhuǎn)換成字符串再顯示,,在效率和實(shí)現(xiàn)上,,都不能讓人滿意。我們可以使用C標(biāo)準(zhǔn)庫(kù)assert的實(shí)現(xiàn)方法,,這樣函數(shù)vAssertCalled只需要接收一個(gè)字符串形式的參數(shù)(推薦仔細(xì)研讀下面的代碼并理解其中的技巧):

  1. #define STR(x) VAL(x)
  2. #define VAL(x) #x
  3. #define configASSERT(x) ((x)?(void) 0 :xAssertCalld(__FILE__ ":" STR(__LINE__) " " #x"\n"))

       這里稍微講解一下,,由于內(nèi)置宏__LINE__是整數(shù)型的而不是字符串型,把它轉(zhuǎn)化成字符串需要一個(gè)額外的處理層,。宏STR和和宏VAL正是用來(lái)輔助完成這個(gè)轉(zhuǎn)化,。宏STR用來(lái)把整形行號(hào)替換掉__LINE__,宏VAL用來(lái)把這個(gè)整形行號(hào)字符串化,。忽略宏STR和VAL中的任何一個(gè),,只能得到字符串”__LINE__”,這不是我們想要的,。

       這里使用三目運(yùn)算符’?:’來(lái)代替參數(shù)判斷if語(yǔ)句,,這樣可以接受任何參數(shù)或表達(dá)式,代碼也更緊湊,,更重要的是代碼優(yōu)化度更高,,因?yàn)槿绻麉?shù)恒為真,在編譯階段就可以去掉不必要的輸出語(yǔ)句,。

38.INCLUDE Parameters

       以“INCLUDE”起始的宏允許用戶不編譯那些應(yīng)用程序不需要的實(shí)時(shí)內(nèi)核組件(函數(shù)),,這可以確保在你的嵌入式系統(tǒng)中RTOS占用最少的ROM和RAM。

每個(gè)宏以這樣的形式出現(xiàn):

       INCLUDE_FunctionName

      在這里FunctionName表示一個(gè)你可以控制是否編譯的API函數(shù),。如果你想使用該函數(shù),,就將這個(gè)宏設(shè)置成1,如果不想使用,,就將這個(gè)宏設(shè)置成0,。比如,對(duì)于API函數(shù)vTaskDelete():

#define INCLUDE_vTaskDelete    1

       表示希望使用vTaskDelete(),,允許編譯器編譯該函數(shù)

#define INCLUDE_vTaskDelete    0

       表示禁止編譯器編譯該函數(shù),。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多