瑞芯微|rk3568 uart快速上手

news2024/9/24 2:09:17

一、调试环境

平台:rk3568
kernel: 4.19.232
SDK: rk_android11.0_sdk
Board: rk3568-evb1-ddr4-v10

二、 rk3568 uart控制器

1. 特性:

rk3568 UART控制器特性如下:

- UART控制器通道:UART0~UART8    【datasheet好像写的有问题】
- 包含2组64字节的 FIFO,用于接收和传输  
- 支持流控
- 支持速率 115.2Kbps, 460.8Kbps, 921.6Kbps, 1.5Mbps, 3Mbps, 4Mbps
- 支持5、6、7、8 bits数据位。
- 支持1、1.5、2 bits停止位。
- 支持奇校验和偶校验。
- 支持基于中断/DMA 模式

2. UART控制器架构

  1. APB INTERFACE
    处理器通过APB接口访问UART的数据,做控制,以及状态信息。
    UART支持8、16和32位的APB数据总线宽度。

  2. Register block
    负责UART的主要功能,包括控制、状态和中断产生。

  3. Modem Synchronization block
    同步modem输入信号.

  4. FIFO block
    负责FIFO控制和存储或向发送信号以控制外部RAM。

  5. Baud Clock Generator
    收发比特率设置。

  6. Serial Transmitter
    数据发送模块。

  7. Serial Receiver
    数据接收模块。

3. 控制器驱动

瑞芯微提供sdk中已经提供了8250uart驱动。

以下为主要驱动文件:

drivers/tty/serial/8250/8250_core.c     # 8250串口驱动核心
drivers/tty/serial/8250/8250_dw.c       # Synopsis DesignWare 8250串口驱动
drivers/tty/serial/8250/8250_dma.c     # 8250串口DMA驱动
drivers/tty/serial/8250/8250_port.c      # 8250串口端口操作
drivers/tty/serial/8250/8250_early.c     # 8250串口early console驱动

4. 设备树:

