登录/注册

rt-thread 串口接收过程

更多

在 RT-Thread 操作系统中,串口(UART)接收数据是一个涉及硬件驱动框架、设备驱动模型和应用程序交互的过程。以下是详细的中文解析:

核心流程:中断驱动 + 环形缓冲区 + 线程同步

  1. 硬件中断触发(底层硬件驱动负责)

    • 当串口的接收寄存器(例如 RxD)接收到一个字符(或达到 FIFO 触发阈值)时,硬件会触发一个接收中断(如 USART_IT_RXNE)。
    • RT-Thread 为该串口注册的中断服务程序static void rt_hw_serial_isr(struct rt_serial_device *serial))会被 CPU 调用。
  2. 中断服务程序(ISR)处理(设备驱动实现)

    • 读取数据: ISR 通过读取硬件寄存器(如 DR),将接收到的一个或多个字节从串口硬件读取出来。
    • 写入环形缓冲区(RX Ring Buffer): ISR 将读取到的字节依次存入为该串口分配的接收环形缓冲区rx_buffer)。
      • 关键点: ISR 的执行速度必须极快。它只做最低限度的必要操作:读硬件、存缓冲区。所有复杂的处理和解析都应该放在应用线程中进行。
    • 数据处理标志(可选): 对于简单的需求,ISR 可能会根据接收到的内容(如特定的起始字节、结束符)设置标志位(rx_indicate)。但这在高数据量或复杂协议中不常用。
    • 发送线程通知(核心): ISR 最核心的任务之一是调用 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | RT_SERIAL_EVENT_RX_INDICATE)(或类似,具体名称可能略有差异)。
      • 这个函数内部会将串口的接收事件(如 RT_SERIAL_EVENT_RX_INDICATE)和接收到的数据量信息传递给上层的设备驱动框架
  3. 设备驱动框架处理接收事件

    • 框架收到 RT_SERIAL_EVENT_RX_INDICATE 事件后,主要做两件事:
      • 更新可接收计数: 增加串口设备对象的 rx_notice 或类似计数变量,表示有新的数据可用。
      • 唤醒等待线程: 检查是否有应用程序线程正在通过 rt_device_read()rt_sem_take() 等方式阻塞(挂起)等待接收数据。如果有,框架会发送一个信号(如释放信号量、发送邮箱消息) 唤醒这些等待的线程。
  4. 应用程序读取数据(用户线程)

    • 应用程序通常会创建一个独立的线程来主动读取串口数据。
    • 使用设备操作 API:应用程序调用标准接口 rt_device_read(serial_dev, -1, buffer, size) 来尝试读取数据。
      • serial_dev: 之前通过 rt_device_find() 找到的串口设备对象。
      • -1: 表示无限等待(RT_WAITING_FOREVER),直到有数据到来。也可以设置超时时间(如 rt_tick_from_millisecond(100))。
      • buffer: 用户提供的缓冲区地址,用于存放读取的数据。
      • size: 用户希望读取的最大字节数。
    • 阻塞与读取:
      • 有数据可读: 如果环形缓冲区中有数据,rt_device_read 会立刻从环形缓冲区中拷贝最多 size 个字节到 buffer 中,并返回实际读取的字节数。此时线程不会阻塞
      • 无数据可读: 如果环形缓冲区为空:
        • 如果调用 rt_device_read 时指定了 RT_WAITING_FOREVER,则调用线程会被挂起(阻塞),并放入该串口设备的接收等待队列中。
        • 步骤3中的驱动框架发出“有数据到达”的信号时,RT-Thread 调度器唤醒这个被挂起的线程。
        • 线程被唤醒后,rt_device_read 函数内部会再次尝试从环形缓冲区拷贝数据到用户 buffer

关键组件与设计思想

总结流程图

+------------------------+      +----------------------------+      +-----------------+      +-------------------+
| 串口硬件收到数据         |----->| 硬件中断触发 (RXNE)         |----->| 中断服务程序 (ISR)  |----->| 1. 从硬件读取数据     |
| (例如:USART RxD Line) |      | (中断向量跳转)             |      |                 |      | 2. 存入接收环形缓冲区 |
+------------------------+      +----------------------------+      |                 |----->| 3. 通知驱动框架       |
                                                                     +---------^--------+      +-------------------+
                                                                               |
                                                                               |
