首页 > 其他分享 >瑞芯微|rk3568 uart快速上手

瑞芯微|rk3568 uart快速上手

时间:2023-07-29 10:45:26浏览次数:30  
标签:8250 引脚 uart rk3568 ts data 瑞芯微 newtio

一、调试环境

平台: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

标签:8250,引脚,uart,rk3568,ts,data,瑞芯微,newtio
From: https://www.cnblogs.com/yikoulinux/p/17589399.html

相关文章

  • FPGA vivado quartus 设置外挂 编辑器
     1.vivado   tools->settings->editor ->customeditor... C:\\pg\\MicrosoftVSCodeInsiders\\Code-Insiders.exe[filename]  2.quartus tools->options->preferredtexteditortexteditor:custom command-line:"C:\pg\M......
  • Quartz任务调度快速入门
    了解Quartz体系结构Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的这些核心概念进行描述:●Job:是一个接口,只有一个方法voidexecute(JobExecutionContextcontext),开发者实现该接口定义运行任务,JobExe......
  • >.NET Core|--Quartz.Net|--控制台应用程序
    前言#VisualStudio版本MicrosoftVisualStudioProfessional2022(64位)#Quartz.Net版本Quartz.Net3.6.3#C#语言版本(别小看这个,否则我下面的代码在你那里很可能跑不起来)10.0安装Quartz.Net我是直接通过Nuget包管理器安装的其它安装方式,也可以使用命......
  • quartz.net 配置UseClustering
    Quartz.NET配置UseClustering概述在开始之前,我们需要明确一些概念。Quartz.NET是一个强大且灵活的开源任务调度库,它可以帮助我们在.NET应用程序中实现各种定时任务。而UseClustering则是Quartz.NET提供的一项功能,用于在多个节点之间分配和处理任务。本文将教你如何通过......
  • quartz.net core
    如何使用Quartz.NetCore介绍Quartz.NetCore是一个开源的任务调度库,可以帮助开发者实现定时任务的调度和执行。本文将指导你如何使用Quartz.NetCore。首先,让我们看一下整个实现过程的流程图。实现步骤下面是使用Quartz.NetCore实现定时任务的步骤:步骤描述步......
  • 基于RK3568J板卡高铁高清视频监控系统解决方案-迅为电子
     随着高速铁路的建设及铁路管理的精细化,越来越多的高速铁路在建设时已经开始规划高清视频监控系统,而现在铁路建设更是桥梁多、隧道多、公跨铁多,安全隐患增加,铁路的运行安全问题以及铁路沿线的设施安全、环境安全、铁路空域安全成为迫切需要解决的问题。    针对3568开......
  • 瑞芯微|如何让拥有双网口的Linux设备实现数据包转发?【超实用】
    本文主要讲解如何,解决基于3568实现双网口互通问题。一、组网如下图所示:rk3568自带2个千兆以太口,对应网卡名称为:eth0、eth1pc1和pc2分别连接这2个网口pc1与eth0连接,网段:192.168.30.0pc2与eth1连接,网段:192.168.40.0目标:实现pc1与pc2互通。组网也可以简化为:......
  • java定时定时任务quartz
    Quartz是一个Java版开源定时调度器,功能强悍,使用方便。一、核心概念1.Job表示一个工作,要执行的具体内容,此接口只有一个方法voidexecute(JobExecutionContextcontext)2.JobDetailJobDetail表示一个具体的可以执行的调度程序,Job是这个可以执行程序所要执行的内容内容,JobDetai......
  • UART——通用异步收发传输器
    特点:发送—并转串;接收—串转并;全双工传输1、发送:常见设置包含:起始位、数据位、波特率、奇偶校验类型、停止位、空闲位(1)起始位先发一个逻辑0,表示传输字符开始,依靠检测起始位来实现发送与接收方的时间同步。(2)数据位单个UART数据传输的数据位数,可以是5、6、7或8(默认)(3......
  • 迅为RK3568|RK3588开发板车牌识别|RKNPU2人工智能视频重磅更新!
     ......