FreeRTOS创建任务正常运行,偶尔出现任务卡死状态,通过在线调试,程序卡在vPortExitCritical()函数中,在IAR Call Stack中观察到各任务都可能回调该接口。
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesguanting == 0 )
{
portENABLE_INTERRUPTS();
}
}
vPortExitCritical() 中configASSERT()中宏定义,uxCriticalNesting出现0的情况,说明了临界区vPortEnterCritical()和vPortExitCritical()调用不对等。
#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中:
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#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是基于系统滴答时钟,那极有可能是滴答中断优先级过高造成的。
查看滴答中断优先级设置:
#define VDD_VALUE ((uint32_t)3300U)
#define TICK_INT_PRIORITY ((uint32_t)0x00U)
TICK_INT_PRIORITY 中断优先级设置为0,优先级高于FreeRTOS临界区设置的中断优先级,从而导致临界区不起作用,估计工程复制过来没有修改导致这个细节的问题,将TICK_INT_PRIORITY优先级改为0x0F,系统正常运行,问题解决!
#define VDD_VALUE ((uint32_t)3300U)
#define TICK_INT_PRIORITY ((uint32_t)0x0FU)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)