關於FreeRTOS 任務運行中卡死在臨界區vPortExitCritical()

FreeRTOS創建任務正常運行,偶爾出現任務卡死狀態,通過在線調試,程序卡在vPortExitCritical()函數中,在IAR Call Stack中觀察到各任務都可能回調該接口。

void vPortExitCritical( void )
{
	configASSERT( uxCriticalNesting );
	uxCriticalNesting--;
	if( uxCriticalNesguanting == 0 )
	{
		portENABLE_INTERRUPTS();
	}
}

vPortExitCritical() 中configASSERT()中宏定義,uxCriticalNesting出現0的情況,說明了臨界區vPortEnterCritical()和vPortExitCritical()調用不對等。

/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }	

每個任務都存在回調該接口,由於不同任務的優先級有些不同,導致高優先級的任務一直佔用資源,並且任務回調是隨機的。
另外一種情況就是uxCriticalNesting的值持續往上增加,這說明了臨界區不起作用或者臨界區被外界頻繁打斷。
進一步跟蹤臨界區屏蔽中斷使能:


#define portDISABLE_INTERRUPTS()							\
{															\
	__set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY );	\
	__DSB();												\
	__ISB();												\
}
/*-----------------------------------------------------------*/

宏configMAX_SYSCALL_INTERRUPT_PRIORITY定義在頭文件FreeRTOSConfig.h中:

/* 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) )

configMAX_SYSCALL_INTERRUPT_PRIORITY在FreeRTOS中的作用就是用於區分臨界區可屏蔽的中斷,中斷優先級低於該設置值則歸FreeRTOS管控,中斷優先級高於該設置值則不受限(數字越小中斷優先級越大)。
從前面懷疑臨界區不起作用或者被打斷的情況來看,中斷優先級高於configMAX_SYSCALL_INTERRUPT_PRIORITY的中斷極有可能會影響到FreeRTOS臨界區,由於FreeRTOS是基於系統滴答時鐘,那極有可能是滴答中斷優先級過高造成的。
查看滴答中斷優先級設置:

/* ########################### System Configuration ######################### */
/**
  * @brief This is the HAL system configuration section
  */
#define  VDD_VALUE		      		  ((uint32_t)3300U) /*!< Value of VDD in mv */           
#define  TICK_INT_PRIORITY            ((uint32_t)0x00U)   /*!< tick interrupt priority */     

TICK_INT_PRIORITY 中斷優先級設置爲0,優先級高於FreeRTOS臨界區設置的中斷優先級,從而導致臨界區不起作用,估計工程複製過來沒有修改導致這個細節的問題,將TICK_INT_PRIORITY優先級改爲0x0F,系統正常運行,問題解決!

/* ########################### System Configuration ######################### */
/**
  * @brief This is the HAL system configuration section
  */
#define  VDD_VALUE		      		  ((uint32_t)3300U) /*!< Value of VDD in mv */           
#define  TICK_INT_PRIORITY            ((uint32_t)0x0FU)   /*!< tick interrupt priority */    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章