问题遇到的现象和发生背景
学习freerots,在学习消息队列时,遇到了一个问题,在调用xQueueReceiveFromISR()时,串口打印一下错误:
Error:..\FreeRTOS\queue.c,1440
Error:..\FreeRTOS\portable\RVDS\ARM_CM3\port.c,696
我使用的是正点原子的例程,实验内容如下:
串口 1 接收中断:接收串口发送过来的数据,并将接收到的数据发送到队列 Message_Queue 中。
定时器 2 中断:定时周期设置为 500ms,在定时中断中读取队列 Message_Queue 中的消息,并将其显示在 LCD 上
main函数中:
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//中断分组为4
delay_init();
uart_init(115200);
LED_Init();
KEY_Init();
LCD_Init();
TIM3_Int_Init(5000,7200-1);
xTaskCreate(Start_task,"start",Start_task_Size,NULL,Start_task_Prio,&Start_Handle);
vTaskStartScheduler();
}
首先在Start_task任务中创建了一个消息队列:
Mes_queHandle = xQueueCreate(4,50);
串口相关的代码:
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=7;//抢占优先级7
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
接收中断发送消息队列:
USART_RX_STA|=0x8000; //接收完成了
xQueueSendFromISR(Mes_queHandle,USART_RX_BUF,&xHigherPriorityTaskWoken);//发送消息队列
if(xHigherPriorityTaskWoken == pdTRUE)//是否进行任务调度
{
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
memset(USART_RX_BUF,0,USART_REC_LEN); //USART_REC_LEN 为 50
USART_RX_STA = 0;
定时器相关代码:
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8; //先占优先级8级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
定时器接收消息对列:
extern QueueHandle_t Mes_queHandle;
u8 Rxbuf[50];
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
BaseType_t xHigherPriorityTaskWoken;
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
{
xQueueReceiveFromISR(Mes_queHandle,Rxbuf,&xHigherPriorityTaskWoken); //问题所在,程序卡死在这里
LCD_ShowString(30,90,16,Rxbuf,0);
memset(Rxbuf,0,50);
if(xHigherPriorityTaskWoken == pdTRUE)
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
断言错误的地方:
queue.c第1440行:
翻译如下:
/*支持中断嵌套的RTOS端口具有最大系统调用(或最大API调用)中断优先级的概念。高于最大系统调用优先级的中断被永久启用,即使当RTOS内核处于临界区,但不能调用FreeRTOS API函数。如果在FreeRTosconfig.h中定义了configASSERT(),那么如果从一个被分配了高于配置的最大系统调用优先级的中断调用FreeRTOS API函数,则portASSERT_IF_INTERRUPT_PRIORITY_INVALID()将导致断言失败。只有以FromISR结尾的FreeRTOS函数才能从被分配的优先级等于或(逻辑上)低于最大系统调用中断优先级的中断调用。FreeRTOS维护一个独立的中断安全API,以确保中断入口尽可能快速和简单。下面提供了更多的信息(尽管是特定于皮质m的)freertos org/RTOS-cortex-M)
port.c 第696行:
翻译如下:
/*优先级分组:中断控制器(NVIC)允许定义每个中断优先级的位被划分为定义中断优先级的位和定义中断子优先级的位。为简单起见,必须将所有位定义为抢占优先位。如果不是这种情况(如果某些位代表子优先级),下面的断言将失败如果应用程序只使用CMSIS库进行中断配置,那么通过调用NVIC_SetPriorityGrouping(e)可以在所有的Cortex-M设备上实现正确的设置;在启动调度程序之前。但是请注意,一些特定于供应商的外围库假设优先级组设置为非零,在这种情况下,使用值为零将导致不可预测的行为。*
FreeRotsConfig.h中,我的中断配置:
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级
按理说Time中断的抢占优先级与串口中断都优先级都低于5,为什么还会出现这种错误呢?