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浅析的更多相关文章

  1. RT thread 设备驱动组件之USART设备

    本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...

  2. linux设备驱动模型-浅析-转

    1.  typeof typeof并非ISO C的关键字,而是gcc对C的一个扩展.typeof是一个关键字(类似sizeof),用于获取一个表达式的类型. 举个简单的例子: char tt; typ ...

  3. RT-Thread 设备驱动I2C浅析及使用

    由于 I2C 可以控制多从机的属性,设备驱动模型分为  I2C总线设备(类似与Linux里面的I2C适配器) + I2C从设备: 系统I2C设备驱动主要实现 I2C 总线设备驱动,而具体的I2C 从设 ...

  4. RT-Thread 设备驱动SPI浅析及使用

    OS版本:RT-Thread 4.0.0 测试BSP:STM32F407 SPI简介 SPI总线框架其实和I2C差不多,可以说都是总线设备+从设备,但SPI设备的通信时序配置并不固定,也就是说控制特定 ...

  5. RT-Thread 设备驱动ADC浅析与改进

    OS版本:RT-Thread 4.0.0 芯片:STM32F407 下面时官方ADC提供的参考访问接口 访问 ADC 设备 应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC ...

  6. RT Thread的SPI设备驱动框架的使用以及内部机制分析

    注释:这是19年初的博客,写得很一般,理解不到位也不全面.19年末得空时又重新看了RTThread的SPI和GPIO,这次理解得比较深刻.有时间时再整理上传. -------------------- ...

  7. RT-Thread 设备驱动-硬件定时器浅析与使用

    RT-Thread 4.0.0 访问硬件定时器设备 应用程序通过 RT-Thread 提供的 I/O 设备管理接口来访问硬件定时器设备,相关接口如下所示: 函数 描述 rt_device_find() ...

  8. RT Thread SPI设备 使用

    后记: 之前,我把SPI的片选在Cubemx中配置成了SPI_NSS.现在我给它改为了GPIO_OUTPUT.  同时参考了别人的类似的一个操作无线模块(采用SPI设备驱动)的例子程序(清楚了RTT的 ...

  9. 【Linux开发】linux设备驱动归纳总结(六):3.中断的上半部和下半部——工作队列

    linux设备驱动归纳总结(六):3.中断的上半部和下半部--工作队列 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

随机推荐

  1. 九度OJ 1119:Integer Inquiry(整数相加) (大数运算)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:679 解决:357 题目描述: One of the first users of BIT's new supercomputer was ...

  2. xmanager 5图文使用教程

    1.Xconfig xconfig是linux下X Window环境中用于配制的一个工具,和menuconfig相似,但用法更友好方便. 当你创建一个会话,会话分配一个默认的配置文件.Xmanager ...

  3. 【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 ...

  4. iOS开发过程中 xcode文件与Finder中文件保持一致 + 支付宝集成出错

    目录 环境 前言 1.使用 Gem 安装 synx 2.直接在终端 Terminal 中开始使用 3.在使用的时候还可以加参数来实现不同的功能 4.解决项目中出现的一些 error 环境 OS X 1 ...

  5. Android Weekly Notes Issue #243

    Android Weekly Issue #243 February 5th, 2017 Android Weekly Issue #243 本期内容包括: ConstraintLayout的动画; ...

  6. Linux下直接读写物理地址内存

    虚拟 转 物理地址  virt_to_phys( *addr );物理 转 虚拟地址  phys_to_virt( *addr ); 如: unsigned long pProtectVA; phys ...

  7. java基础以及操作Excle

    今天把会经常用的几个集合的迭代方法又练习了一下,放在这里,经常复习! map集合迭代 /*** 迭代map[1]*/ for (Integer key : map.keySet()) {//迭代key ...

  8. [Vim 使用]vim 自动括号补全配置

    打开Vim的配置文件,windows 上面的配置文件在vim 的安装目录下,_vimrc,使用记事本或vim打开 在下方加入如下代码 inoremap ( ()<ESC>i inorema ...

  9. MYSQL进阶学习笔记十三:MySQL 内存优化!(视频序号:进阶_31)

    知识点十四:MySQL 内存的优化(31) 一.优化MySQL SERVER 7组后台进程: masterthread:主要负责将脏缓存页刷新到数据文件,执行purge操作,触发检查点,合并插入缓冲区 ...

  10. android读取apk中已经存在的数据库信息

    在android数据库编程方面,大家有没有遇到过,我要从指定位置的已经存在的数据库来进行操作的问题.之前我尝试了很多方法都没有成功,后来找到了解决的方法.   下面说明下这段代码的意思,第一步先判断在 ...