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 ...
随机推荐
- Snow White,摘自iOS应用Snow White and more stories
Once upon a time, there was a land. 从前,有个国度. It was ruled by an evil queen. 它被一位邪恶的女王统治. Every day t ...
- mac shell命令连接mongo
1. 安装rebomongo 2. mongo 192.168.1.100/databasename -u lsg -p 123456 3.db.drawspecs.find({name:'prize ...
- MySQL 的“root”用户修改密码
MySQL 的“root”用户默认状态是没有密码的,所以在 PHP 中您可以使用 mysql_connect("localhost","root"," ...
- [usaco2009nov]奶牛的图片
Farmer John希望给他的N(1<=N<=100,000)只奶牛拍照片,这样他就可以向他的朋友炫耀他的奶牛.这N只奶牛被标号为1..N.在照相的那一天,奶牛们排成了一排.其中第i个位 ...
- 如何配置DSI时钟频率
[DESCRIPTION] 计算DSI数据速率的方式,以及如何配置时钟clk的方式 [KEYWORD] dsi.data rate.mipi clk [SOLUTION] 1.DSI vdo mode ...
- ubuntu安装ros indigo
版本是14.04.1 一.先配置 1.点击新立得软件包管理器,输入密码exbot123, 2,点击最上面一栏的设置,选择软件源,前四个打勾,后一个不打,把sevice america改成mainsev ...
- dyld: could not load inserted library '/Developer/usr/lib/libBacktraceRecording.dylib' because no suitable image found. Did find:
错误: dyld: could not load inserted library '/Developer/usr/lib/libBacktraceRecording.dylib' because n ...
- BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并
BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20 ...
- ASoC框架
ASoC框架分为3部分: 1. platform(用来描述芯片的DAI接口,负责数据传输): DAI:snd_soc_dai_driver, 用来表示支持哪些格式数据, 提供设置格式的函数, 启动数据 ...
- POJ3211(trie+01背包)
Washing Clothes Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 9384 Accepted: 2997 ...