RT-Thread中的串口DMA分析

这里分析一下RT-Thread中串口DMA方式的实现,以供做新处理器串口支持时的参考。

背景

在如今的芯片性能和外设强大功能的情况下,串口不实现DMA/中断方式操作,我认为在实际项目中基本是不可接受的,但遗憾的是,rt-thread现有支持的实现中,基本上没有支持串口的DMA,文档也没有关于串口DMA支持相关的说明,这里以STM32实现为背景,梳理一下串口DMA的实现流程,以供新处理器实现时以作参考。

DMA接收准备

启用DMA接收,需要在打开设备的时候做一些处理,入口函数为rt_device_open()。主体实现是:

rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag) { ...... result = device_init(dev); ...... result = device_open(dev, oflag); ...... } 

device_init()就是rt_serial_init()函数,其主要是调用configure()函数,

static rt_err_t rt_serial_init(struct rt_device *dev) { ...... if (serial->ops->configure) result = serial->ops->configure(serial, &serial->config); ...... } 

在stm32下,其configure()函数是stm32_configure(),其根据设备打开参数,配置STM32外设的寄存器。包括波特率、校验等串口工作参数。

device_open()函数就是rt_serial_open()函数,其主要实现是:

static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) { ...... #ifdef RT_SERIAL_USING_DMA else if (oflag & RT_DEVICE_FLAG_DMA_RX) { if (serial->config.bufsz == 0) { struct rt_serial_rx_dma* rx_dma; rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma)); RT_ASSERT(rx_dma != RT_NULL); rx_dma->activated = RT_FALSE; serial->serial_rx = rx_dma; } else { struct rt_serial_rx_fifo* rx_fifo; rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) + serial->config.bufsz); RT_ASSERT(rx_fifo != RT_NULL); rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1); rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); rx_fifo->put_index = 0; rx_fifo->get_index = 0; rx_fifo->is_full = RT_FALSE; serial->serial_rx = rx_fifo; /* configure fifo address and length to low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CONFIG, (void *) RT_DEVICE_FLAG_DMA_RX); } dev->open_flag |= RT_DEVICE_FLAG_DMA_RX; } #endif /* RT_SERIAL_USING_DMA */ ...... #ifdef RT_SERIAL_USING_DMA else if (oflag & RT_DEVICE_FLAG_DMA_TX) { struct rt_serial_tx_dma* tx_dma; tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma)); RT_ASSERT(tx_dma != RT_NULL); tx_dma->activated = RT_FALSE; rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL); serial->serial_tx = tx_dma; 

转载于:https://www.cnblogs.com/dabbler/p/11582199.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值