RT-thread串口驱动框架的使用问题,无DMA不能使用IDLE中断

发布于 2019-11-26 14:26:57
RT-thread串口驱动框架的使用问题,无DMA不能使用IDLE中断

我先贴一下部分代码,这个是串口中断的,STM32的串口中断直接调用的函数,正常情况下我是使用接收中断去接受数据,但是存在断帧,一帧多次接收的现象

rt_device_open(“serial_name”, RT_DEVICE_FLAG_INT_RX);



打开了static void uart_isr(struct rt_serial_device *serial)函数发现
它调用了
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
而在这个函数里面一直不停读数据,直到读不到数据并调用indicate回调函数完成接收,
我想说这样并不能很好的接收数据,倒不如用IDLE中断去提示完成接收数据,但是这个中断被DMA接收占用了,我所在串口并没有DMA,希望RTT能改进以下支持IDLE方式的中断接收





static void uart_isr(struct rt_serial_device *serial)
{
struct stm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
rt_size_t recv_total_index, recv_len;
rt_base_t level;
#endif

RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct stm32_uart, serial);

/* UART in mode Receiver -------------------------------------------------*/
if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_RXNE) != RESET))
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
#ifdef RT_SERIAL_USING_DMA
else if ((uart->uart_dma_flag) && (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_IDLE) != RESET)
&& (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_IDLE) != RESET))
{
level = rt_hw_interrupt_disable();
recv_total_index = serial->config.bufsz - __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle));
recv_len = recv_total_index - uart->dma_rx.last_index;
uart->dma_rx.last_index = recv_total_index;
rt_hw_interrupt_enable(level);

if (recv_len)
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8));
}
__HAL_UART_CLEAR_IDLEFLAG(&uart->handle);
}
else if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) != RESET)
{
if ((serial->parent.open_flag & RT_DEVICE_FLAG_DMA_TX) != 0)
{
HAL_UART_IRQHandler(&(uart->handle));
}
else
{
UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC);
}
}
#endif
else






/* ISR for serial interrupt */
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{
switch (event & 0xff)
{
case RT_SERIAL_EVENT_RX_IND:
{
int ch = -1;
rt_base_t level;
struct rt_serial_rx_fifo* rx_fifo;

/* interrupt mode receive */
rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
RT_ASSERT(rx_fifo != RT_NULL);

while (1)
{
ch = serial->ops->getc(serial);
if (ch == -1) break;


/* disable interrupt */
level = rt_hw_interrupt_disable();

rx_fifo->buffer[rx_fifo->put_index] = ch;
rx_fifo->put_index += 1;
if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;

/* if the next position is read index, discard this 'read char' */
if (rx_fifo->put_index == rx_fifo->get_index)
{
rx_fifo->get_index += 1;
rx_fifo->is_full = RT_TRUE;
if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;

_serial_check_buffer_size();
}

/* enable interrupt */
rt_hw_interrupt_enable(level);
}

/* invoke callback */
if (serial->parent.rx_indicate != RT_NULL)
{
rt_size_t rx_length;

/* get rx length */
level = rt_hw_interrupt_disable();
rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
(serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
rt_hw_interrupt_enable(level);

if (rx_length)
{
serial->parent.rx_indicate(&serial->parent, rx_length);
}
}
break;
}





查看更多

关注者
0
被浏览
742
0 个回答
暂无答案,快来添加答案吧

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友