良许Linux教程网 干货合集 厚积薄发,我们一起学RTT UART设备驱动框架

厚积薄发,我们一起学RTT UART设备驱动框架

UART简介

STM32 芯片具有多个 USART 外设用于串口通讯,它是 Universal Synchronous Asynchronous Receiver and Transmitter 的缩写,即通用同步异步收发器可以灵活地与外部设备进行全双工数据交换。

有别于 USART,它还有具有 UART 外设(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。

简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。

UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。

其工作原理是将传输数据的每个字符一位接一位地传输。其传输数据格式如下:

image-20231009210923457
image-20231009210923457

UART设备框架学习笔记

RT-Thread 提供了一套简单的 I/O 设备模型框架,它位于硬件和应用程序之间,共分成三层,从上到下分别是 I/O 设备管理层、设备驱动框架层、设备驱动层 :

image-20231009210935050
image-20231009210935050

应用程序访问串口设备的接口:

image-20231009210937840
image-20231009210937840

下面我们直接来看个实例:

同时使用两个串口(uart1uart3),uart1作为系统打印调试串口,用来打印一些日志信息,uart3作为我们本次实验的测试串口,实现与串口调试助手的收发测试。

uart3设备启动后,往串口调试助手发送字符串I am uart3。同时,uart3设备使用中断的方式接收数据,然后再错位输出数据,比如收到ASCII码字符A,则会回复B

#define SAMPLE_UART_NAME    "uart3"          /* 串口设备名称           */
/* uart3应用函数 */
static int uart3_app(void)
{
    rt_err_t ret = RT_EOK;                      /* 函数返回值        */
    rt_thread_t tid;                            /* 动态线程句柄      */
    char uart3_name[RT_NAME_MAX];               /* 保存查找的设备名  */
    char usart3_tx_str[] = "I am uart3.\r\n";   /* uart3发送的字符串 */

    rt_strncpy(uart3_name, SAMPLE_UART_NAME, RT_NAME_MAX);
    
    /* 查找串口设备 */
    uart3_dev = rt_device_find(uart3_name);
    if (!uart3_dev)
    {
        rt_kprintf("find %s failed!\n", uart3_name);
        return RT_ERROR;
    }
    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
    /* 以读写及中断接收方式打开串口设备 */
    rt_device_open(uart3_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(uart3_dev, uart3_rx_callback);
    /* 发送字符串 */
    rt_device_write(uart3_dev, 0, usart3_tx_str, (sizeof(usart3_tx_str) - 1));
    
    /* 创建动态线程 :优先级 25 ,时间片 5个系统滴答,线程栈512字节 */
    tid = rt_thread_create("uart3_rx_thread",
   static_uart3_rx_entry,
   RT_NULL,
   STACK_SIZE,
   THREAD_PRIORITY,
   TIMESLICE);
    /* 创建成功则启动动态线程 */
    if (tid != RT_NULL)
    {
 rt_thread_startup(tid);
    }
    return ret;
}

我们的应用程序首先根据串口设备名字uart3来查找设备,查找到设备之后则返回串口设备句柄uart3_dev

为什么应用程序可以查找得到名字为uart3的串口设备呢?那是因为我们的硬件驱动层已经把名字为uart3的串口设备注册到系统中:

image-20231009210942098
image-20231009210942098
image-20231009210946722
image-20231009210946722

串口设备注册函数里会调用通用的设备注册函数

image-20231009210952247
image-20231009210952247

在这个流程中涉及到了如下函数:

  • uart3_app函数:在main.c文件中定义。
  • rt_hw_usart_init函数:在drv_usart.c文件中定义。
  • rt_hw_serial_register函数:在serial.c文件中定义。
  • rt_device_register函数:在device.c文件中定义。
  • rt_device_find函数:在device.c文件中定义。

在上面的RT-Thread驱动框架框图中,分为好几层,在这里的对应关系如下:

image-20231009210955192
image-20231009210955192

此处,main.c文件属于应用层,我们的应用程序为:

image-20231009210958048
image-20231009210958048

drv_usart.c文件属于硬件设备驱动层,是RT-Thread为我们提供的,其属于板级支持包中的一部分:

image-20231009211000814
image-20231009211000814

这一层与硬件相关,其调用底层芯片固件库,如:

image-20231009211004029
image-20231009211004029

serial.c文件属于驱动框架(驱动抽象层),是RT-Thread系统的组件:

image-20231009211006615
image-20231009211006615

其在RT-Thread源码中的位置如下:

image-20231009211009330
image-20231009211009330

device.c文件给应用程序提供操作设备的接口,这个文件属于RT-Thread内核文件。
RT-Thread 内核采用面向对象的设计思想进行设计,其中设备属于它的一类对象。其继承关系如下:

image-20231009211012778
image-20231009211012778

在这个应用程序中,我们用到了信号量(用其它同步机制也可以,比如事件),信号量属于IPC机制中的一种:

image-20231009211015502
image-20231009211015502

信号量用于线程与线程中断与线程间的同步中,在我们这个实验中是中断与线程间的同步。

在裸机开发中,有这样一种场景(中断接收数据,主函数中处理数据):

在串口的接收中断函数中接收数据,然后使用一个全局变量作为中断接收的标志,有触发中断,则这个标志变量被置位;另一方面,在我们的主函数的while循环中,判断这个标志位是否被置位,若置位则进行相应的操作,并把该标志变量清零。

在RT-Thread系统中,其IPC机制做的事情与上面这个裸机开发中的标志变量做的事情类似(中断与线程同步)。比如在我们这个实验中,若uart3的接收中断被触发,则会触发回调函数,如:

image-20231009211018143
image-20231009211018143

回调函数中进行释放信号量操作,在线程中阻塞等待接收信号量:

image-20231009211020948
image-20231009211020948

接收到数据之后,再错位发送数据。最终,我们的实验结果如下:

image-20231009211025166
image-20231009211025166

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部