FreeRTOS筆記(三)配置檔案FreeRTOSConfig.h
文章目錄
上一文連結:FreeRTOS筆記(二)移植STM32F407
01 - FreeRTOS核心剪裁
1.1 - FreeRTOSConfig.h檔案
在上一文中,針對官方給出的STM32F407例程Demo,很容易移植了FreeRTOS到STM32F407上併成功執行。容易的原因是官方Demo中對FreeRTOS核心的配置已經完全對應了STM32F407的硬體配置
開啟官方的API手冊,可以看到,第7章就是核心配置檔案的描述:
能夠看到,FreeRTOSConfig.h其實就是對核心進行剪裁的配置檔案,主體巨集分為兩部分,一部分是字首為INCLUER_的巨集,另一部分是字首為config的巨集,它們的用處文件有很詳細的結束,小白簡單總結如下:
1.2 - FreeRTOSConfig.h內容
在FreeRTOSConfig.h中,我們暫時只關心一些常用內容的配置,根據官方文件,能夠知道config字首巨集的對映內容,下面是部分的註釋:
#define configUSE_PREEMPTION 1 //0-協程排程,1-搶佔式排程
#define configUSE_IDLE_HOOK 0 //0-除能空閒任務的鉤子函式,1-使能
#define configUSE_TICK_HOOK 0 //0-除能時間片鉤子函式,1-使能
#define configCPU_CLOCK_HZ ( SystemCoreClock ) //設定CPU頻率
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) //設定滴答計時器的中斷頻率,為HZ/1000=1ms
#define configMAX_PRIORITIES ( 5 ) //任務優先順序是0~(configMAX_PRIORITIES-1)
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 ) //設定空閒任務的堆疊大小,單位是字(4位元組)
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) ) //設定系統總堆疊大小
#define configMAX_TASK_NAME_LEN ( 10 ) //設定任務名最大長度
#define configUSE_TRACE_FACILITY 1 //0-除能視覺化跟蹤除錯,1-使能
#define configUSE_16_BIT_TICKS 0 //節拍計時器變數範圍,0-16位,1-32位
#define configIDLE_SHOULD_YIELD 1 //0-空閒任務不會讓出CPU給同等優先順序的任務,1-會讓出CPU
#define configUSE_MUTEXES 1 //0-除能互斥訊號量,1-使能
#define configQUEUE_REGISTRY_SIZE 8 //0-除能核心除錯中檢視佇列和訊號量數量,>0-可以註冊的數量
#define configCHECK_FOR_STACK_OVERFLOW 0 //0-除能堆疊溢位檢測,1-使能
#define configUSE_RECURSIVE_MUTEXES 1 //0-除能遞迴互斥訊號量,1-使能
#define configUSE_MALLOC_FAILED_HOOK 0 //0-除能malloc失敗時呼叫的鉤子函式,1-使能
#define configUSE_APPLICATION_TASK_TAG 0 //0-除能一些應用程式鉤子函式,1-使能
#define configUSE_COUNTING_SEMAPHORES 1 //0-除能計數訊號量,1-使能
#define configGENERATE_RUN_TIME_STATS 0 //0-除能時間統計功能,1-使能
……
//硬體相關的中斷位數
#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
//最低優先順序,一般與configPRIO_BITS對應,2^configPRIO_BITS-1
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
//可管理的最大優先順序(設定STM的BASEPRI暫存器)
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
//真正的中斷優先順序,用於設定滴答中斷等等的優先順序
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
//真正的中斷優先順序,最大可以使用FreeRTOS-API的中斷優先順序
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
FreeRTOSConfig.h前部分是一些CPU、排程演算法等配置,後部分是中斷配置。能夠清晰觀測到,只有配置了例如CPU頻率、滴答時鐘頻率等等的硬體相關內容才能成功移植,而其它的一些例如訊號量、鉤子函式等等的內容是根據實際情況而定的。
前部分的內容是硬體能執行的基本配置,而後部分的中斷配置是實時嵌入式系統的需求配置,中斷配置記憶體如下:
- FreeRTOS中斷配置
- 1、 確定邏輯上表達中斷優先順序數量的暫存器位數: STM32F407為4位,共16個優先順序
- 2、 確定邏輯上最低優先順序: STMF407為2^4 - 1 = 15
- 3、 確定邏輯上FreeRTOS可管理的最大優先順序: 設定為5,意味著優先順序>=5的優先順序不受FreeRTOS管理和處理
- 4、 確定暫存器上真正的最低優先順序: STM使用暫存器的高位,摒棄低位,因此需要移位
- 5、 確定暫存器上FreeRTOS可管理的最大優先順序: 需要移位
可管理的最大優先順序描述如下:
02 - 測試剪裁內容
2.1 - 任務設計
在此我們測試FreeRTOSConfig.h中的中斷配置,可管理的最大優先順序為5,也就優先順序<5的中斷不歸FreeRTOS管理,於是設計測試程式邏輯如下:
在上一文的工程中進行程式設計,先編寫定時器程式碼,再編寫任務程式碼。其中定時器使用通用定時器3和5,兩者都是定時1s,唯一不同的是優先順序,定時器3的優先順序是4(超過了FreeRTOS管理的優先順序),定時器5的優先順序是6(可以被FreeRTOS管理)。
定時器配置程式碼區別的位置如下:
// 定時器3
……
NVIC_struct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_struct.NVIC_IRQChannelPreemptionPriority = 0x04; //搶佔優先順序4
NVIC_struct.NVIC_IRQChannelSubPriority = 0x00;
NVIC_struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_struct);
……
……
// 定時器5
NVIC_struct.NVIC_IRQChannel = TIM5_IRQn;
NVIC_struct.NVIC_IRQChannelPreemptionPriority = 0x06; //搶佔優先順序4
NVIC_struct.NVIC_IRQChannelSubPriority = 0x00;
NVIC_struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_struct);
……
/* ----------------------------中斷函式---------------------------*/
void TIM5_IRQHandler(void)
{
//溢位中斷
if(TIM_GetITStatus(TIM5,TIM_IT_Update) == SET)
{
printf("timer5 with priority 6 \r\n");
}
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
}
void TIM3_IRQHandler(void)
{
//溢位中斷
if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
{
printf("timer3 with priority 4 \r\n");
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
開關中斷我們採用註釋然後重新編輯的方式去實現,不能使用vTaskDelay()來進行間隔開關中斷,因為vTaskDelay()會掛起排程器,導致不能進行任務切換,但是同時也開啟了中斷,不能起到關中斷的作用。
/* Start 任務 */
void start_task(void *pParam)
{
//portDISABLE_INTERRUPTS();
for(;;)
{
portDISABLE_INTERRUPTS();
printf("satrt portDISABLE_INTERRUPTS()\r\n");
vTaskDelay(5000);
portENABLE_INTERRUPTS();
printf("satrt portENABLE_INTERRUPTS()\r\n");
vTaskDelay(5000);
}
}
2.2 - 測試結果
首先測試statr開中斷(預設),執行結果如下,兩個定時器都在相繼輸出
然後是關閉中斷,執行結果如下。只有time3在輸出,因為time3優先順序為4,超出了FreeRTOS配置的最大可管理優先順序5,所有timer3不受管理,而time5優先順序是6,在FreeRTOS中斷管理優先順序內,於是timer5被關閉。
03 - 總結
- FreeRTOS核心剪裁配置檔案是FreeRTOSConfig.h
- FreeRTOSConfig.h前部分是一些CPU、排程演算法等配置,後部分是中斷配置
- FreeRTOSConfig.h的中斷配置使得FreeRTOS系統可以理會和不理會某些中斷