FreeRTOS队列错误解决
错误描述
Stm32运行FreeRTOS,在串口中断函数中加上使用队列发送数据的代码就报错,不加就没问题:
// 省略前面代码
xQueueSendFromISR(U3_MSG_Queue,&res,&IspxHigherPriorityTaskWoken);
if(IspxHigherPriorityTaskWoken==pdTRUE){
portYIELD_FROM_ISR(IspxHigherPriorityTaskWoken);
}
报错,串口输出:
Error:..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c,768
Error:..\FreeRTOS\portable\RVDS\ARM_CM4F\port.c,768
问题剖析
在FreeRTOS的移植时,需要重写断言函数:
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)
这个断言实际上就是判断是否输入值为0,为0则会打印出当前文件和当前行。因此,很有可能是xQueueSendFromISR
或者portYIELD_FROM_ISR
函数里面有调用断言函数,并且传入的值是0!!!根据\FreeRTOS\portable\RVDS\ARM_CM4F\port.c,768
提示,进入上面两个函数体内部,最终会发现在xQueueSendFromISR
里面调用了port.c
的void vPortValidateInterruptPriority( void )
,往下看,
然后就得看看注释,为什么这里断言会成立(报错)。读完第一段,也许就会发现了:
The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
即是在中断服务中调用以FromISR结尾的函数,该中断优先级必须要小于configMAX_SYSCALL_INTERRUPT_PRIORITY (FreeRTOSConfig.h里面定义的)
。即中断优先级数字大于configMAX_SYSCALL_INTERRUPT_PRIORITY
(在STM32中,数字越小,优先级越高)。
解决办法
修改对应中断的优先级(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY+1 ~ configLIBRARY_LOWEST_INTERRUPT_PRIORITY
)之间即可。