1. 程式人生 > >FreeRTOS筆記(三)配置檔案FreeRTOSConfig.h

FreeRTOS筆記(三)配置檔案FreeRTOSConfig.h

文章目錄


上一文連結:FreeRTOS筆記(二)移植STM32F407

01 - FreeRTOS核心剪裁

1.1 - FreeRTOSConfig.h檔案

  在上一文中,針對官方給出的STM32F407例程Demo,很容易移植了FreeRTOS到STM32F407上併成功執行。容易的原因是官方Demo中對FreeRTOS核心的配置已經完全對應了STM32F407的硬體配置

,配置檔案就是FreeRTOSConfig.h。
  開啟官方的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系統可以理會和不理會某些中斷