rtthread 串口dma接收_RT-Thread 设备驱动UART浅析
OS版本:RT-Thread 4.0.0
芯片:STM32F407
RT-Thread的串口驱动框架与Linux相识,分成 I/O设备框架 + 设备底层驱动;
1. serial设备初始化及使用
将配置使能的 uart_obj[ ] 进行设备注册
rtthread_startup --> rt_hw_usart_init() --> rt_hw_serial_register --> rt_device_register
设备注册之后就可使用设备操作方式来使用串口
rt_device_find("uart3") --> rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX) --> rt_device_set_rx_indicate(serial, uart_dma_rx_handle)
2. serial设备
设备层 rt_device 注册及 ops 实现
const static struct rt_device_ops serial_ops ={
rt_serial_init,
rt_serial_open,
rt_serial_close,
rt_serial_read,
rt_serial_write,
rt_serial_control
};
而serial设备 rt_serial_device 为 rt_device 的一个子类
structrt_serial_device
{structrt_device parent;const struct rt_uart_ops *ops;structserial_configure config;void *serial_rx;void *serial_tx;
};
其中 rt_serial_device 中的 ops 通过 stm32_uart_ops 实现,这样 rt_device、rt_serial_device 和 uart底层就都关联起来了
硬件驱动层文件
drv_usart.c
drv_usart.h
stm32f4xx_hal_msp.c
主要内容 ops 实现,中断处理
static const struct rt_uart_ops stm32_uart_ops ={
.configure=stm32_configure, //默认配置
.control=stm32_control,
.putc=stm32_putc,
.getc=stm32_getc,
};
串口硬件初始化 HAL_UART_MspInit 对串口引脚和时钟的初始化 在 stm32f4xx_hal_msp.c 中,通过配置CubeMX生成;
3. 驱动分析
serial 的 control 操作 设计成 不能设置中断,即缺少 RT_DEVICE_CTRL_SET_INT 和 RT_DEVICE_CTRL_CLR_INT 操作, 这样可以避免误设置;
同时也是由于串口接收已经设计成三选一方式:中断、DMA、轮询;
说一下DMA,因为这也是我们最常用的串口数据接收处理方式;
RTT的 serial 的DMA接收,采用的 IDLE 中断来控制DMA接收数据的,
在 drv_usart.c 中
static void stm32_dma_config(struct rt_serial_device *serial)
{
....../*enable interrupt*/__HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_IDLE); //使能了空闲中断和DMA中断/*enable rx irq*/HAL_NVIC_SetPriority(uart->config->dma_rx->dma_irq, 0, 0);
HAL_NVIC_EnableIRQ(uart->config->dma_rx->dma_irq);
HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0);
HAL_NVIC_EnableIRQ(uart->config->irq_type);
....
}
在中断处理函数 uart_isr 中 实现了
static void uart_isr(struct rt_serial_device *serial)
{
....
#ifdef RT_SERIAL_USING_DMAelse 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)) //IDLE空闲中断
{
level=rt_hw_interrupt_disable();
recv_total_index= serial->config.bufsz - __HAL_DMA_GET_COUNTER(&(uart->dma.handle));
recv_len= recv_total_index - uart->dma.last_index;
uart->dma.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);
}#endif.....
}
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{caseRT_SERIAL_EVENT_RX_DMADONE:
{intlength;
rt_base_t level;/*get DMA rx length*/length= (event & (~0xff)) >> 8;if (serial->config.bufsz == 0)
{struct rt_serial_rx_dma*rx_dma;
rx_dma= (struct rt_serial_rx_dma*) serial->serial_rx;
RT_ASSERT(rx_dma!=RT_NULL);
RT_ASSERT(serial->parent.rx_indicate !=RT_NULL);
serial->parent.rx_indicate(&(serial->parent), length);
rx_dma->activated =RT_FALSE;
}else{/*disable interrupt*/level=rt_hw_interrupt_disable();/*update fifo put index*/rt_dma_recv_update_put_index(serial, length);/*calculate received total length*/length=rt_dma_calc_recved_len(serial);/*enable interrupt*/rt_hw_interrupt_enable(level);/*invoke callback*/
if (serial->parent.rx_indicate !=RT_NULL)
{
serial->parent.rx_indicate(&(serial->parent), length); //应用回调接收处理函数
}
}break;
}
}
如果进行大数据传输,发现默认缓存(64字节)不够用 可修改 RT_SERIAL_RB_BUFSZ 值
#define RT_SERIAL_CONFIG_DEFAULT \{ \
BAUD_RATE_115200,/*115200 bits/s*/\
DATA_BITS_8,/*8 databits*/\
STOP_BITS_1,/*1 stopbit*/\
PARITY_NONE,/*No parity*/\
BIT_ORDER_LSB,/*LSB first sent*/\
NRZ_NORMAL,/*Normal mode*/\
RT_SERIAL_RB_BUFSZ,/*Buffer size*/\0\
}
#define RT_SERIAL_RB_BUFSZ 64
rtthread 串口dma接收_RT-Thread 设备驱动UART浅析相关推荐
- rtthread 串口dma接收_rtthread 添加串口 (uart3)
1.查询uart配置过程 文件路径: /drivers/board.h 使能RTT uart驱动 2.使能usart3总线 打开 /drivers/board.h #define BSP_UART3_ ...
- rtthread 串口dma接收_RT-Thread 串口DMA使用笔记--STM32F207
RT-Thread学习笔记八 --------USART DMA方式发送 老规矩,首先说一下我的配置 STM32F207IGT6 MDK RTT 1.1.0 使用UART2作为finsh组件, ...
- RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60
系列文章目录 RT-Thread (1) 添加外部内存到内存管理 RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60 RT-Thread (3) 为RTT增加 ...
- STM32 串口DMA接收 Openmv / K210 整数、小数字符串数据 (基于HAL库)
目录 前言 一.工程配置 二.串口DMA部分代码 1.源文件UART_DMA.c 2.头文件UART_DMA.h 3.stm32f1xx_it.c的修改 4.串口收发DMA测试 三.字符串数字提取代码 ...
- 第九章 AT32F403A基于V2库串口 dma接收不定长数据
目录 概述 硬件 DMA 软件 流程 初始化 初始化代码: 中断服务函数: DMA1通道5设置函数:(重新使能通道) DMA1通道4发送函数:(设置dma长度和内存地址) 测试 最后 概述 本文主要是 ...
- STM32 USART串口DMA 接收和发送的源码详解!
硬件平台:STM32F103ZET6: 开发环境:KEIL 4: 先说说应用通讯模式,串口终端的工作方式和迪文屏差不多,终端被动接受MCU发的指令,终端会偶尔主动发送一些数据给MCU(像迪文屏的触摸信 ...
- android 串口一直打开_STM32之串口DMA接收不定长数据
STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...
- STM32 HAL库 串口DMA接收不定长数据
STM32 HAL库 串口DMA接收不定长数据 整体思路:我是用的CUBEMX软件生成的工程,使能了两个串口,串口2用来接收不定长的数据,串口1用来发送串口2接收到的数据:串口2我找了一个UBLOX卫 ...
- linux 串口 dma,STM32 USART串口DMA 接收和发送流程详解
1.dma发送流程 1.配置DMA发送中断 - NVIC_Init 2.配置串口中断 - NVIC_Init 3.GPIO配置 - GPIO_Init 4.DMA发送配置 -DMA_Init DMA ...
最新文章
- mac mysql本地连接数_如何用command line链接mysql
- 【Excel技巧】如何批量去掉×××号前的单引号
- maven中jar下载失败
- MySQL学习笔记07【事务、用户管理和权限管理】
- Emacs之魂(三):列表,引用和求值策略
- 【LeetCode】3. Longest Substring Without Repeating Characters
- matlab 带有下标的赋值维度不匹配_远见另类资产管理体系下的核心系统搭建
- svn版利用什么技术实现_金葱粉涂料印花利用了什么技术?
- opencv 从原始的图像中找出ROI区域
- 基于图像的相机定位/SLAM分类
- C程序设计--排序(冒泡、选择、插入)--冒泡
- wps linux 在线安装程序,WPS Office 2019 For Linux下载及安装教程
- LINUX下三个内核文件详解(vmlinuz/initrd.img/System.map)
- Python爬取哔哩哔哩视频
- 会计科目类词汇(中英)
- 原生js实现购物车添加删除商品、计算价格功能
- Wireshark抓包实例诊断TCP连接问题
- 开机提示小娜无法在本计算机运行,win10 20h2提示此应用无法在你的电脑上运行解决方法...
- CCC之I类设备、II类设备、III类设备的对比
- 【CSDN问答】使用体验、产品BUG和改进建议