1.现象
想在串口中断中实现任务通知的功能,所以在串口中断服务函数中使用了xTaskGenericNotifyFromISR()函数来发送通知,发现一进入中断服务函数,程序就卡死了。下边是串口初始化和中断服务函数:
void Usart_Init_U(uint32_t BaudRate)
{
//配置时钟
……
//配置输出脚:USART0_Tx
……
//配置输入脚:USART0_Rx
……
usart_baudrate_set(USART_PORT, BaudRate); //波特率
usart_parity_config(USART_PORT, USART_PM_NONE); //无校验
usart_word_length_set(USART_PORT, USART_WL_8BIT); //有效数据:8bit
usart_stop_bit_set(USART_PORT, USART_STB_1BIT); //停止位长度:1bit
usart_transmit_config(USART_PORT, USART_TRANSMIT_ENABLE); //使能发送
usart_receive_config(USART_PORT, USART_RECEIVE_ENABLE); //使能接收
usart_enable(USART_PORT); //使能串口
nvic_irq_enable(USARTx_IRQn, 2, 0); //启用NVIC请求:配置中断通道和优先级
usart_interrupt_enable(USART_PORT,USARTx_IT); //设置串口触发中断的标志
}
void USARTx_IRQHandler(void)
{
BaseType_t flag = pdFALSE;
uint32_t Num = 6;
uint32_t Num1 = 0;
if(usart_interrupt_flag_get(USART_PORT,USARTx_IT_FLAG) == SET)
{
Rx_Data = usart_data_receive(USART_PORT);
usart_data_transmit(USART_PORT,Rx_Data);
// Value = 1;
flag = xTaskGenericNotifyFromISR(LED1Task_Handler,Num,eSetValueWithOverwrite,&Num1,&xHigherPriorityTaskWoken);
if(flag == pdTRUE)
printf("发送成功\r\n");
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
usart_interrupt_flag_clear(USART_PORT,USARTx_IT_FLAG);
}
}
由上边两段代码可以看到:
- 串口中断的优先级为2(4位抢占,0位响应)。
- 执行代码,程序就会卡在flag = xTaskGenericNotifyFromISR(LED1Task_Handler,Num,eSetValueWithOverwrite,&Num1,&xHigherPriorityTaskWoken);这一句,而不会去执行下一句代码,也不会出中断,完完全全卡死在这里。
2.解决办法
我先试了不用中断的任务通知(定义两个任务,用一个任务去通知另一个任务),发现完全没有问题。所以问题就出在中断上,而能出问题的地方就只能是中断的优先级。通过查找资料可知FreeRTOS操作系统内核使用最低优先级,操作系统所能调用管理的最高优先级为5~15级。所以在定义外设的中断优先级时,要想FreeRTOS能够正常运行,必须将优先级设置在5-15级之间。
void Usart_Init_U(uint32_t BaudRate)
{
//配置时钟
……
//配置输出脚:USART0_Tx
……
//配置输入脚:USART0_Rx
……
usart_baudrate_set(USART_PORT, BaudRate); //波特率
usart_parity_config(USART_PORT, USART_PM_NONE); //无校验
usart_word_length_set(USART_PORT, USART_WL_8BIT); //有效数据:8bit
usart_stop_bit_set(USART_PORT, USART_STB_1BIT); //停止位长度:1bit
usart_transmit_config(USART_PORT, USART_TRANSMIT_ENABLE); //使能发送
usart_receive_config(USART_PORT, USART_RECEIVE_ENABLE); //使能接收
usart_enable(USART_PORT); //使能串口
nvic_irq_enable(USARTx_IRQn, 6, 0); //启用NVIC请求:配置中断通道和优先级
usart_interrupt_enable(USART_PORT,USARTx_IT); //设置串口触发中断的标志
}
将优先级改为7,就能在中断服务函数中正常发送任务通知了。