+------------------+      +----------------------+      +----------------------v--------------------+      +-------------------------+
| 应用线程         |<-----| 1. 拷贝数据到用户buffer |<-----|          rt_device_read(...)             |      |                         |
| (用户数据处理逻辑) |      | 2. 返回实际读取字节数   |      |                                      |      |                         |
|                  |----->| (非阻塞:立即返回)      |      | * 检查环形缓冲区是否有数据?            |----->|                         |
+------------------+      +----------------------+      |   - 有数据:读取并返回                    |      |                         |
               ^                                         |   - 无数据且超时设置 != RT_NULL:         |      |  RT-Thread 内核调度器     |
               |                                         |     等待指定时间,超时则返回0或-ETIMEOUT |      | (负责线程阻塞和唤醒)       |
               |                                         |   - 无数据且超时 == RT_WAITING_FOREVER: |      |                         |
               |                                         |     调用线程被挂起(阻塞),进入等待队列    |<-----|                         |
               |                                         +------------------------------------------+      |                         |
               |                                                                                           |                         |
               |         +------------------------------------------------------+<-----------------------+
               |         |           设备驱动框架收到 ISR 通知                      |
               |         |   (rt_hw_serial_isr(RT_SERIAL_EVENT_RX_INDICATE))    |
               +---------| 1. 更新可接收计数                                      |
                         | 2. 发送信号唤醒在 rt_device_read 中阻塞的线程             |
                         +------------------------------------------------------+

简单来说:

硬件接收数据触发中断 -> 中断程序快速把数据存入内存缓冲区 -> 中断程序通知系统框架"有新数据了" -> 系统框架唤醒等待读取数据的应用程序线程 -> 被唤醒的应用程序线程调用 rt_device_read 函数从缓冲区拷贝数据到自己的内存空间进行处理。

这种设计确保了硬件中断处理的高效性(避免在中断中执行复杂操作),同时为应用程序提供了灵活、同步的数据读取方式。

RT-Thread Nano入门:串口接收与消息队列

本文主要介绍怎么用RT-Thread Nano的消息队列方式实现串口数据接收,结合串口

2023-11-22 11:07:27

RT-Thread v5.0.2 发布

RT-Thread 代码仓库地址: ●  https://github.com/RT-Thread/rt-thread

2023-10-10 18:45:01

基于RT-Thread Studio学习

前期准备:从官网下载 RT-Thread Studio,弄个账号登陆,开启rt-thread学习之旅。

2023-05-15 11:00:38

RT-Thread文档_RT-Thread SMP 介绍与移植

RT-Thread文档_RT-Thread SMP 介绍与移植

资料下载 刘燕 2023-02-22 18:31:34

RT-Thread文档_RT-Thread 潘多拉 STM32L475 上手指南

RT-Thread文档_RT-Thread 潘多拉 STM32L475 上手指南

资料下载 佚名 2023-02-22 18:23:17

RT-Thread文档_RT-Thread 简介

RT-Thread文档_RT-Thread 简介

资料下载 张览秀 2023-02-22 18:22:24

RT-Thread学习笔记 --(6)RT-Thread线程间通信学习过程总结

前两篇文章总结了RT-Thread多线程以及多线程同步的学习过程,关于前两篇学习总结,可以查看之前的文章。

资料下载 龙献益 2022-01-25 18:50:59

记录——基于 RT-Thread 实现 USB 虚拟串口

记录——基于 RT-Thread 实现 USB 虚拟串口记录一下我在正点原子 F429 阿波罗开发板上实现 USB 虚拟串口的

资料下载 佚名 2021-12-02 17:21:05

如何使用RT-Thread串口设备

控)输出了字符 2、0、1、8 和字符串 Hello RT-Thread!。输入字符 ‘A’,串口 2 接收到将其错位后输出。实验现象如图所示:

2022-10-25 11:05:11

RT-Thread学习笔记 RT-Thread的架构概述

RT-Thread 简介 作为一名 RTOS 的初学者,也许你对 RT-Thread 还比较陌生。然而,随着你的深入接触,你会逐渐发现 RT-Thread

2022-07-09 11:27:42

RT-Thread全球技术大会:POSIX FILE select的调用过程

在上午RT-Thread全球技术大会,RT-Thread开发者详细介绍了POSIX FILE select的调用过程。如下图:

2022-05-28 10:56:52

RT-Thread全球技术大会:RT-Thread测试用例集合案例

RT-Thread全球技术大会:RT-Thread测试用例集合案例           审核编辑:彭静

2022-05-27 16:34:46

RT-Thread全球技术大会:Kconfig在RT-Thread中的工作机制

RT-Thread全球技术大会:Kconfig在RT-Thread中的工作机制               审核编辑:彭静

2022-05-27 14:49:12

RT-Thread全球技术大会:萤石研发团队使用RT-Thread的技术挑战

RT-Thread全球技术大会:研发团队使用RT-Thread的技术挑战         审核编辑:彭静

2022-05-27 11:36:17

RT-Thread实现USB虚拟串口过程记录

记录——基于 RT-Thread 实现 USB 虚拟串口记录一下我在正点原子 F429 阿波罗开发板上实现 USB 虚拟串口的

2022-01-26 06:31:14
7天热门专题 换一换
相关标签