串口驱动
1.rt_hw_usart_init
中调用 rt_hw_serial_register
注册串口设备
1 |
|
- 串口设备注册
1 |
|
串口V1
1.rt_serial_init
执行 configure
函数,配置串口参数
- RX接收驱动方式:
- RX POLL方式,轮询方式,直接读取串口数据,直到读取到指定长度数据退出;
- RX 中断方式,串口中断触发,读取串口数据;中断触发后,使用fifo缓冲区,一个个字节搬运,调用RX中再从fifo缓冲区读取数据;
- RX DMA方式,串口DMA触发,读取串口数据;使用fifo缓冲区,从DMA搬运数据到fifo缓冲区,再从fifo缓冲区读取数据;
- TX发送驱动方式:
- TX POLL方式,轮询方式,直接发送数据;每次发送一个字节,等待发送完成
- TX 中断方式,串口中断触发,发送数据;每次发送一个字节,等待发送完成;如果发送失败,则阻塞等待完成量;完成量由TX完成中断触发
- TX DMA方式,串口DMA触发,发送数据;使用数据队列,将数据放入队列,再从队列中取出数据发送;如果发送时队列满了,则阻塞等待
RX中断方式
open
- malloc分配fifo缓冲区
可以使用ringbuff改造
1 |
|
read
- 从fifo缓冲区中读取数据,一个个字节读取
效率低了,可以直接做逻辑读取lenth长度的数据
ISR
- 串口中断中判断为接收中断,进入中断处理函数
- 读取串口数据,写入fifo缓冲区,并执行接收完成回调函数
使用while方式一个个字节读取
RX POLL方式
- while循环读取串口数据,直到读取到指定长度数据退出
RX DMA方式
open
- malloc分配fifo缓冲区
- control 调用底层驱动配置DMA
read
- 获取fifo缓冲区中数据长度
- 从fifo中读取数据
- 更新fifo缓冲区读取指针
ISR
- 中断处理函数,判断为DMA触发标志;获取DMA传输数据长度
2.UART_RX_DMA_IT_IDLE_FLAG
DMA+空闲中断触发
- 计算接收数据长度
3.UART_RX_DMA_IT_HT_FLAG
DMA+半传输中断触发
- 计算接收数据长度
4.UART_RX_DMA_IT_TC_FLAG
,DMA+传输完成中断触发
- 更新fifo put索引,计算接收数据长度.执行回调函数
TX POLL方式
- while循环发送数据,直到发送完成
- 调用
put
函数发送数据,一个个字节发送,while循环判断发送完成
TX 中断方式
open
- 初始化完成量,malloc分配fifo缓冲区
write
- while循环发送数据,直到发送完成,一次发送一个字节
2.put
后等待完成量唤醒
1 |
|
ISR
- 执行
RT_SERIAL_EVENT_TX_DONE
,触发完成量
TX DMA方式
- open
- malloc dataqueue缓冲区,初始化dataqueque
1 |
|
- write
使用数据队列push,队列满时,阻塞等待
1 |
|
- ISR
HAL_UART_TxCpltCallback
- 获取TX DMA计数,当计数为0时,执行
RT_SERIAL_EVENT_TX_DONE
2.rt_data_queue_pop
出队列中的数据,DMA发送完成进入;再次 peek
是否还有数据,接着发送
STM32 HAL 串口驱动
1.HAL_USART_Transmit
- 阻塞发送,直到发送完成,一次发送一个字节
2.HAL_USART_Receive
- 阻塞接收,直到接收完成,一次接收一个字节
3.HAL_USART_Transmit_IT
- 仅是使能与设置数据地址,具体实现需要自行编写
- 设置
pTxBuffPtr
指针指向的数据地址,设置TxXferSize
发送数据长度,设置TxXferCount
发送数据计数 - 使能
USART_IT_TXE
中断,发送数据 - 设置
husart->TxISR
执行中断函数
-HAL_USART_IRQHandler
中断函数,判断为 USART_IT_TXE
中断,发送一个字节数据,直到发送完成指定数据长度,清除中断标志,执行 HAL_USART_TxCpltCallback
;
4.HAL_USART_Receive_IT
- 仅是使能与设置数据地址,具体实现需要自行编写
- 使能
USART_IT_RXNE
中断,接收数据 - 设置
husart->TxISR
执行中断函数
-HAL_USART_IRQHandler
中断函数,判断为 USART_IT_RXNE
中断,接收一个字节数据;直到中断接收完成需要的数据长度,执行 HAL_USART_RxCpltCallback
;
5.HAL_USART_Transmit_DMA
- 仅是使能与设置数据地址,具体实现需要自行编写
- 设置
USART_DMATransmitCplt
,USART_DMATxHalfCplt
,USART_DMAError
- 设置
pTxBuffPtr
指针指向的数据地址,设置TxXferSize
发送数据长度,设置TxXferCount
发送数据计数
-HAL_DMA_IRQHandler
中执行 USART_DMATransmitCplt
,USART_DMATxHalfCplt
,USART_DMAError
6.HAL_USART_Receive_DMA
- 仅是使能与设置数据地址,具体实现需要自行编写
- 设置
USART_DMAReceiveCplt
,USART_DMARxHalfCplt
,USART_DMAError
- 设置
pRxBuffPtr
指针指向的数据地址,设置RxXferSize
接收数据长度,设置RxXferCount
接收数据计数
-HAL_DMA_IRQHandler
中执行 USART_DMAReceiveCplt
,USART_DMARxHalfCplt
,USART_DMAError
7.HAL_UARTEx_ReceiveToIdle_DMA
- 仅是使能与设置数据地址,具体实现需要自行编写
- 启动空闲中断可以执行完成回调
串口驱动V2
- 串口V1和串口V2驱动实现方式没区别,仅有概念不同,将底层的POLL,中断,阻塞变为了阻塞,非阻塞方式+是否DMA方式来使用
RX 阻塞方式
- 没有缓冲区使用POLL方式,一次读取一字节数据,直到读取到指定长度数据退出;
- 有缓冲区使用ringbuff方式
- 初始化ringbuff缓冲区和完成量,使用中断方式
- 读取时:获取ringbuff缓冲区中数据长度,从ringbuff中读取数据,更新ringbuff缓冲区读取指针
当获取到的长度<需要读取的长度时,完成量阻塞等待
- 中断中:
RT_SERIAL_EVENT_RX_IND
时,完成量完成唤醒等待线程;更新ringbuff缓冲区写入指针
RX 非阻塞方式
- 初始化ringbuff缓冲区,使用DMA方式
- 读取时:获取ringbuff缓冲区中数据长度,从ringbuff中读取数据,更新ringbuff缓冲区读取指针;
获取长度为0时,外部自行处理判断,内部非阻塞返回
- 中断中:
RT_SERIAL_EVENT_RX_DMADONE
时,更新ringbuff缓冲区写入指针
TX 阻塞方式
- 没有缓冲区使用POLL方式,一次发送一字节数据,直到发送完成;
- 有缓冲区使用ringbuff方式
- 初始化ringbuff缓冲区和完成量,使用中断方式
- 写入时:将数据put到ringbuff缓冲区,等待完成量唤醒
- 中断中:
RT_SERIAL_EVENT_TX_DONE
时,获取ringbuff获取完成,完成量完成唤醒等待线程;
TX 非阻塞方式
- 初始化ringbuff缓冲区,使用DMA方式
- 写入时:将数据push到ringbuff缓冲区,直接返回
- 中断中:
RT_SERIAL_EVENT_TX_DMADONE
时,读取ringbuff缓冲区数据,再次push到ringbuff缓冲区
serialX
POLL TX RX 方式
- 与V1无差别
中断 TX RX 方式
- 与V1无差别
DMA TX RX 方式
- 多了一个数组,用于存放DMA数据;再次push到ringbuff缓冲区