基于瑞芯微RV1109 Linux串口驱动调试心得(给正点原子DS100示波器点赞!)

简介: 基于瑞芯微RV1109 Linux串口驱动调试心得(给正点原子DS100示波器点赞!)

在调试的时候发现板厂供应商调整了RK原厂的原理图设计,然后他们把串口5原来的M0的连接换成了另一路IO M1,也就是说他们并没有按照原厂的原理图去设计,所以UART5根本动不起来,由于好久没搞驱动了,对驱动也不熟,所以只能硬着头皮追代码、上示波器、上逻辑分析仪调试等等,走了很多弯路,最后终于把问题给找出来了,在此记录一下调试过程。

640.png

640.png

1、关于uart5节点pinctrl配置的描述

uart5 {
  /omit-if-no-ref/
  uart5m0_xfer: uart5m0-xfer {
   rockchip,pins =
    /* uart5_rx_m0 */
    <3 RK_PA7 4 &pcfg_pull_up>,
    /* uart5_tx_m0 */
    <3 RK_PA6 4 &pcfg_pull_up>;
  };
  /omit-if-no-ref/
  uart5m0_ctsn: uart5m0-ctsn {
   rockchip,pins =
    <3 RK_PB1 4 &pcfg_pull_none>;
  };
  /omit-if-no-ref/
  uart5m0_rtsn: uart5m0-rtsn {
   rockchip,pins =
    <3 RK_PB0 4 &pcfg_pull_none>;
  };
  /omit-if-no-ref/
  uart5m1_xfer: uart5m1-xfer {
   rockchip,pins =
    /* uart5_rx_m1 */
    <2 RK_PB1 4 &pcfg_pull_up>,
    /* uart5_tx_m1 */
    <2 RK_PB0 4 &pcfg_pull_up>;
  };
  /omit-if-no-ref/
  uart5m1_ctsn: uart5m1-ctsn {
   rockchip,pins =
    <2 RK_PB3 4 &pcfg_pull_none>;
  };
  /omit-if-no-ref/
  uart5m1_rtsn: uart5m1-rtsn {
   rockchip,pins =
    <2 RK_PB2 4 &pcfg_pull_none>;
  };
  /omit-if-no-ref/
  uart5m2_xfer: uart5m2-xfer {
   rockchip,pins =
    /* uart5_rx_m2 */
    <2 RK_PA1 3 &pcfg_pull_up>,
    /* uart5_tx_m2 */
    <2 RK_PA0 3 &pcfg_pull_up>;
  };
  /omit-if-no-ref/
  uart5m2_ctsn: uart5m2-ctsn {
   rockchip,pins =
    <2 RK_PA3 3 &pcfg_pull_none>;
  };
  /omit-if-no-ref/
  uart5m2_rtsn: uart5m2-rtsn {
   rockchip,pins =
    <2 RK_PA2 3 &pcfg_pull_none>;
  };
};

我的电路原理图是这样的:

640.png

看到如上原理图的标识,我们很容易就知道pinctrl配置的IO是什么:

uart5m1_xfer: uart5m1-xfer {
 rockchip,pins =
 /* uart5_rx_m1 */
 <2 RK_PB1 4 &pcfg_pull_up>,
 /* uart5_tx_m1 */
 <2 RK_PB0 4 &pcfg_pull_up>;
};

也就是上面定义的这个节点。

2、原厂默认配置的uart5节点的配置描述

原厂dtsi

rv1126.dtsi

关于aliases的配置:

aliases {
  i2c0 = &i2c0;
  i2c1 = &i2c1;
  i2c2 = &i2c2;
  i2c3 = &i2c3;
  i2c4 = &i2c4;
  i2c5 = &i2c5;
  mmc0 = &emmc;
  mmc1 = &sdio;
  mmc2 = &sdmmc;
  serial0 = &uart0;
  serial1 = &uart1;
  serial2 = &uart2;
  serial3 = &uart3;
  serial4 = &uart4;
  serial5 = &uart5;
  spi0 = &spi0;
  spi1 = &spi1;
  dphy0 = &csi_dphy0;
  dphy1 = &csi_dphy1;
};

驱动会根据以下的aliase,来对应串口编号,比如serial0最后会在/dev/目录下生成ttyS0,其它以此类推:

640.png

关于uart5dts配置:

uart5: serial@ff5a0000 {
  compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
  reg = <0xff5a0000 0x100>;
  interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
  reg-shift = <2>;
  reg-io-width = <4>;
  dmas = <&dmac 15>, <&dmac 14>;
  clock-frequency = <24000000>;
  clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
  clock-names = "baudclk", "apb_pclk";
  pinctrl-names = "default";
  pinctrl-0 = <&uart5m0_xfer &uart5m0_ctsn &uart5m0_rtsn>;
  status = "disabled";
};

这个配置一般来说是原厂的一个默认的参数配置,然后我们只需要找到板厂的dts将节点的状态设置为okay,那么这个驱动一般来说就可以使用了。

3、板厂端开启串口功能

3.1、基于中断收发的串口配置

默认情况下,配置的串口是基于中断方式的。


在xxx.dts(你自己板子的dts配置)中添加你的端口使能:

&uart5 {
 pinctrl-0 = <&uart5m1_xfer &uart5m1_ctsn &uart5m1_rtsn>;
 status = "okay";
};

一般情况下,串口不需要硬件流控来进行控制,所以可以将上面的这个节点简化为如下:

&uart5 {
 pinctrl-0 = <&uart5m1_xfer>;
 status = "okay";
};

其中uart5m1_xfer在pinctrl中已经有所体现:

