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 的一个子类
struct rt_serial_device
{
struct rt_device parent; const struct rt_uart_ops *ops;
struct serial_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, , );
HAL_NVIC_EnableIRQ(uart->config->dma_rx->dma_irq); HAL_NVIC_SetPriority(uart->config->irq_type, , );
HAL_NVIC_EnableIRQ(uart->config->irq_type); ....
}
在中断处理函数 uart_isr 中 实现了
static void uart_isr(struct rt_serial_device *serial)
{
.... #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)) //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 << ));
}
__HAL_UART_CLEAR_IDLEFLAG(&uart->handle);
}
#endif .....
}
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
{ case RT_SERIAL_EVENT_RX_DMADONE:
{
int length;
rt_base_t level; /* get DMA rx length */
length = (event & (~0xff)) >> ; if (serial->config.bufsz == )
{
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 */ \
\
} #define RT_SERIAL_RB_BUFSZ 64
RT-Thread 设备驱动UART浅析的更多相关文章
- RT thread 设备驱动组件之USART设备
本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...
- linux设备驱动模型-浅析-转
1. typeof typeof并非ISO C的关键字,而是gcc对C的一个扩展.typeof是一个关键字(类似sizeof),用于获取一个表达式的类型. 举个简单的例子: char tt; typ ...
- RT-Thread 设备驱动I2C浅析及使用
由于 I2C 可以控制多从机的属性,设备驱动模型分为 I2C总线设备(类似与Linux里面的I2C适配器) + I2C从设备: 系统I2C设备驱动主要实现 I2C 总线设备驱动,而具体的I2C 从设 ...
- RT-Thread 设备驱动SPI浅析及使用
OS版本:RT-Thread 4.0.0 测试BSP:STM32F407 SPI简介 SPI总线框架其实和I2C差不多,可以说都是总线设备+从设备,但SPI设备的通信时序配置并不固定,也就是说控制特定 ...
- RT-Thread 设备驱动ADC浅析与改进
OS版本:RT-Thread 4.0.0 芯片:STM32F407 下面时官方ADC提供的参考访问接口 访问 ADC 设备 应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC ...
- RT Thread的SPI设备驱动框架的使用以及内部机制分析
注释:这是19年初的博客,写得很一般,理解不到位也不全面.19年末得空时又重新看了RTThread的SPI和GPIO,这次理解得比较深刻.有时间时再整理上传. -------------------- ...
- RT-Thread 设备驱动-硬件定时器浅析与使用
RT-Thread 4.0.0 访问硬件定时器设备 应用程序通过 RT-Thread 提供的 I/O 设备管理接口来访问硬件定时器设备,相关接口如下所示: 函数 描述 rt_device_find() ...
- RT Thread SPI设备 使用
后记: 之前,我把SPI的片选在Cubemx中配置成了SPI_NSS.现在我给它改为了GPIO_OUTPUT. 同时参考了别人的类似的一个操作无线模块(采用SPI设备驱动)的例子程序(清楚了RTT的 ...
- 【Linux开发】linux设备驱动归纳总结(六):3.中断的上半部和下半部——工作队列
linux设备驱动归纳总结(六):3.中断的上半部和下半部--工作队列 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
随机推荐
- 九度OJ 1119:Integer Inquiry(整数相加) (大数运算)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:679 解决:357 题目描述: One of the first users of BIT's new supercomputer was ...
- xmanager 5图文使用教程
1.Xconfig xconfig是linux下X Window环境中用于配制的一个工具,和menuconfig相似,但用法更友好方便. 当你创建一个会话,会话分配一个默认的配置文件.Xmanager ...
- 【LeetCode】Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...
- iOS开发过程中 xcode文件与Finder中文件保持一致 + 支付宝集成出错
目录 环境 前言 1.使用 Gem 安装 synx 2.直接在终端 Terminal 中开始使用 3.在使用的时候还可以加参数来实现不同的功能 4.解决项目中出现的一些 error 环境 OS X 1 ...
- Android Weekly Notes Issue #243
Android Weekly Issue #243 February 5th, 2017 Android Weekly Issue #243 本期内容包括: ConstraintLayout的动画; ...
- Linux下直接读写物理地址内存
虚拟 转 物理地址 virt_to_phys( *addr );物理 转 虚拟地址 phys_to_virt( *addr ); 如: unsigned long pProtectVA; phys ...
- java基础以及操作Excle
今天把会经常用的几个集合的迭代方法又练习了一下,放在这里,经常复习! map集合迭代 /*** 迭代map[1]*/ for (Integer key : map.keySet()) {//迭代key ...
- [Vim 使用]vim 自动括号补全配置
打开Vim的配置文件,windows 上面的配置文件在vim 的安装目录下,_vimrc,使用记事本或vim打开 在下方加入如下代码 inoremap ( ()<ESC>i inorema ...
- MYSQL进阶学习笔记十三:MySQL 内存优化!(视频序号:进阶_31)
知识点十四:MySQL 内存的优化(31) 一.优化MySQL SERVER 7组后台进程: masterthread:主要负责将脏缓存页刷新到数据文件,执行purge操作,触发检查点,合并插入缓冲区 ...
- android读取apk中已经存在的数据库信息
在android数据库编程方面,大家有没有遇到过,我要从指定位置的已经存在的数据库来进行操作的问题.之前我尝试了很多方法都没有成功,后来找到了解决的方法. 下面说明下这段代码的意思,第一步先判断在 ...