freeRtos学习笔(1)内核剪裁
freeRtos學習筆記
freeRtos內核剪裁
#define configCPU_CLOCK_HZ
系統主頻
#define configTICK_RATE_HZ
時鐘節拍
#define configTOTAL_HEAP_SIZE
freeRtos使用的堆棧大小,注意cortex系列的內核一般都是雙堆棧指針的,MSP(Main Stack Pointer主堆棧指針)和PSP(Process Stack Pointer)。這種設計非常適合RTOS的設計。MSP顧名思義是給系統棧使用的。PSP是給進程棧使用的。在RTOS運行中,整個棧空間是由PSP管理的,而切換到ISR中則使用MSP。.s文件中的heap只管分配給MSP,而這里的則是分配給PSP。
#define configMINIMAL_STACK_SIZE
空閑任務堆棧大小,單位是字
#define configSUPPORT_DYNAMIC_ALLOCATION
是否使用動態內存分配API,一般使用動態分配,從configTOTAL_HEAP_SIZE中獲取未使用的內存塊進行分配。
#define configSUPPORT_STATIC_ALLOCATION
是否使用靜態內存分配API,一般不使用靜態分配,麻煩
#define configAPPLICATION_ALLOCATED_HEAP
使用動態內存分配時,freeRtos有5種內存分配方式,一般使用heap_4.c文件,該文件開始部分直接定義了一個configTOTAL_HEAP_SIZE大小的數組,用于動態內存分配使用。默認為1,如果為0,則需要用戶自己實現uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]數組,比如使用stm32F4系列單片機,通常使用CCM用作freeRtos的任務堆棧,就可以將此處設置為0,自己定義uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]并通過編譯器的__attribute__((at(n)))指令將數組存放在固定的地址,注意keil的AC6使用__attribute__((section(".ARM._at"#n)))
#define configMAX_PRIORITIES
任務最大優先級數 注意frertos任務優先級越大,優先級越高,空閑任務默認優先級為0.
用戶實際可以使用的優先級范圍是 1 到 configMAX_PRIORITIES – 1
#define configUSE_PREEMPTION
使用搶占式任務調度
#define configUSE_TIME_SLICING
是能時間片
#define configIDLE_SHOULD_YIELD
用戶任務是否可以使用空閑任務優先級,一般不使用
#define configMAX_TASK_NAME_LEN
用戶任務名字最大長度
#define configUSE_16_BIT_TICKS
是否是16位的單片機
#define configUSE_TIMERS
是否使用軟件定時器
#define configTIMER_TASK_PRIORITY
軟件定時器任務優先級
#define configTIMER_QUEUE_LENGTH
軟件定時器隊列長度,軟件定時器可以看作是一個系統任務,軟件定時器的一些API操作可以看作是對該任務發送消息。
#define configTIMER_TASK_STACK_DEPTH
軟件定時器任務堆棧大小
#define configUSE_MUTEXES
是否使用互斥信號量,互斥信號量可以避免優先級反轉,常用于臨界資源的互斥訪問
#define configUSE_RECURSIVE_MUTEXES
是否使用遞歸互斥信號量
#define configUSE_COUNTING_SEMAPHORES
計數信號量,可以當作二值信號量來用,常用于任務間的同步
#define configUSE_QUEUE_SETS
是否使用消息隊列
#define configUSE_TASK_NOTIFICATIONS
是否啟用任務通知功能,可以高效率進行任務間通訊
#define configUSE_TRACE_FACILITY
是否開啟跟蹤調試功能,會激活一些附加的結構體成員和函數,開啟后方便內核調試
#define configUSE_TICKLESS_IDLE
是否開啟低功耗模式
#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP
如果開啟了低功耗模式,除空閑任務外,其他任務在接下來configEXPECTED_IDLE_TIME_BEFORE_SLEEP 個tick時間中均堵塞或者掛起),則會進入低功耗模式
#define configUSE_APPLICATION_TASK_TAG
給任務分配標簽,一般不使用
#define configUSE_NEWLIB_REENTRANT
每個任務創建的時候將分配 Newlib 的重入結構體
#define configUSE_CO_ROUTINES
使用合作式調度,一般不使用
#define configCHECK_FOR_STACK_OVERFLOW
堆棧溢出檢查
-
0不檢查
-
1檢查 在任務切換時檢測任務棧指針是否過界了,如果過界了,在任務切換的時候會觸發棧溢出鉤子函
數。
void vApplicationStackOverflowHook( TaskHandle_t xTask,
signed char *pcTaskName );
用戶可以在鉤子函數里面做一些處理。這種方法不能保證所有的棧溢出都能檢測到。比如任務在執行
的過程中出現過棧溢出。任務切換前棧指針又恢復到了正常水平,這種情況在任務切換的時候是檢測
不到的。又比如任務棧溢出后, 把這部分棧區的數據修改了, 這部分棧區的數據不重要或者暫時沒有
用到還好, 但如果是重要數據被修改將直接導致系統進入硬件異常, 這種情況下,棧溢出檢測功能也
是檢測不到的。 -
2檢查 任務創建的時候將任務棧所有數據初始化為 0xa5,任務切換時進行任務棧檢測的時候會檢測末
尾的 16 個字節是否都是 0xa5,通過這種方式來檢測任務棧是否溢出了。相比方法一, 這種方法的速
度稍慢些, 但是這樣就有效地避免了方法一里面的部分情況。 不過依然不能保證所有的棧溢出都能檢
測到,比如任務棧末尾的 16 個字節沒有用到, 即沒有被修改,但是任務棧已經溢出了, 這種情況是
檢測不到的。 另外任務棧溢出后, 任務棧末尾的 16 個字節沒有修改,但是溢出部分的棧區數據被修
改了, 這部分棧區的數據不重要或者暫時沒有用到還好, 但如果是重要數據被修改將直接導致系統進
入硬件異常, 這種情況下,棧溢出檢測功能也是檢測不到的。
#define configQUEUE_REGISTRY_SIZE
設置可以注冊的信號量和消息隊列個數。內核調試時使用,如果不進行內核調試,沒有作用。
#define configASSERT( x )
斷言
#define configUSE_IDLE_HOOK
空閑任務回調函數使能,發生空閑任務時,是否調用vApplicationIdleHook(void)函數,注意該函數需要用戶自己編寫
#define configUSE_TICK_HOOK
時間片鉤子函數使能,發生時間片中斷時,是否調用vApplicationTickHook(void)函數,注意該函數需要用戶自己編寫
#define 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()失敗鉤子函數void vApplicationMallocFailedHook( void),如果宏configUSE_MALLOC_FAILED_HOOK設置為0,malloc()失敗鉤子函數不會被調用,即便已經定義了這個函數。
#define configUSE_DAEMON_TASK_STARTUP_HOOK
定義守護進程HOOK函數,如果設置為1且configUSE_TIMERS設置為1,用戶應用程序必須定義一個守護鉤子函數void vApplicationDaemonTaskStartupHook(void);
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY
此宏定義是用來配置FreeRTOS用到的SysTick中斷和PendSV中斷的優先級。在NVIC分組設置為4的情況下,此宏定義的范圍就是0-15,即專門配置搶占優先級。這里配置為了0x0f,即SysTick和PendSV都是配置為了最低優先級,實際項目中也建議大家配置最低優先級即可。
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
此宏定義比較重要,定義了受FreeRTOS管理的最高優先級中斷。簡單的說就是允許用戶在這個中斷服務程序里面調用FreeRTOS的API的最高優先級。
比如說設置NVIC的優先級分組為4的情況下。配置configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY為0x01表示用戶可以在搶占式優先級為1到15的中斷里面調用FreeRTOS的API函數,搶占式優先級為0的中斷里面是不允許調用的,也就是說優先級為0的中斷服務函數和裸機上是一樣的。
#define configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
宏定義configLIBRARY_LOWEST_INTERRUPT_PRIORITY的數值經過4bit偏移后得到一個8bit的優先級數值,即宏定義configKERNEL_INTERRUPT_PRIORITY的數值。這個8bit的數值才可以實際賦值給相應中斷的優先級寄存器。
也許初學者有疑問了,為什么前面NVIC配置的時候不是8bit的方式進行配置?這是因為ST的庫函數NVIC_Init()已經為我們做好了。這里的宏定義數值是供PendSV和SysTick中斷進行優先級配置的。比如:我們這里配置宏定義configLIBRARY_LOWEST_INTERRUPT_PRIORITY是0x0f,經過4bit偏移后就是0xf0,即SysTick和PendSV的中斷優先級就是240。
#define configMAX_SYSCALL_INTERRUPT_PRIORITY
宏定義configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的數值經過4bit偏移后得到一個8bit的優先級數值,即宏定義configMAX_SYSCALL_INTERRUPT_PRIORITY的數值。這個數值是賦值給寄存器basepri使用的,8bit的數值才可以實際賦值給相應中斷的優先級寄存器。這里的宏定義數值賦給寄存器basepri后就可以實現全局的開關中斷操作了。
比如:我們這里配置宏定義configLIBRARY_LOWEST_INTERRUPT_PRIORITY是0x01,經過4bit偏移后就是0x10,即16。調用了FreeRTOS的關中斷后,所有優先級數值大于等于16的中斷都會被關閉。優先級數值小于16的中斷不會被關閉,對寄存器basepri寄存器賦值0,那么被關閉的中斷會被打開。
本文參考 freertos官方文檔 https://freertos.org/a00110.html
博客 https://www.cnblogs.com/yeshenmeng/p/9805080.html
總結
以上是生活随笔為你收集整理的freeRtos学习笔(1)内核剪裁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32F103CUBE学习笔记 一
- 下一篇: freeRtos学习笔(2)任务管理