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 ...
随机推荐
- Android笔记之平移View
方法有多种,只讲一种 使用View.setLeft和View.setRight 对于wrap_content的View,要横向平移,setRight是必要的,否则View的宽度会被改变(right应设 ...
- Linux就该这么学--命令集合6(打包压缩文件、文件查询搜索命令)
1.tar命令用于对文件打包压缩或解压:(tar [选项] [文件]) 打包并压缩文件:tar -czvf 压缩包名.tar.gz 文件名 解压并展开压缩包:tar -xzvf 压缩包名.tar.gz ...
- git基本操作---持续更新(2017-08-11)
git 强制push $ git push -u origin master -f 查看本地标签 $ git tag 打标签并添加备注 $ git tag 20170811 -m"图片保存多 ...
- eval函数用法
JavaScript 全局对象 定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法 eval(string) 参数 描述 string 必需.要计算的字 ...
- 关于redis的思考
集群版本的redis主从复制 也可以实现集群 但是不是很好 集群版redis主从复制版本集群 Spring Boot整合Redi事务 Spring Boot+Redis+Ehcache实现二级缓存 S ...
- 牛逼的This使用
今天看到一个很不错的this使用demo: package com.toov5.Reordering; class Message1{ private Channel channel; private ...
- Java(一)——认识Java语言
1.Java语言简介 Java是一种可以撰写跨平台应用程序的面向对象的程序设计语言,具有卓越的通用性.高效性.平台移植性和安全性.Sun 公司对 Java 编程语言的解释是:Java 编程语言是个简单 ...
- CISCO-配置SSH
PC直接连在交换机端口上,PC的ip地址是:192.168.1.1/24 在交换机的操作步骤如下: 1.设置交换机管理ip Switch#conf t Switch(config)#int vlan ...
- Can't locate Log/Dispatch.pm in @INC /Makefile out-of-date with respect to Makefile.PL
mha check的时候报错问题解决: # masterha_check_ssh --conf=/data/mha/app1.cnf Can't locate Log/Dispatch.pm in ...
- rsync(五)工作机制
当我们讨论rsync时,我们使用了一些特殊的术语来代表不同的进程以及它们在任务执行过程中所扮演的角色.人类为了更方便.更准确地交流,使用同一种语言是非常重要的:同样地,在特定的上下文环境中,使用固定的 ...