普通串口设备将会根据dts中的aliase来对串口进行编号,对应注册成ttySx设备。
dts中的aliases如下:

 aliases {
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
......
@kernel\arch\arm64\boot\dts\rockchip\rk3568.dtsi

	uart6: serial@fe6a0000 {
		compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart";
		reg = <0x0 0xfe6a0000 0x0 0x100>;
		interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>;
		clock-names = "baudclk", "apb_pclk";
		reg-shift = <2>;
		reg-io-width = <4>;
		dmas = <&dmac0 12>, <&dmac0 13>;
		pinctrl-names = "default";
		pinctrl-0 = <&uart6m0_xfer>;
		status = "disabled";
	};

UART的板级dts配置只有以下参数允许修改:

  • dma-names:
    “tx” 打开tx dma
    “rx” 打开rx dma
    “!tx” 关闭tx dma
    “!rx” 关闭rx dma
  • pinctrl-0:
    &uart1m0_xfer 配置tx和rx引脚为iomux group 0
    &uart1m1_xfer 配置tx和rx引脚为iomux group 1
    &uart1m0_ctsn和&uart1m0_rtsn 配置硬件自动流控cts和rts引脚为iomux group 0
    &uart1m1_ctsn和&uart1m1_rtsn 配置硬件自动流控cts和rts引脚为iomux group 1
  • status:
    “okay” 打开
    “disabled” 关闭

引脚说明在下面定义:
以UART6为例:

@kernel\arch\arm64\boot\dts\rockchip\rk3568-pinctrl.dtsi

	uart6 {
		/omit-if-no-ref/
		uart6m0_xfer: uart6m0-xfer {
			rockchip,pins =
				/* uart6_rxm0 */
				<2 RK_PA3 3 &pcfg_pull_up>,
				/* uart6_txm0 */
				<2 RK_PA4 3 &pcfg_pull_up>;
		};

		/omit-if-no-ref/
		uart6m0_ctsn: uart6m0-ctsn {
			rockchip,pins =
				/* uart6m0_ctsn */
				<2 RK_PC0 3 &pcfg_pull_none>;
		};

		/omit-if-no-ref/
		uart6m0_rtsn: uart6m0-rtsn {
			rockchip,pins =
				/* uart6m0_rtsn */
				<2 RK_PB7 3 &pcfg_pull_none>;
		};

		/omit-if-no-ref/
		uart6m1_xfer: uart6m1-xfer {
			rockchip,pins =
				/* uart6_rxm1 */
				<1 RK_PD6 3 &pcfg_pull_up>,
				/* uart6_txm1 */
				<1 RK_PD5 3 &pcfg_pull_up>;
		};
	};

5. 使用硬件自动流控

UART使用硬件自动流控时,需要确保UART驱动使能硬件自动流控功能,且在dts中已经切换cts和rts流控引脚的iomux。

建议在高波特率(1.5M波特率及以上)、大数据量的场景下都使用硬件自动流控,即使用四线UART。

6. 使用串口唤醒系统

串口唤醒系统功能是在系统待机时串口保持打开,并且把串口中断设置为唤醒源。使用时需要在dts中增
加以下参数:

	&uart1 {
		wakeup-source;
	}

注意,串口唤醒系统需要同时修改trust固件,请联系Rockchip以获取支持。

三、 移植

1. 修改设备树

sdk中UART默认并没有打开,所以我们只需要修改设备树就可以了。

下面以uart6为例,带流控:

/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi

&uart6{
       status = "okay";
       pinctrl-names = "default";
       pinctrl-0 = <&uart6m1_xfer >;
};

注意:

引脚选择有两种配置: m0、m1;

编写设备树之前,查看电路图先确认,

公板是m1。

只有m0支持流控,如果需要支持设置 pinctrl-0:

​ pinctrl-0 = <&uart6m0_xfer &uart6m0_ctsn &uart6m0_rtsn>;

重新编译烧录boot.img即可。

查看设备文件

rk3568_r:/ # ls /dev/ttyS*
/dev/ttyS6  /dev/ttyS8

其中ttyS8是给蓝牙使用。

2. 引脚复用问题:uart6与gmac0冲突

uart6引脚与以太网口Gmac0会有冲突:

@kernel\arch\arm64\boot\dts\rockchip\rk3568-pinctrl.dtsi

	gmac0 {
		/omit-if-no-ref/
		gmac0_miim: gmac0-miim {
			rockchip,pins =
				/* gmac0_mdc */
				<2 RK_PC3 2 &pcfg_pull_none>,
				/* gmac0_mdio */
				<2 RK_PC4 2 &pcfg_pull_none>;
		};

		…………………………


		/omit-if-no-ref/
		gmac0_rgmii_bus: gmac0-rgmii-bus {
			rockchip,pins =
				/* gmac0_rxd2 */
				<2 RK_PA3 2 &pcfg_pull_none>,
				/* gmac0_rxd3 */
				<2 RK_PA4 2 &pcfg_pull_none>,
				/* gmac0_txd2 */
				<2 RK_PA6 2 &pcfg_pull_none_drv_level_2>,
				/* gmac0_txd3 */
				<2 RK_PA7 2 &pcfg_pull_none_drv_level_2>;
		};
	};

只需要禁用gmac0即可

/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi

&gmac0 {
	………………
	phy-handle = <&rgmii_phy0>;
	status = "disable";
};

3. 通过寄存器,查看引脚复用配置情况

uart6使用到的引脚如下:

请添加图片描述

1) GRF_GPIO1D_IOMUX_H

Address: Operational Base + offset (0x001C)

2) GRF_GPIO2A_IOMUX_L

Address: Operational Base + offset (0x0020)

3) GRF_GPIO2A_IOMUX_H

Address: Operational Base + offset (0x0024)

4) GRF_GPIO2B_IOMUX_H

