• RT-Thread uart2串口dma idle接收不断帧


    硬件STM32F407,IDE使用RT-Thread Studio。

    uart2串口使用这两个引脚:

    功能IO端口
    UART2-TXPA2
    UART2-RXPA3



    UART2 - DMA接收配置

    • 先使能DMA接收,RX缓冲区可以稍微调大些。
      在这里插入图片描述

    • board.h 中添加宏,来使能 RX_DMA。
      在这里插入图片描述

    • 既然都打开了 board.h,再顺便把时钟源改为外部晶振。
      在这里插入图片描述

    • 编写 UART2 DMA 接收测试代码。

    • 发生接收事件后,会触发回调。回调内记录本次接收的消息长度,并发送信号量。线程内接收到信号量后开始执行后续的任务,调试输出接收到的长度和内容。
      main.c

    #include <rtthread.h>
    
    #define DBG_TAG "main"
    #define DBG_LVL DBG_LOG
    #include <rtdbg.h>
    
    #include "drivers/serial.h"
    rt_device_t u2_dev = RT_NULL;
    struct serial_configure u2_cfg = RT_SERIAL_CONFIG_DEFAULT;
    struct rt_semaphore u2_rx_sem;
    rt_thread_t u2_recv_thread;
    
    rt_size_t u2_rx_len = 0;
    rt_err_t u2_rx_callback(rt_device_t dev, rt_size_t size)
    {
        u2_rx_len = size; // 记录消息长度
        rt_sem_release(&u2_rx_sem);
        return RT_EOK;
    }
    
    void u2_recv_entry(void *parameter)
    {
        char rx_buf[256];
        rt_size_t len = 0;
        while (1) {
            rt_sem_take(&u2_rx_sem, RT_WAITING_FOREVER); // 等待信号量
            len = rt_device_read(u2_dev, 0, rx_buf, u2_rx_len);
            rx_buf[len] = '\0';
            rt_kprintf("u2 recv: %d, %s\n", len, rx_buf);
        }
    }
    
    int main(void)
    {
        rt_err_t err;
    
        u2_dev = rt_device_find("uart2");
        if (u2_dev == RT_NULL) {
            LOG_E("uart2 rt_device_find failed");
            return -EINVAL;
        }
    
        //rt_device_open(u2_dev, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
        err = rt_device_open(u2_dev, RT_DEVICE_FLAG_DMA_RX);
        if (err < 0) {
            LOG_E("uart2 rt_device_open failed");
            return err;
        }
    
        rt_device_control(u2_dev, RT_DEVICE_CTRL_CONFIG, (void *)&u2_cfg);
    
        rt_device_set_rx_indicate(u2_dev, u2_rx_callback); // 设置接收回调函数
    
        err = rt_sem_init(&u2_rx_sem, "u2_rx", 0, RT_IPC_FLAG_FIFO);
        if (err < 0) {
            LOG_E("uart2 rt_sem_init failed");
            return err;
        }
    
        u2_recv_thread = rt_thread_create("u2_recv", u2_recv_entry, NULL, 1024*2, 8, 5); // 优先级8,时间片长度5
    
        rt_thread_startup(u2_recv_thread);
    
        rt_device_write(u2_dev, 0, "hello", 5);
    
        return RT_EOK;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67



    编译错误解决

    • 编译后会提示缺少文件等错误。按如下更改。

    • 改动RTT源码,添加缺少的头文件。
      在这里插入图片描述

    • 再配置交叉编译器include目录,增加如下:

    "${workspace_loc:/${ProjName}/rt-thread/components/drivers/include/drivers}"
    "${workspace_loc:/${ProjName}/rt-thread/components/drivers/include/ipc}"
    
    • 1
    • 2

    在这里插入图片描述

    • 添加目录时请使用工作空间,使用的是相对工程文件的路径。(文件系统指的是磁盘的绝对路径,复制工程又要重新配置)
      在这里插入图片描述



    运行测试RX DMA接收,解决断帧

    • 接收正常,但当接收的一帧字节数较长时,非常容易出现断帧。
      在这里插入图片描述

    • 断帧的解决方法我参考这个,实测好用:
      使用RT-Thread的串口空闲+DMA收发数据

    • 找打 drv_usart.c,注释掉这两句。
      在这里插入图片描述

    • 编译验证,确认经如上修改后就没有了断帧。

    • 但当接收的一帧字节数大于缓冲区容量时,以前的内容会被覆盖。所以在硬件允许时,uart rx缓冲区可设置的大一些。

    • 测试发送一帧270字节,当缓冲区容量为256字节时,仅提示收到14字节,前面的内容被覆盖。
      在这里插入图片描述
      在这里插入图片描述



    关于RT-Thread的学习

      本来自己是没计划去学习 RT-Thread 的,但在MCU国产化替代进程中,发现大多数IC厂商提供的支持十分有限,可以说几乎都是在近几年内以STM32为蓝本进行的仿制,其中隐藏的雷坑单靠个人摸索去解决相当不推荐。再加之大多数原厂Demo是裸机的,很少有RTOS的。于是就想到了国产的 RT-Thread。

      试用了 RT-Thread Studio 感觉相当好用,MCU的外设驱动不用用户操心,又有比较多的扩展组件可用,开发者可在熟悉RT-Thread的基础上,专注于应用的开发。其对国产MCU的支持正在逐步完善,暂时有 AT32、APM32、CH32、ES32、GD32、MM32 等,虽然只支持部分型号,但个人目前只中意AT32F403A,好巧不巧正好有它的芯片支持包。希望国产MCU能抓住替换潮机会,抓紧完善生态,不然等价格回落又会有一大批人转回STM32。望疫情早些过去,想念前三年芯片的价格。

  • 相关阅读:
    [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
    【深度学习】Pytorch torch.autograd 自动差分引擎
    MySQL面试
    JSP中如何正确的填写include指令中的file路径呢?
    事务的概念-事务的概念、事务的定义(BEGIN TRANSACTION、COMMIT、ROLLBACK)
    基于SpringBoot+Vue+uniapp的疫情期间高校人员的详细设计和实现(源码+lw+部署文档+讲解等)
    【C++项目】高并发内存池第五讲内存回收释放过程介绍
    Spring Web MVC入门
    Ubuntu 16.04 xrdp远程桌面
    那些Drools规则的坑(各种疑难杂症汇集)
  • 原文地址:https://blog.csdn.net/Mark_md/article/details/125418583