uart5m1_xfer: uart5m1-xfer {
 rockchip,pins =
 /* uart5_rx_m1 */
 <2 RK_PB1 4 &pcfg_pull_up>,
 /* uart5_tx_m1 */
 <2 RK_PB0 4 &pcfg_pull_up>;
};

这部分一定要和硬件原理图对应好,确保配置正确,否则串口很可能工作不正常,配置完毕后如果串口没有开DMA的时候,在使用这个串口驱动的时候可能会看到如下信息:

640.png

但并不影响正常使用,报这个错的原因是因为没有配置dma的端口。

3.2、基于dma方式配置

这部分参考原厂的UART文档的:关于DMA的使用 有非常清晰的描述:

640.png

如果要配置成DMA的方式,那么DTS要做如下的修改:

&uart5 {
 pinctrl-0 = <&uart5m1_xfer>;
 //使能DMA发送和接收
 dma-names = "tx", "rx"; 
 //配置DMAC连接的通道号
 dmas = <&dmac 15>, <&dmac 14>;
 status = "okay";
};

这里的DMAC通道号需要通过手册来Req number,如下图:

640.png

4、串口驱动调试

4.1、查看开机是否有串口驱动加载信息

调试指令如下:

dmesg | grep "serial"

可以看到:

640.png

4.2、查看串口pinctrl的占用情况

调试指令如下:

cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins | grep ff5a0000

如上,这里的ff5a0000指的是设备树节点的标识:

640.png

可以看到:

640.png

打出来的信息会告诉你,当前你的串口的发送、接收以及硬件流控的引脚接在CPU管脚的哪个位置,如上所示,我的串口收发引脚分别接在gpio2-8以及gpio2-9的位置,即是第二组GPIO的第8和第9这两个管脚,我们来查一下GPIO管脚的序号:

640.png

4.3、查看串口时钟

调试指令如下:

cat /sys/kernel/debug/clk/clk_summary | grep uart

可以看到:

640.png

这个时钟频率就是设备树里配置的时钟频率,如下:

640.png

波特率 = 时钟源 / 16 / DIV,DIV是分频系数。


我这边的时钟默认分频系数为1,所以DIV为1,根据以上计算公式,可计算得到波特率为:


波特率 = 24000000 / 16 / 1 = 1500000

4.4、测试串口是否收发正常

我们可以借助busybox的stty工具来进行设置,接下来我们将串口波特率为115200:

640.png

640.png

接下来用串口调试助手进行收发测试:

640.png

测试双向发送和接收成功!驱动调试完成!下班鸟!秀一下调试过程中用正点原子DS100示波器打出来的时序图,此处一定要推荐下正点原子的DS100示波器,要是没有它,估计我不能下午6点半按时下班了吧!640.png

往期精彩

一个强大的音视频编解码库-rkmedia的应用


瑞芯微RV1109配置7寸电容触摸屏的方向修改笔记


如何添加APP到Buildroot里(以瑞芯微rv1126为例)


瑞芯微RV1109配置7寸电容触摸屏的方向修改笔记


基于瑞芯微RV1109 Linux触摸屏GT911驱动调试心得


Linux MIPI DSI LCD设备驱动开发调试细节学习笔记(一)


Linux MIPI DSI驱动调试笔记-LCD时序参数配置(三)


Linux MIPI DSI驱动调试笔记-设备树DCS格式序列之配置LCD初始化代码(二)


瑞芯微RV1109配置GPIO设备树修改笔记(熟悉新平台从点灯大法开始)


新产品立项了,作为嵌入式软件工程师该如何来开展设计工作?(个人经验分享)

目录
相关文章
|
5天前
|
Linux
Linux(5)WIFI/BT调试笔记
Linux(5)WIFI/BT调试笔记
21 0
|
1月前
|
监控 Shell Linux
【Shell 命令集合 网络通讯 】Linux 分析串口的状态 statserial命令 使用指南
【Shell 命令集合 网络通讯 】Linux 分析串口的状态 statserial命令 使用指南
33 0
|
1月前
|
Linux 编译器 程序员
【Linux 调试秘籍】深入探索 C++:运行时获取堆栈信息和源代码行数的终极指南
【Linux 调试秘籍】深入探索 C++:运行时获取堆栈信息和源代码行数的终极指南
68 0
|
5天前
|
Linux Android开发
Linux(6)CH9434 SPI调试笔记
Linux(6)CH9434 SPI调试笔记
13 0
|
12天前
|
Linux Go
Linux命令Top 100驱动人生! 面试必备
探索Linux命令不再迷茫!本文分10部分详解20个基础命令,带你由浅入深掌握文件、目录管理和文本处理。 [1]: <https://cloud.tencent.com/developer/article/2396114> [2]: <https://pan.quark.cn/s/865a0bbd5720> [3]: <https://yv4kfv1n3j.feishu.cn/docx/MRyxdaqz8ow5RjxyL1ucrvOYnnH>
64 0
|
25天前
|
安全 Linux
嵌入式Linux系统关闭串口调试信息的输出
嵌入式Linux系统关闭串口调试信息的输出
19 1
|
25天前
|
Linux
Linux驱动运行灯 Heartbeat
Linux驱动运行灯 Heartbeat
12 0
|
25天前
|
传感器 Linux API
嵌入式Linux串口编程简介
嵌入式Linux串口编程简介
19 1
|
1月前
|
缓存 Linux iOS开发
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
【C/C++ 集成内存调试、内存泄漏检测和性能分析的工具 Valgrind 】Linux 下 Valgrind 工具的全面使用指南
66 1
|
6天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。