关于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 */    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章