【STM32】FreeRTOS系统配置
00. 目錄
文章目錄
- 00. 目錄
- 01. 概述
- 02. FreeRTOS配置文件
- 03. INCLUDE開始的宏
- 04. config開始的宏
- 05. 其它
- 06. 附錄
- 07. 參考
01. 概述
? 在實際使用FreeRTOS的時候,我們常常需要根據自己的需求來配置FreeRTOS,而且不同的架構的MCU在使用的時候配置也不同。FreeRTOS的系統配置文件為FreeRTOSConfig.h,在該配置文件中可以完成FreeRTOS的裁剪和配置,這是非常重要的一個文件。
? FreeRTOS內核是高度可定制的,使用配置文件FreeRTOSConfig.h進行定制。每個FreeRTOS應用都必須包含這個頭文件,用戶根據實際應用來裁剪定制FreeRTOS內核。這個配置文件是針對用戶程序的,而非內核,因此配置文件一般放在應用程序目錄下,不要放在RTOS內核源碼目錄下。
? 在下載的FreeRTOS文件包中,每個演示例程都有一個FreeRTOSConfig.h文件。有些例程的配置文件是比較舊的版本,可能不會包含所有有效選項。如果沒有在配置文件中指定某個選項,那么RTOS內核會使用默認值。典型的FreeRTOSConfig.h配置文件定義如下所示,隨后會說明里面的每一個參數。
02. FreeRTOS配置文件
/** FreeRTOS Kernel V10.4.1* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.** Permission is hereby granted, free of charge, to any person obtaining a copy of* this software and associated documentation files (the "Software"), to deal in* the Software without restriction, including without limitation the rights to* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of* the Software, and to permit persons to whom the Software is furnished to do so,* subject to the following conditions:** The above copyright notice and this permission notice shall be included in all* copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** http://www.FreeRTOS.org* http://aws.amazon.com/freertos** 1 tab == 4 spaces!*/#ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H/*-----------------------------------------------------------* Application specific definitions.** These definitions should be adjusted for your particular hardware and* application requirements.** THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.** See http://www.freertos.org/a00110.html*----------------------------------------------------------*//* Ensure stdint is only used by the compiler, and not the assembler. */ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)#include <stdint.h>extern uint32_t SystemCoreClock; #endif#define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ ( SystemCoreClock ) #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES ( 5 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 10 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 #define configCHECK_FOR_STACK_OVERFLOW 0 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_MALLOC_FAILED_HOOK 0 #define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_COUNTING_SEMAPHORES 1 #define configGENERATE_RUN_TIME_STATS 0/* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )/* Software timer definitions. */ #define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY ( 2 ) #define configTIMER_QUEUE_LENGTH 10 #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskCleanUpResources 1 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1/* Cortex-M specific definitions. */ #ifdef __NVIC_PRIO_BITS/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */#define configPRIO_BITS __NVIC_PRIO_BITS #else#define configPRIO_BITS 4 /* 15 priority levels */ #endif/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf/* The highest interrupt priority that can be used by any interrupt service routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values. */ #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5/* Interrupt priorities used by the kernel port layer itself. These are generic to all Cortex-M ports, and do not rely on any particular library functions. */ #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )/* Normal assert() semantics without relying on the provision of an assert.h header file. */ #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names. */ #define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler //#define xPortSysTickHandler SysTick_Handler#endif /* FREERTOS_CONFIG_H */03. INCLUDE開始的宏
使用“INCLUDE_”開頭的宏用來表示使能或者除能FreeRTOS中相應的API函數,作用就是用來配置FreeRTOS中可選的API函數。比如當宏INCLUDE_vTaskPrioritySet設置為0的時候表示不能使用函數vTaskPrioritySet(),當設置為1的時候就表示可以使用函數vTaskPrioritySet()。這個功能其實就是條件編譯,在tasks.c中有所示的代碼。
/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ #define INCLUDE_vTaskPrioritySet 1 #if ( INCLUDE_vTaskPrioritySet == 1 )void vTaskPrioritySet( TaskHandle_t xTask,UBaseType_t uxNewPriority ){TCB_t * pxTCB;/*此處省略大部分代碼*/}#endif /* INCLUDE_vTaskPrioritySet */3.1 INCLUDE_xTaskAbortDelay
如果要使用函數xTaskAbortDelay()的話將宏INCLUDE_xTaskAbortDelay定義為1。
3.2 INCLUDE_xTaskGetCurrentTaskHandle
如果要使用函數xTaskGetCurrentTaskHandle()的話需要將宏INCLUDE_xTaskGetCurrentTaskHandle定義為。
3.3 INCLUDE_xTaskGetHandle
如果要使用函數xTaskGetHandle的話需要將宏INCLUDE_xTaskGetHandle定義為1。
3.4 INCLUDE_xTaskGetIdleTaskHandle
如果要使用函數xTaskGetIdleTaskHandle()的話需要將宏INCLUDE_xTaskGetIdleTaskHandle定義為1。
3.5 INCLUDE_xTaskGetSchedulerState
如果要使用函數xTaskGetSchedulerState()的話需要將宏INCLUDE_xTaskGetSchedulerState定義為1。
3.6 INCLUDE_uxTaskGetStackHighWaterMark
如果要使用函數uxTaskGetStackHighWaterMark()的話需要將宏INCLUDE_uxTaskGetStackHighWaterMark定義為1。
3.7 INCLUDE_uxTaskPriorityGet
如果要使用函數uxTaskPriorityGet()的話需要將宏INCLUDE_uxTaskPriorityGet定義為1。
3.8 INCLUDE_vTaskPrioritySet
如果要使用函數vTaskPrioritySet()的話需要將宏INCLUDE_vTaskPrioritySet定義為1。
3.9 INCLUDE_xTaskResumeFromISR
如果要使用函數xTaskResumeFromISR()的話需要將宏INCLUDE_xTaskResumeFromISR和INCLUDE_vTaskSuspend都定義為1。
3.10 INCLUDE_eTaskGetState
如果要使用函數eTaskGetState()的話需要將宏INCLUDE_eTaskGetState定義為1.
3.11 INCLUDE_vTaskSuspend
如果要使用函數vTaskSuspend()、vTaskResume()、prvTaskIsTaskSuspended()、XTaskResumeFromISR()的話宏INCLUDE_vTaskSuspend要定義為1.
如果要使用函數xTaskResumeFromISR()的話宏INCLUDE_xTaskResumeFromISR和INCLUDE_vTaskSuspend都必須定義為1.
3.12 INCLUDE_vTaskDelete
如果要使用函數vTaskDelete()就必須將INCLUDE_vTaskDelete該宏設置為1.
3.13 INCLUDE_vTaskCleanUpResources
如果要使用函數vTaskCleanUpResources()函數就需要將宏INCLUDE_vTaskCleanUpResources設置為1.
3.14 INCLUDE_vTaskSuspend
如果要使用函數vTaskSuspend()就需要將宏INCLUDE_vTaskSuspend設置為1.
3.15 INCLUDE_vTaskDelayUntil
如果要使用函數vTaskDelayUntil()就需要將宏INCLUDE_vTaskDelayUntil設置為1.
3.16 INCLUDE_vTaskDelay
如果要使用函數vTaskDelay()就需要將宏INCLUDE_vTaskDelay設置為1.
04. config開始的宏
config開始的宏和INCLUDE開始的宏一樣,都是用來完成FreeRTOS的配置和裁剪的。
4.1 configUSE_PREEMPTION
為1的時候使用搶占式調度器,為0的時候使用協程。如果使用搶占式調度器的話內核會在每個時鐘節拍中斷中進行任務切換,當使用協程的話會在如下地方進行任務切換。
-
一個任務調用了函數taskYIELD()。
-
一個任務調用了可以使任務進入阻塞態的API函數。
-
應用程序明確定義了在中斷中執行上下文切換。
4.2 configUSE_IDLE_HOOK
設置為1使用空閑鉤子(Idle Hook類似于回調函數),0忽略空閑鉤子。
? 當RTOS調度器開始工作后,為了保證至少有一個任務在運行,空閑任務被自動創建,占用最低優先級(0優先級)。對于已經刪除的RTOS任務,空閑任務可以釋放分配給它們的堆棧內存。因此,在應用中應該注意,使用vTaskDelete()函數時要確保空閑任務獲得一定的處理器時間。除此之外,空閑任務沒有其它特殊功能,因此可以任意的剝奪空閑任務的處理器時間。
? 應用程序也可能和空閑任務共享同個優先級。
? 空閑任務鉤子是一個函數,這個函數由用戶來實現,RTOS規定了函數的名字和參數,這個函數在每個空閑任務周期都會被調用。
? 要創建一個空閑鉤子:
這個鉤子函數不可以調用會引起空閑任務阻塞的API函數(例如:vTaskDelay()、帶有阻塞時間的隊列和信號量函數),在鉤子函數內部使用協程是被允許的。
使用空閑鉤子函數設置CPU進入省電模式是很常見的。
4.3 configUSE_TICK_HOOK
設置為1使用時間片鉤子(Tick Hook),0忽略時間片鉤子。
注:時間片鉤子函數(Tick Hook Function)
時間片中斷可以周期性的調用一個被稱為鉤子函數(回調函數)的應用程序。時間片鉤子函數可以很方便的實現一個定時器功能。
只有在FreeRTOSConfig.h中的configUSE_TICK_HOOK設置成1時才可以使用時間片鉤子。一旦此值設置成1,就要定義鉤子函數,函數名和參數如下所示:
void vApplicationTickHook( void );vApplicationTickHook()函數在中斷服務程序中執行,因此這個函數必須非常短小,不能大量使用堆棧,不能調用任何不是以”FromISR" 或 "FROM_ISR”結尾的API函數。
在FreeRTOSVx.x.x\FreeRTOS\Demo\Common\Minimal文件夾下的crhook.c文件中有使用時間片鉤子函數的例程。
4.4 configCPU_CLOCK_HZ
寫入實際的CPU內核時鐘頻率,也就是CPU指令執行頻率,通常稱為Fcclk。配置此值是為了正確的配置系統節拍中斷周期。
4.5 configTICK_RATE_HZ
RTOS 系統節拍中斷的頻率。即一秒中斷的次數,每次中斷RTOS都會進行任務調度。
系統節拍中斷用來測量時間,因此,越高的測量頻率意味著可測到越高的分辨率時間。但是,高的系統節拍中斷頻率也意味著RTOS內核占用更多的CPU時間,因此會降低效率。RTOS演示例程都是使用系統節拍中斷頻率為1000HZ,這是為了測試RTOS內核,比實際使用的要高。(實際使用時不用這么高的系統節拍中斷頻率)
多個任務可以共享一個優先級,RTOS調度器為相同優先級的任務分享CPU時間,在每一個RTOS 系統節拍中斷到來時進行任務切換。高的系統節拍中斷頻率會降低分配給每一個任務的“時間片”持續時間。
設置FreeRTOS的系統時鐘節拍頻率,單位為HZ,此頻率就是抵達定時器的中斷頻率,需要使用此宏來配置滴答定時器的中斷。這里我們一般設置為1000,周期就是1ms。
4.6 configMAX_PRIORITIES
配置應用程序有效的優先級數目。任何數量的任務都可以共享一個優先級,使用協程可以單獨的給與它們優先權。見configMAX_CO_ROUTINE_PRIORITIES。
在RTOS內核中,每個有效優先級都會消耗一定量的RAM,因此這個值不要超過你的應用實際需要的優先級數目。
每一個任務都會被分配一個優先級,優先級值從0~ (configMAX_PRIORITIES - 1)之間。低優先級數表示低優先級任務。空閑任務的優先級為0(tskIDLE_PRIORITY),因此它是最低優先級任務。
FreeRTOS調度器將確保處于就緒狀態(Ready)或運行狀態(Running)的高優先級任務比同樣處于就緒狀態的低優先級任務優先獲取處理器時間。換句話說,處于運行狀態的任務永遠是高優先級任務。
處于就緒狀態的相同優先級任務使用時間片調度機制共享處理器時間。
4.7 configMINIMAL_STACK_SIZE
定義空閑任務使用的堆棧大小。通常此值不應小于對應處理器演示例程文件FreeRTOSConfig.h中定義的數值。
就像xTaskCreate()函數的堆棧大小參數一樣,堆棧大小不是以字節為單位而是以字為單位的,比如在32位架構下,棧大小為100表示棧內存占用400字節的空間。
4.8 configTOTAL_HEAP_SIZE
RTOS內核總計可用的有效的RAM大小。僅在你使用官方下載包中附帶的內存分配策略時,才有可能用到此值。每當創建任務、隊列、互斥量、軟件定時器或信號量時,RTOS內核會為此分配RAM,這里的RAM都屬于configTOTAL_HEAP_SIZE指定的內存區。后續的內存配置會詳細講到官方給出的內存分配策略。
4.9 configMAX_TASK_NAME_LEN
調用任務函數時,需要設置描述任務信息的字符串,這個宏用來定義該字符串的最大長度。這里定義的長度包括字符串結束符’\0’。
4.10 configUSE_TRACE_FACILITY
設置成1表示啟動可視化跟蹤調試,會激活一些附加的結構體成員和函數。
4.11 configUSE_16_BIT_TICKS
定義系統節拍計數器的變量類型,即定義portTickType是表示16位變量還是32位變量。
定義configUSE_16_BIT_TICKS為1意味著portTickType代表16位無符號整形,定義configUSE_16_BIT_TICKS為0意味著portTickType代表32位無符號整形。
使用16位類型可以大大提高8位和16位架構微處理器的性能,但這也限制了最大時鐘計數為65535個’Tick’。因此,如果Tick頻率為250HZ(4MS中斷一次),對于任務最大延時或阻塞時間,16位計數器是262秒,而32位是17179869秒。
4.12 configIDLE_SHOULD_YIELD
這個參數控制任務在空閑優先級中的行為。僅在滿足下列條件后,才會起作用。
通過時間片共享同一個優先級的多個任務,如果共享的優先級大于空閑優先級,并假設沒有更高優先級任務,這些任務應該獲得相同的處理器時間。
但如果共享空閑優先級時,情況會稍微有些不同。當configIDLE_SHOULD_YIELD為1時,其它共享空閑優先級的用戶任務就緒時,空閑任務立刻讓出CPU,用戶任務運行,這樣確保了能最快響應用戶任務。處于這種模式下也會有不良效果(取決于你的程序需要),描述如下:
圖中描述了四個處于空閑優先級的任務,任務A、B和C是用戶任務,任務I是空閑任務。上下文切換周期性的發生在T0、T1…T6時刻。當用戶任務運行時,空閑任務立刻讓出CPU,但是,空閑任務已經消耗了當前時間片中的一定時間。這樣的結果就是空閑任務I和用戶任務A共享一個時間片。用戶任務B和用戶任務C因此獲得了比用戶任務A更多的處理器時間。
可以通過下面方法避免:
- 如果合適的話,將處于空閑優先級的各單獨的任務放置到空閑鉤子函數中;
- 創建的用戶任務優先級大于空閑優先級;
- 設置IDLE_SHOULD_YIELD為0;
設置configIDLE_SHOULD_YIELD為0將阻止空閑任務為用戶任務讓出CPU,直到空閑任務的時間片結束。這確保所有處在空閑優先級的任務分配到相同多的處理器時間,但是,這是以分配給空閑任務更高比例的處理器時間為代價的。
4.13 configUSE_MUTEXES
設置為1表示使用互斥量,設置成0表示忽略互斥量。讀者應該了解在FreeRTOS中互斥量和二進制信號量的區別。
關于互斥量和二進制信號量簡單說:
- 互斥型信號量必須是同一個任務申請,同一個任務釋放,其他任務釋放無效。
- 二進制信號量,一個任務申請成功后,可以由另一個任務釋放。
- 互斥型信號量是二進制信號量的子集
4.14 configQUEUE_REGISTRY_SIZE
隊列記錄有兩個目的,都涉及到RTOS內核的調試:
除了進行內核調試外,隊列記錄沒有其它任何目的。
configQUEUE_REGISTRY_SIZE定義可以記錄的隊列和信號量的最大數目。如果你想使用RTOS內核調試器查看隊列和信號量信息,則必須先將這些隊列和信號量進行注冊,只有注冊后的隊列和信號量才可以使用RTOS內核調試器查看。查看API參考手冊中的vQueueAddToRegistry() 和vQueueUnregisterQueue()函數獲取更多信息。
4.15 configCHECK_FOR_STACK_OVERFLOW
每個任務維護自己的棧空間,任務創建時會自動分配任務需要的占內存,分配內存大小由創建任務函數(xTaskCreate())的一個參數指定。堆棧溢出是設備運行不穩定的最常見原因,因此FreeeRTOS提供了兩個可選機制用來輔助檢測和改正堆棧溢出。配置宏configCHECK_FOR_STACK_OVERFLOW為不同的常量來使用不同堆棧溢出檢測機制。
注意,這個選項僅適用于內存映射未分段的微處理器架構。并且,在RTOS檢測到堆棧溢出發生之前,一些處理器可能先產生故障(fault)或異常(exception)來反映堆棧使用的惡化。如果宏configCHECK_FOR_STACK_OVERFLOW沒有設置成0,用戶必須提供一個棧溢出鉤子函數,這個鉤子函數的函數名和參數必須如下所示:
void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName );參數xTask和pcTaskName為堆棧溢出任務的句柄和名字。請注意,如果溢出非常嚴重,這兩個參數信息也可能是錯誤的!在這種情況下,可以直接檢查pxCurrentTCb變量。
推薦僅在開發或測試階段使用棧溢出檢查,因為堆棧溢出檢測會增大上下文切換開銷。
任務切換出去后,該任務的上下文環境被保存到自己的堆棧空間,這時很可能堆棧的使用量達到了最大(最深)值。在這個時候,RTOS內核會檢測堆棧指針是否還指向有效的堆棧空間。如果堆棧指針指向了有效堆棧空間之外的地方,堆棧溢出鉤子函數會被調用。
這個方法速度很快,但是不能檢測到所有堆棧溢出情況(比如,堆棧溢出沒有發生在上下文切換時)。設置configCHECK_FOR_STACK_OVERFLOW為1會使用這種方法。
當堆棧首次創建時,在它的堆棧區中填充一些已知值(標記)。當任務切換時,RTOS內核會檢測堆棧最后的16個字節,確保標記數據沒有被覆蓋。如果這16個字節有任何一個被改變,則調用堆棧溢出鉤子函數。
這個方法比第一種方法要慢,但也相當快了。它能有效捕捉堆棧溢出事件(即使堆棧溢出沒有發生在上下文切換時),但是理論上它也不能百分百的捕捉到所有堆棧溢出(比如堆棧溢出的值和標記值相同,當然,這種情況發生的概率極小)。
使用這個方法需要設置configCHECK_FOR_STACK_OVERFLOW為2.
4.16 configUSE_RECURSIVE_MUTEXES
設置成1表示使用遞歸互斥量,設置成0表示不使用。
4.17 configUSE_MALLOC_FAILED_HOOK
每當一個任務、隊列、信號量被創建時,內核使用一個名為pvPortMalloc()的函數來從堆中分配內存。官方的下載包中包含5個簡單內存分配策略,分別保存在源文件heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c中。 僅當使用這五個簡單策略之一時,宏configUSE_MALLOC_FAILED_HOOK才有意義。
如果定義并正確配置malloc()失敗鉤子函數,則這個函數會在pvPortMalloc()函數返回NULL時被調用。只有FreeRTOS在響應內存分配請求時發現堆內存不足才會返回NULL。
如果宏configUSE_MALLOC_FAILED_HOOK設置為1,那么必須定義一個malloc()失敗鉤子函數,如果宏configUSE_MALLOC_FAILED_HOOK設置為0,malloc()失敗鉤子函數不會被調用,即便已經定義了這個函數。malloc()失敗鉤子函數的函數名和原型必須如下所示:
void vApplicationMallocFailedHook( void);4.18 configUSE_APPLICATION_TASK_TAG
此宏設置為1的話函數configUSE_APPLICATION_TASK_TAGF()和xTaskCallApplicationTaskHook()就會被編譯。
4.19 configUSE_COUNTING_SEMAPHORES
設置成1表示使用計數信號量,設置成0表示不使用。
4.20 configGENERATE_RUN_TIME_STATS
設置宏configGENERATE_RUN_TIME_STATS為1使能運行時間統計功能。一旦設置為1,則下面兩個宏必須被定義:
? 舉一個例子,假如我們配置了一個定時器,每500us中斷一次。在定時器中斷服務例程中簡單的使長整形變量ulHighFrequencyTimerTicks自增。那么上面提到兩個宏定義如下(可以在FreeRTOSConfig.h中添加):
extern volatile unsigned longulHighFrequencyTimerTicks;#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ( ulHighFrequencyTimerTicks = 0UL )#define portGET_RUN_TIME_COUNTER_VALUE() ulHighFrequencyTimerTicks4.21 configUSE_CO_ROUTINES
設置成1表示使用協程,0表示不使用協程。如果使用協程,必須在工程中包含croutine.c文件。
注:協程(Co-routines)主要用于資源發非常受限的嵌入式系統(RAM非常少),通常不會用于32位微處理器。
在當前嵌入式硬件環境下,不建議使用協程,FreeRTOS的開發者早已經停止開發協程。
4.22 configMAX_CO_ROUTINE_PRIORITIES
應用程序協程(Co-routines)的有效優先級數目,任何數目的協程都可以共享一個優先級。使用協程可以單獨的分配給任務優先級。見configMAX_PRIORITIES。
4.23 configUSE_TIMERS
設置成1使用軟件定時器,為0不使用軟件定時器功能。詳細描述見FreeRTOS software timers 。
4.24 configTIMER_TASK_PRIORITY
設置軟件定時器服務/守護進程的優先級。詳細描述見FreeRTOS software timers 。
4.25 configTIMER_QUEUE_LENGTH
設置軟件定時器命令隊列的長度。詳細描述見FreeRTOS software timers。
4.26 configTIMER_TASK_STACK_DEPTH
設置軟件定時器服務/守護進程任務的堆棧深度,詳細描述見FreeRTOS software timers 。
4.27 configKERNEL_INTERRUPT_PRIORITY、configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY
這是移植和應用FreeRTOS出錯最多的地方,所以需要打起精神仔細讀懂。
? Cortex-M3、PIC24、dsPIC、PIC32、SuperH和RX600硬件設備需要設置宏configKERNEL_INTERRUPT_PRIORITY;PIC32、RX600和Cortex-M硬件設備需要設置宏configMAX_SYSCALL_INTERRUPT_PRIORITY。
? configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY,這兩個宏是等價的,后者是前者的新名字,用于更新的移植層代碼。
? 注意下面的描述中,在中斷服務例程中僅可以調用以“FromISR”結尾的API函數。
- 僅需要設置configKERNEL_INTERRUPT_PRIORITY的硬件設備(也就是宏configMAX_SYSCALL_INTERRUPT_PRIORITY不會用到):configKERNEL_INTERRUPT_PRIORITY用來設置RTOS內核自己的中斷優先級。調用API函數的中斷必須運行在這個優先級;不調用API函數的中斷,可以運行在更高的優先級,所以這些中斷不會被因RTOS內核活動而延時。
- configKERNEL_INTERRUPT_PRIORITY和configMAX_SYSCALL_INTERRUPT_PRIORITY都需要設置的硬件設備:configKERNEL_INTERRUPT_PRIORITY用來設置RTOS內核自己的中斷優先級。因為RTOS內核中斷不允許搶占用戶使用的中斷,因此這個宏一般定義為硬件最低優先級。configMAX_SYSCALL_INTERRUPT_PRIORITY用來設置可以在中斷服務程序中安全調用FreeRTOS API函數的最高中斷優先級。優先級小于等于這個宏所代表的優先級時,程序可以在中斷服務程序中安全的調用FreeRTOS API函數;如果優先級大于這個宏所代表的優先級,表示FreeRTOS無法禁止這個中斷,在這個中斷服務程序中絕不可以調用任何API函數。
? 通過設置configMAX_SYSCALL_INTERRUPT_PRIORITY的優先級級別高于configKERNEL_INTERRUPT_PRIORITY可以實現完整的中斷嵌套模式。這意味著FreeRTOS內核不能完全禁止中斷,即使在臨界區。此外,這對于分段內核架構的微處理器是有利的。請注意,當一個新中斷發生后,某些微處理器架構會(在硬件上)禁止中斷,這意味著從硬件響應中斷到FreeRTOS重新使能中斷之間的這段短時間內,中斷是不可避免的被禁止的。
? 不調用API的中斷可以運行在比configMAX_SYSCALL_INTERRUPT_PRIORITY高的優先級,這些級別的中斷不會被FreeRTOS禁止,因此不會因為執行RTOS內核而被延時。
? 例如:假如一個微控制器有8個中斷優先級別:0表示最低優先級,7表示最高優先級(Cortex-M3和Cortex-M4內核優先數和優先級別正好與之相反,后續文章會專門介紹它們)。當兩個配置選項分別為4和0時,下圖描述了每一個優先級別可以和不可做的事件:
- configMAX_SYSCALL_INTERRUPT_PRIORITY=4
- configKERNEL_INTERRUPT_PRIORITY=0
這些配置參數允許非常靈活的中斷處理:
? 在系統中可以像其它任務一樣為中斷處理任務分配優先級。這些任務通過一個相應中斷喚醒。中斷服務例程(ISR)內容應盡可能的精簡—僅用于更新數據然后喚醒高優先級任務。ISR退出后,直接運行被喚醒的任務,因此中斷處理(根據中斷獲取的數據來進行的相應處理)在時間上是連續的,就像ISR在完成這些工作。這樣做的好處是當中斷處理任務執行時,所有中斷都可以處在使能狀態。
? 中斷、中斷服務例程(ISR)和中斷處理任務是三碼事:當中斷來臨時會進入中斷服務例程,中斷服務例程做必要的數據收集(更新),之后喚醒高優先級任務。這個高優先級任務在中斷服務例程結束后立即執行,它可能是其它任務也可能是中斷處理任務,如果是中斷處理任務,那么就可以根據中斷服務例程中收集的數據做相應處理。
? configMAX_SYSCALL_INTERRUPT_PRIORITY接口有著更深一層的意義:在優先級介于RTOS內核中斷優先級(等于configKERNEL_INTERRUPT_PRIORITY)和configMAX_SYSCALL_INTERRUPT_PRIORITY之間的中斷允許全嵌套中斷模式并允許調用API函數。大于configMAX_SYSCALL_INTERRUPT_PRIORITY的中斷優先級絕不會因為執行RTOS內核而延時。
? 運行在大于configMAX_SYSCALL_INTERRUPT_PRIORITY的優先級中斷是不會被RTOS內核所屏蔽的,因此也不受RTOS內核功能影響。這主要用于非常高的實時需求中。比如執行電機轉向。但是,這類中斷的中斷服務例程中絕不可以調用FreeRTOS的API函數。
為了使用這個方案,應用程序要必須符合以下規則:調用FreeRTOS API函數的任何中斷,都必須和RTOS內核處于同一優先級(由宏configKERNEL_INTERRUPT_PRIORITY設置),或者小于等于宏configMAX_SYSCALL_INTERRUPT_PRIORITY定義的優先級。
4.28 configASSERT
斷言,調試時可以檢查傳入的參數是否合法。FreeRTOS內核代碼的關鍵點都會調用configASSERT( x )函數,如果參數x為0,則會拋出一個錯誤。這個錯誤很可能是傳遞給FreeRTOS API函數的無效參數引起的。定義configASSERT()有助于調試時發現錯誤,但是,定義configASSERT()也會增大應用程序代碼量,增大運行時間。推薦在開發階段使用這個斷言宏。
? 舉一個例子,我們想把非法參數所在的文件名和代碼行數打印出來,可以先定義一個函數vAssertCalled,該函數有兩個參數,分別接收觸發configASSERT宏的文件名和該宏所在行,然后通過顯示屏或者串口輸出。代碼如下:
#define configASSERT( ( x ) ) if( ( x ) == 0 )vAssertCalled( __FILE__, __LINE__ )這里__FILE__和__LINE__是大多數編譯器預定義的宏,分別表示代碼所在的文件名(字符串格式)和行數(整形)。
這個例子雖然看起來很簡單,但由于要把整形__LINE__轉換成字符串再顯示,在效率和實現上,都不能讓人滿意。我們可以使用C標準庫assert的實現方法,這樣函數vAssertCalled只需要接收一個字符串形式的參數(推薦仔細研讀下面的代碼并理解其中的技巧):
#define STR(x) VAL(x)#define VAL(x) #x#define configASSERT(x) ((x)?(void) 0 :xAssertCalld(__FILE__ ":" STR(__LINE__) " " #x"\n"))這里稍微講解一下,由于內置宏__LINE__是整數型的而不是字符串型,把它轉化成字符串需要一個額外的處理層。宏STR和和宏VAL正是用來輔助完成這個轉化。宏STR用來把整形行號替換掉__LINE__,宏VAL用來把這個整形行號字符串化。忽略宏STR和VAL中的任何一個,只能得到字符串”LINE”,這不是我們想要的。
? 這里使用三目運算符’?:’來代替參數判斷if語句,這樣可以接受任何參數或表達式,代碼也更緊湊,更重要的是代碼優化度更高,因為如果參數恒為真,在編譯階段就可以去掉不必要的輸出語句。
4.29
4.30
05. 其它
FreeRTOS目錄結構
├─FreeRTOS │ ├─Demo // 各種開發工具的完整Demo,開發者可以方便的以此搭建出自己的項目,甚至直接使用 │ │ ├─Common // 所有例程都可以使用的演示例程文件 │ │ └─其他 // 對應平臺和開發工具的項目例程(命名:平臺_開發工具,例如:CORTEX_M4F_M0_LPC43xx_Keil) │ ├─License // 使用修改過的GPL │ └─Source // FreeRTOS的源碼 │ ├─include // 源碼對應的頭文件 │ └─portable // 每個支持的處理器架構需要一小段與處理器架構相關的RTOS代碼。該目錄下即為和開發平臺相關的代碼 │ ├─MemMang // FreeRTOS內存管理方案(一般要根據平臺來選擇以下5個之一) │ │ heap_1.c │ │ heap_2.c │ │ heap_3.c │ │ heap_4.c │ │ heap_5.c │ └─其他 // 其他開發工具相關的代碼,需要根據自己的開發工具進行選擇 │ croutine.c // 協線程(協程)文件,和任務類似,在系統資源比較缺乏下使用 │ event_groups.c // 事件標志組 │ list.c // 列表結構描述,在內核整體控制上都使用了列表格式數據處理,一切數據結構的基礎 │ queue.c // 隊列,任務和任務之間的通訊處理 │ tasks.c // 所有任務相關函數 │ timers.c // 軟件定時器,以任務形式存在 | stream_buffer.c // 10.0.0 新增 └─FreeRTOS-Plus // FreeRTOS+組件和演示例程FreeRTOS_Config.h文件
#ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H#include "sys.h" #include "usart.h" //針對不同的編譯器調用不同的stdint.h文件 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)#include <stdint.h>extern uint32_t SystemCoreClock; #endif//斷言 #define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int) #define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)/***************************************************************************************************************/ /* FreeRTOS基礎配置配置選項 */ /***************************************************************************************************************/ #define configUSE_PREEMPTION 1 //1使用搶占式內核,0使用協程 #define configUSE_TIME_SLICING 1 //1使能時間片調度(默認式使能的) #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 //1啟用特殊方法來選擇下一個要運行的任務//一般是硬件計算前導零指令,如果所使用的//MCU沒有這些硬件指令的話此宏應該設置為0! #define configUSE_TICKLESS_IDLE 0 //1啟用低功耗tickless模式 #define configUSE_QUEUE_SETS 1 //為1時啟用隊列 #define configCPU_CLOCK_HZ (SystemCoreClock) //CPU頻率 #define configTICK_RATE_HZ (1000) //時鐘節拍頻率,這里設置為1000,周期就是1ms #define configMAX_PRIORITIES (32) //可使用的最大優先級 #define configMINIMAL_STACK_SIZE ((unsigned short)130) //空閑任務使用的堆棧大小 #define configMAX_TASK_NAME_LEN (16) //任務名字字符串長度#define configUSE_16_BIT_TICKS 0 //系統節拍計數器變量數據類型,//1表示為16位無符號整形,0表示為32位無符號整形 #define configIDLE_SHOULD_YIELD 1 //為1時空閑任務放棄CPU使用權給其他同優先級的用戶任務 #define configUSE_TASK_NOTIFICATIONS 1 //為1時開啟任務通知功能,默認開啟 #define configUSE_MUTEXES 1 //為1時使用互斥信號量 #define configQUEUE_REGISTRY_SIZE 8 //不為0時表示啟用隊列記錄,具體的值是可以//記錄的隊列和信號量最大數目。 #define configCHECK_FOR_STACK_OVERFLOW 0 //大于0時啟用堆棧溢出檢測功能,如果使用此功能//用戶必須提供一個棧溢出鉤子函數,如果使用的話//此值可以為1或者2,因為有兩種棧溢出檢測方法。 #define configUSE_RECURSIVE_MUTEXES 1 //為1時使用遞歸互斥信號量 #define configUSE_MALLOC_FAILED_HOOK 0 //1使用內存申請失敗鉤子函數 #define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_COUNTING_SEMAPHORES 1 //為1時使用計數信號量/***************************************************************************************************************/ /* FreeRTOS與內存申請有關配置選項 */ /***************************************************************************************************************/ #define configSUPPORT_DYNAMIC_ALLOCATION 1 //支持動態內存申請 #define configTOTAL_HEAP_SIZE ((size_t)(20*1024)) //系統所有總的堆大小/***************************************************************************************************************/ /* FreeRTOS與鉤子函數有關的配置選項 */ /***************************************************************************************************************/ #define configUSE_IDLE_HOOK 0 //1,使用空閑鉤子;0,不使用 #define configUSE_TICK_HOOK 0 //1,使用時間片鉤子;0,不使用/***************************************************************************************************************/ /* FreeRTOS與運行時間和任務狀態收集有關的配置選項 */ /***************************************************************************************************************/ #define configGENERATE_RUN_TIME_STATS 0 //為1時啟用運行時間統計功能 #define configUSE_TRACE_FACILITY 1 //為1啟用可視化跟蹤調試 #define configUSE_STATS_FORMATTING_FUNCTIONS 1 //與宏configUSE_TRACE_FACILITY同時為1時會編譯下面3個函數//prvWriteNameToBuffer(),vTaskList(),//vTaskGetRunTimeStats()/***************************************************************************************************************/ /* FreeRTOS與協程有關的配置選項 */ /***************************************************************************************************************/ #define configUSE_CO_ROUTINES 0 //為1時啟用協程,啟用協程以后必須添加文件croutine.c #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) //協程的有效優先級數目/***************************************************************************************************************/ /* FreeRTOS與軟件定時器有關的配置選項 */ /***************************************************************************************************************/ #define configUSE_TIMERS 1 //為1時啟用軟件定時器 #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //軟件定時器優先級 #define configTIMER_QUEUE_LENGTH 5 //軟件定時器隊列長度 #define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //軟件定時器任務堆棧大小/***************************************************************************************************************/ /* FreeRTOS可選函數配置選項 */ /***************************************************************************************************************/ #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskCleanUpResources 1 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 #define INCLUDE_eTaskGetState 1 #define INCLUDE_xTimerPendFunctionCall 1/***************************************************************************************************************/ /* FreeRTOS與中斷有關的配置選項 */ /***************************************************************************************************************/ #ifdef __NVIC_PRIO_BITS#define configPRIO_BITS __NVIC_PRIO_BITS #else#define configPRIO_BITS 4 #endif#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中斷最低優先級 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系統可管理的最高中斷優先級 #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )/***************************************************************************************************************/ /* FreeRTOS與中斷服務函數有關的配置選項 */ /***************************************************************************************************************/ #define xPortPendSVHandler PendSV_Handler #define vPortSVCHandler SVC_Handler#endif /* FREERTOS_CONFIG_H */06. 附錄
6.1 【STM32】STM32系列教程匯總
網址:【STM32】STM32系列教程匯總
07. 參考
《FreeRTOS Reference Manual》
《Using the FreeRTOS Real Time Kernel -A Practical Guide》
《The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors,3rd Edition》
總結
以上是生活随笔為你收集整理的【STM32】FreeRTOS系统配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【STM32】FreeRTOS编码风格
- 下一篇: 【STM32】FreeRTOS中断配置