Address: Operational Base + offset (0x002C)

5) GRF_GPIO2C_IOMUX_L

Address: Operational Base + offset (0x0030)

uart6寄存器配置对应位位置如下图所示:,

我们只设置m1引脚为uart6的收发引脚,m0引脚未设置

所以只有寄存器 0xFDC60000+0x1c 的 bit[11:4]为 33

四、测试

公板预留了UART2~UART7的接口(4根线),

一口君不会焊接线,所以直接找的硬件工程师把线连好,

我只负责测试。

板子上的测试程序,瑞芯微官方已经提供了: ts_uart.uart

该工具获取,见文章底部

1. 移植ts_uart.uart

adb root
adb remount
adb push ts_uart.uart /bin
adb push send_0x55 /bin
adb push send_00_ff /bin

2. ts_uart.uart实用

1) 查看ts_uart.uart帮助信息:

rk3568_r:/ # ts_uart.uart

 Use the following format to run the HS-UART TEST PROGRAM
 ts_uart v1.1
 For sending data:
 ./ts_uart <tx_rx(s/r)> <file_name> <baudrate> <flow_control(0/1)> <max_delay(0-100)> <random_size(0/1)>
 tx_rx : send data from file (s) or receive data (r) to put in file
 file_name : file name to send data from or place data in
 baudrate : baud rate used for TX/RX
 flow_control : enables (1) or disables (0) Hardware flow control using RTS/CTS lines
 max_delay : defines delay in seconds between each data burst when sending. Choose 0 for continuous stream.
 random_size : enables (1) or disables (0) random size data bursts when sending. Choose 0 for max size.
 max_delay and random_size are useful for sleep/wakeup over UART testing. ONLY meaningful when sending data
 Examples:
 Sending data (no delays)
 ts_uart s init.rc 1500000 0 0 0 /dev/ttyS0
 loop back mode:
 ts_uart m init.rc 1500000 0 0 0 /dev/ttyS0
 receive, data must be 0x55
 ts_uart r init.rc 1500000 0 0 0 /dev/ttyS0

2) 非流控read:

ts_uart.uart r init.rc 115200 0 0 0  /dev/ttyS6

3) 流控read:

ts_uart.uart r init.rc 115200 1 0 0  /dev/ttyS6

4) 非流控write:

ts_uart.uart s /data/send_0x55.0x55 115200 0 0 0 /dev/ttyS6

5) 流控write:

ts_uart.uart s /data/send_0x55.0x55 115200 1 0 0 /dev/ttyS6

五、编写自己的测试程序

下面是一口君自己编写的测试程序,可以实现简单的数据收发,

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<termios.h>
#include<string.h>

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	if  ( tcgetattr( fd,&oldtio)  !=  0) 
	{
		perror("SetupSerial 1");
		return -1;
	}
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag  |=  CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;

	switch( nBits )
	{
	case 7:
		newtio.c_cflag |= CS7;
		break;
	case 8:
		newtio.c_cflag |= CS8;
		break;
	}

	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':  
		newtio.c_cflag &= ~PARENB;
		break;
	}

	switch( nSpeed )
	{
	case 2400:
		cfsetispeed(&newtio, B2400);
		cfsetospeed(&newtio, B2400);
		break;
	case 4800:
		cfsetispeed(&newtio, B4800);
		cfsetospeed(&newtio, B4800);
		break;
	case 9600:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	case 115200:
		cfsetispeed(&newtio, B115200);
		cfsetospeed(&newtio, B115200);
		break;
	case 460800:
		cfsetispeed(&newtio, B460800);
		cfsetospeed(&newtio, B460800);
		break;
	default:
		cfsetispeed(&newtio, B9600);
		cfsetospeed(&newtio, B9600);
		break;
	}
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;
	newtio.c_cc[VTIME]  = 0;
	newtio.c_cc[VMIN] = 0;
	tcflush(fd,TCIFLUSH);
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
//	printf("set done!\n\r");
	return 0;
}

