我使用官方提供的GD32H759bsp移植到GD32H757Z单片机上时发现在finsh命令行输入上下左右键时会卡死,初步调试发现是串口发生了ORE溢出中断,而驱动未对ORE溢出中断清除标志导致卡死在中断里,中断处理代码如下
static void GD32_UART_IRQHandler(struct rt_serial_device *serial)
{
struct gd32_uart *uart = (struct gd32_uart *) serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
/* UART in mode Receiver -------------------------------------------------*/
if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_RBNE) != RESET) &&
(usart_flag_get(uart->uart_periph, USART_FLAG_RBNE) != RESET))
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
/* Clear RXNE interrupt flag */
usart_flag_clear(uart->uart_periph, USART_FLAG_RBNE);
}
}
于是我在中断处理里加入清除ORE标志
else if((usart_flag_get(uart->uart_periph, USART_FLAG_ORERR) != RESET))
{
usart_flag_clear(uart->uart_periph, USART_FLAG_ORERR);
}
这时发现finsh不会卡死,但是出现了新的问题:使用上下键时会出现字母AB
我研究了一下方向键是会下发多个字节,最后一个字节就是字母的ASCII码,如下是上下键下发的数据
这么看来应该是串口数据丢帧导致的,我对串口中断进行修改,打开空闲中断,屏蔽中断处理中rt_hw_serial_isr函数,并定义一个数据接收数据,在空闲中断处理中把接收到数据发送出去
static void GD32_UART_IRQHandler(struct rt_serial_device *serial)
{
struct gd32_uart *uart = (struct gd32_uart *) serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
// /* UART in mode Receiver -------------------------------------------------*/
if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_RBNE) != RESET) &&
(usart_flag_get(uart->uart_periph, USART_FLAG_RBNE) != RESET))
{
//rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
uart_rec_buff[count++] = (uint8_t)(usart_data_receive(uart->uart_periph)&0xff);
/* Clear RXNE interrupt flag */
usart_flag_clear(uart->uart_periph, USART_FLAG_RBNE);
}
else if((usart_flag_get(uart->uart_periph, USART_FLAG_ORERR) != RESET))
{
usart_flag_clear(uart->uart_periph, USART_FLAG_ORERR);
}
else if((usart_flag_get(uart->uart_periph, USART_FLAG_IDLE) != RESET))
{
for(uint8_t i = 0;i<count;i++)
{
usart_data_transmit(uart->uart_periph, uart_rec_buff[i]);
while((usart_flag_get(uart->uart_periph, USART_FLAG_TBE) == RESET));
uart_rec_buff[i] = 0;
}
count = 0;
usart_flag_clear(uart->uart_periph, USART_FLAG_IDLE);
}
}
果然接收的数据会丢失一点,如下图
结合溢出中断我觉得可能是串口中断处理的时间太长导致的,为了验证猜想,将波特率从115200改为9600,这时发送上来的数据是完整的,很奇怪,中断中的代码很少,600M的主频不应该会出现这个问题。我又在裸机上试了一下,115200的波特率下并没有出现这个问题。之后我又将设备驱动接口几个函数中的代码注释,在rt_hw_usart_init手动初始化串口
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_USART0);
gpio_af_set(GPIOA, GPIO_AF_7,GPIO_PIN_9);
gpio_af_set(GPIOA, GPIO_AF_7,GPIO_PIN_10);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);
usart_baudrate_set(USART0, 115200U);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_interrupt_enable(USART0, USART_INT_RBNE);
usart_interrupt_enable(USART0, USART_INT_IDLE);
nvic_irq_enable(USART0_IRQn, 0, 0);
usart_enable(USART0);
问题依旧。
所以有没有好心的大佬知道什么原因啊