【FreeRTOS學習05】深度解剖FreeRTOSConfig.h實現對系統的自定義剪裁
ROM/RAM太小,因此要對系統進行剪裁;

相關文章
【FreeRTOS實戰匯總】小白博主的RTOS學習實戰快速進階之路(持續更新)
文章目錄
相關文章
1 系統的剪裁
2 FreeRTOSConfig.h
3 應用相關配置
configUSE_PREEMPTION
configMAX_PRIORITIES
configMINIMAL_STACK_SIZE
configUSE_16_BIT_TICKS
configUSE_CO_ROUTINES
configMAX_CO_ROUTINE_PRIORITIES
4 內存管理配置
configSUPPORT_STATIC_ALLOCATION
configSUPPORT_DYNAMIC_ALLOCATION
configTOTAL_HEAP_SIZE
configAPPLICATION_ALLOCATED_HEAP
5 hook 鉤子函數
configUSE_TICK_HOOK
configUSE_IDLE_HOOK
configUSE_MALLOC_FAILED_HOOK
configUSE_DAEMON_TASK_STARTUP_HOOK
6 功能選配
7 總結
1 系統的剪裁
嵌入式系統通常都支持用戶自定義進行剪裁,比較常見的Linux系統通過Kbuild在構建系統的時候進行剪裁,同樣,國產的RT-Thread也支持Kbuild,可以很方便地通過menuconfig進行內核的剪裁,具體如下所示;
另外也支持通過對config文件進行配置,Linux的內核構建過程可以參考文章《探索Linux內核:Kconfig / kbuild的秘密》;
FreeRTOS支持使用FreeRTOSConfig.h配置文件進行定制,下面有幾點需要注意的地方;
每個FreeRTOS應用程序的預處理器必須包含頭文件FreeRTOSConfig.h;
FreeRTOSConfig.h是根據用戶需求而進行定制產生的文件,它應位于應用程序的目錄中,而不是RTOS內核代碼的目錄;
FreeRTOS源碼中的每一個demo程序都有屬于自己的FreeRTOSConfig.h文件,如果一下配置選項被省略,那這些設置為默認值;
用戶通過修改FreeRTOSConfig.h頭文件中的宏定義,從而刪減系統的模塊,設置任務棧空間大小,設置系統分配的堆大小等等,下面配合源碼進行詳細解析。
2 FreeRTOSConfig.h
這里先找到文件FreeRTOSConfig.h,這個FreeRTOS工程是通過CubeIDE進行快速整合的,具體可以參考《【FreeRTOS學習01】CubeIDE快速整合FreeRTOS創建第一個任務》;工程結構如下圖所示;
本文的FreeRTOSConfig.h頭文件是根據集成在CubeIDE中的CubeMX插件自動生成的,源碼如下所示;
#ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H /* Ensure definitions are only used by the compiler, and not by the assembler. */ #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) #include
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
下面將對某些額外需要注意的進行另外注釋;
3 應用相關配置
configUSE_PREEMPTION
這個宏定義來選擇當前系統任務之間的調度算法;
設置為1,則表示選擇RTOS為搶占式調度;
設置為0,則表示調度算法為時間片調度;
通常這里需要設置為搶占式調度,一般設置為1
configMAX_PRIORITIES
應用程序任務可用 的優先級數,任意數量的任務可以共享相同的優先級。協同例程(Co-routines)分別進行優先級排序,可以參考configMAX_CO_ROUTINE_PRIORITIES;
每個可用的優先級都會消耗RTOS內核中的RAM,因此該值不應設置為高于應用程序實際需要的值;
configMINIMAL_STACK_SIZE
空閑任務使用的堆棧大小;通常,不應將此值從演示應用程序隨附的FreeRTOSConfig.h文件中為您所使用的端口設置的值中減少。
xTaskCreate()和 xTaskCreateStatic()函數的堆棧大小參數一樣,
堆棧大小以字而不是字節
,如果放在堆棧上的每個單元都是32位,堆棧大小100則表示 400字節,4bytes等于32bit;
configUSE_16_BIT_TICKS
設置為1:TickType_t被定義(類型定義)為無符號的16位類型;
設置為0:TickType_t被定義(類型定義)為無符號的32位類型;
當系統是8位或16位的結構時,使用這個設置,可以提高能;
configUSE_CO_ROUTINES
設置為1可在構建中包括協同例程功能;
設置為0可從構建中省略協同例程功能;
要包含協例程,必須在項目中包含croutine.c
configMAX_CO_ROUTINE_PRIORITIES
應用程序協同例程可用的優先級數。任意數量的協同例程可以共享相同的優先級。任務分別進行優先級排序-請參閱configMAX_PRIORITIES
4 內存管理配置
configSUPPORT_STATIC_ALLOCATION
設置為1:則可以使用程序中預先分配好的RAM創建RTOS對象;
設置為0:只能使用從FreeRTOS堆分配的RAM創建RTOS對象;
如果未定義configSUPPORT_STATIC_ALLOCATION,則默認為0
如果將configSUPPORT_STATIC_ALLOCATION設置為1
,則應用程序編寫器還必須提供兩個回調函數:- -
vApplicationGetIdleTaskMemory():用于提供RTOS空閑任務的內存;
vApplicationGetTimerTaskMemory():用于提供RTOS守護程序/計時器服務任務(如果configUSE_TIMERS設置為1)的內存: 。
這個在移植的時候可能也會遇到,具體如下所示;
/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an implementation of vApplicationGetIdleTaskMemory() to provide the memory that is used by the Idle task. */ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { /* If the buffers to be provided to the Idle task are declared inside this function then they must be declared static – otherwise they will be allocated on the stack and so not exists after this function exits. */ static StaticTask_t xIdleTaskTCB; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; /* Pass out a pointer to the StaticTask_t structure in which the Idle task’s state will be stored. */ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; /* Pass out the array that will be used as the Idle task’s stack. */ *ppxIdleTaskStackBuffer = uxIdleTaskStack; /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. Note that, as the array is necessarily of type StackType_t, configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } /*———————————————————–*/ /* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the application must provide an implementation of vApplicationGetTimerTaskMemory() to provide the memory that is used by the Timer service task. */ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) { /* If the buffers to be provided to the Timer task are declared inside this function then they must be declared static – otherwise they will be allocated on the stack and so not exists after this function exits. */ static StaticTask_t xTimerTaskTCB; static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; /* Pass out a pointer to the StaticTask_t structure in which the Timer task’s state will be stored. */ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; /* Pass out the array that will be used as the Timer task’s stack. */ *ppxTimerTaskStackBuffer = uxTimerTaskStack; /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. Note that, as the array is necessarily of type StackType_t, configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
configSUPPORT_DYNAMIC_ALLOCATION
設置為1:則可以使用從FreeRTOS堆自動分配的RAM創建RTOS對象;
設置為0:則只能使用應用程序編寫器提供的RAM創建RTOS對象;
如果未定義configSUPPORT_DYNAMIC_ALLOCATION,則默認為1;
configTOTAL_HEAP_SIZE
設置FreeRTOS中堆可用的RAM總量;
僅當configSUPPORT_DYNAMIC_ALLOCATION設置為1;且使用FreeRTOS源代碼下載中提供的示例內存分配方案(heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c)時,才會配置這個值;
configAPPLICATION_ALLOCATED_HEAP
設置為0:FreeRTOS堆由FreeRTOS聲明,并由鏈接器放置在內存中;
設置為1:可以使堆改為由用戶程序進行設置,允許將堆放置在內存中任意位置;
如果使用heap_1.c,heap_2.c或heap_4.c,并且configAPPLICATION_ALLOCATED_HEAP設置為1,那么應用程序編寫器必須提供一個uint8_t數組,其名稱和維數如下所示。
uint8_t ucHeap [configTOTAL_HEAP_SIZE];
該數組將被作為FreeRTOS的堆來使用。如何將數組放置在特定的內存位置取決于所使用的編譯器–請參閱編譯器的文檔。
5 hook 鉤子函數
鉤子函數的本質就是回調函數,有下面四個函數;
configUSE_TICK_HOOK;
configUSE_IDLE_HOOK;
configUSE_MALLOC_FAILED_HOOK;
configUSE_DAEMON_TASK_STARTUP_HOOK;
具體參考hook函數;
configUSE_TICK_HOOK
程序必須為hook函數提供以下原型:
void vApplicationTickHook( void );
configUSE_IDLE_HOOK
configUSE_IDLE_HOOK設置為1,才會調用IDLE_HOOK,設置此選項后,應用程序必須為hook函數提供以下原型:
void vApplicationIdleHook(void);
configUSE_MALLOC_FAILED_HOOK
程序必須為hook函數提供以下原型:
void vApplicationMallocFailedHook( void );
configUSE_DAEMON_TASK_STARTUP_HOOK
RTOS守護程序任務與計時器服務任務相同。有時將其稱為守護程序任務,因為該任務現在不僅用于維護計時器,還用于更多任務。
將configUSE_DAEMON_TASK_STARTUP_HOOK設置為1,則在守護程序任務首次開始執行時,將立即調用守護程序任務啟動鉤子函數。應用程序的初始化代碼如果需要放在該鉤子函數中,則該功能將很有用,這將允許初始化代碼利用RTOS功能。
應用程序編寫器必須使用以下名稱提供原型的“守護程序任務”啟動掛鉤函數的實現。
void vApplicationDaemonTaskStartupHook( void );
6 功能選配
如果以下函數沒有被使用到,已經設置為0,使其不被包含到應用程序中,從而減少程序的應用空間;
#define INCLUDE_vTaskPrioritySet 1 #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskSuspend 1 #define INCLUDE_xResumeFromISR 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 #define INCLUDE_xTaskGetSchedulerState 1 #define INCLUDE_xTaskGetCurrentTaskHandle 1 #define INCLUDE_uxTaskGetStackHighWaterMark 0 #define INCLUDE_xTaskGetIdleTaskHandle 0 #define INCLUDE_eTaskGetState 0 #define INCLUDE_xEventGroupSetBitFromISR 1 #define INCLUDE_xTimerPendFunctionCall 0 #define INCLUDE_xTaskAbortDelay 0 #define INCLUDE_xTaskGetHandle 0 #define INCLUDE_xTaskResumeFromISR 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
7 總結
如果是學習FreRTOS的初期,只需要了解幾個比價關鍵的配置即可,隨著后期對該系統功能了解的深入,在系統的剪裁,RAM和ROM的優化上就可以進一步的了解,另外也可以參考https://www.freertos.org/a00110.html,
嵌入式
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。