int main(void)
{
	int fd1;
	char  data[10] = "yikoupeng";
	char buf[100]={0};

	fd1 = open( "/dev/ttyS6", O_RDWR);
	if (fd1 == -1)
		exit(1);

	nset = set_opt(fd1, 115200, 8, 'N', 1);
	if (nset == -1)
	{
		exit(1);	
	}
    printf("write start!\n");	
	write(fd1,data,strlen(data));	
    read(fd1,buf,sizeof(buf));
    printf("rcv:%s\n",buf);
	close(fd1);
	return 0;
}

工具ts_uart.uart s获取

公众号后台回复:rxw

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/806450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

44.C++ static的用法

目录 一、静态成员变量 二、静态成员函数 三、局部静态变量 今天进行了新的学习。C关于static的用法。 只有.cpp文件能够被编译链接 在C中&#xff0c;static关键字有多种用法&#xff0c;主要用于以下几个方面&#xff1a; 一、静态成员变量 在类中使用static关键字修…

使用easyui的tree组件实现给角色快捷分配权限功能

这篇文章主要介绍怎么实现角色权限的快捷分配功能&#xff0c;不需要像大多数项目的授权一样&#xff0c;使用类似穿梭框的组件来授权。 具体实现&#xff1a;通过菜单树的勾选和取消勾选来给角色分配权限&#xff0c;在这之前&#xff0c;需要得到角色的菜单树&#xff0c;角色…

基于内核链表和JSON的MQTT的使用

一、内核链表 1.回顾单链表的插入和遍历 假设学生结构体信息如下&#xff0c;封装一个单链表的插入接口和遍历输出的接口&#xff0c;在主函数中利用封装的接口生成一个学生链表&#xff0c;并遍历输出链表的学生信息。 #include <stdio.h> #include <string.h>…

Spring MVC学习笔记,包含mvc架构使用,过滤器、拦截器、执行流程等等

&#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 Spring MVC 习笔记1、Spring MVC demo2、Spring MVC 中常见注解3、数据处理3.1、请求参数处理3.2、响应数据处理 4、RESTFul 风格5、静态资源处理6、HttpMessageConverter 转换器7、过…

iOS开发-下拉刷新动画依次渐隐渐显Indicator指示器效果

iOS开发-下拉刷新动画依次渐隐渐显Indicator指示器效果 之前开发中实现下拉刷新动画三个球依次渐隐渐显指示器效果。 一、效果图 二、基础动画 CABasicAnimation类的使用方式就是基本的关键帧动画。 所谓关键帧动画&#xff0c;就是将Layer的属性作为KeyPath来注册&#xf…

【Linux进程】进程控制(下) {进程程序替换:程序替换的工作原理,程序替换函数exec*,简单的命令行解释器}

四、进程程序替换 之前用fork创建子进程后&#xff0c;父子进程执行同一个程序的不同代码段。 如何使子进程执行另一个不同的程序呢&#xff1f;子进程需要进行程序替换&#xff01; 程序替换&#xff0c;就是通过特定的接口&#xff0c;将磁盘上一个全新的程序&#xff08;包…

STL中的神秘“指针”:迭代器

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;C学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我最大…

【Linux】- RPM 与 YUM

RPM 与 YUM 1.1 rpm 包的管理1.2 rpm 包的简单查询指令1.3 rpm 包的其它查询指令&#xff1a;1.4 卸载 rpm 包&#xff1a;2.1 安装 rpm 包3.1 yum3.2 yum 的基本指令3.3 安装指定的 yum 包3.4 yum 应用实例&#xff1a; 1.1 rpm 包的管理 介绍 rpm 用于互联网下载包的打包及安…

SDN系统方法 | 9. 接入网

随着互联网和数据中心流量的爆炸式增长&#xff0c;SDN已经逐步取代静态路由交换设备成为构建网络的主流方式&#xff0c;本系列是免费电子书《Software-Defined Networks: A Systems Approach》的中文版&#xff0c;完整介绍了SDN的概念、原理、架构和实现方式。原文: Softwar…

【Spring Boot丨序列化、反序列化】

序列化、反序列化 概述Jackson 序列化和反序列化简介自定义序列化器注册外部序列化程序&#xff1a; 指定类的 Json 序列化、反序列化 主页传送门&#xff1a;&#x1f4c0; 传送 概述 序列化是将对象转换为字节序列的过程&#xff0c;而反序列化则是将字节序列恢复为对象的过…

用于系统监控及进程管理python库之psutil

前言 对于一个job级别应用再进行测试的过程中&#xff0c;不可避免测试该服务的一些性能&#xff0c;比如占有cpu的使用量&#xff0c;使用的memory的大小等&#xff0c;比较简单的方式是在服务中起一个并行的线程&#xff0c;每隔一段时间打印这些关注量的大小&#xff0c;之后…

【二分答案】CF1661 C

Problem - C - Codeforces 题意&#xff1a; 思路&#xff1a; 在check的时候&#xff0c;我们要尽量用算贡献的思想&#xff0c;并且大胆贪心 Code&#xff1a; #include <bits/stdc.h>#define int long longusing namespace std;const int mxn3e510; const int mxe3…

MySQL基础扎实——列对比运算符是什么

词义解释 在MySQL中&#xff0c;用于进行列对比的运算符主要有以下几种&#xff0c;其实就是逻辑运算符号&#xff1a; 等号&#xff08;&#xff09;&#xff1a;用于判断两个列是否相等&#xff0c;例如&#xff1a;column_name value。 不等号&#xff08;<>或!&am…

Verilog语法学习——边沿检测

边沿检测 代码 module edge_detection_p(input sys_clk,input sys_rst_n,input signal_in,output edge_detected );//存储上一个时钟周期的输入信号reg signal_in_prev;always (posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)signal_in_prev < 0;else…

95. Python基础教程:异常处理try...except语句

【目录】 文章目录 1. try...except语法解析2. 程序异常3. except的4种使用方式3.1 单独的except3.2 except 异常名称3.3 except 异常类型 as 别名3.4 except (异常类型1,异常类型2) as 别名 4. 总结 【正文】 1. try…except语法解析 try[traɪ]&#xff1a;尝试。 except[…

【QT】Day4

1> 思维导图 2> 手动完成服务器的实现&#xff0c;并具体程序要注释清楚 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器类 #include <QTcpSocket> //客户端类 #include <QMessageBox> //…

综合能源系统(4)——综合能源系统建模方法

综合能源系统关键技术与典型案例  何泽家&#xff0c;李德智主编 本文主要从物理、信息、价值三个方面介绍综合能源系统关键技术&#xff0c;如图3-1所示。 物理方面&#xff1a;主要包括综合能源系统建模分析技术、规划设计(配置)技术、优化控制技术、运行维护技术和综合评…

mybatisPlus之逻辑删除解读

目录 为什么会有逻辑删除 逻辑删除基本介绍 逻辑删除的使用 局部使用 全局使用 为什么会有逻辑删除 在我们对数据进行增删查改的时候&#xff0c;对于删除操作来说&#xff0c;我们思考一个问题&#xff0c;在实际开发中我们真的会将数据完成从数据库中删除掉么&#xff1f…

二叉搜索树(二叉排序树)

文章目录 基本概念基本操作实现分析插入数据查找数据删除数据遍历数据 源码 基本概念 二叉搜索树也叫搜索二叉树、二叉排序树、排序二叉树。是一种对查找和排序都有用的特殊二叉树。 二叉搜索树&#xff08;Binary Search Tree&#xff0c;简称BST&#xff09; 如何构建一颗二叉…

【使用维纳滤波进行信号分离】基于维纳-霍普夫方程的信号分离或去噪维纳滤波器估计(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…