RK3399 UART Driver

Debug RS232 RS485

Posted by LXG on September 21, 2022

UART 使用-firefly

Firefly-RK3399

RK3399 支持五路 UART:UART0, UART1, UART2, UART3, UART4,都拥有两个 64 字节的 FIFO 缓冲区,用于数据接收和发送。 其中:

  • UART0 用于蓝牙传输,UART2 用作调试串口,只有 UART0 和 UART3 支持硬件自动流控。
  • 支持比特率 115.2Kbps,460.8Kbps,921.6Kbps,1.5Mbps,3Mbps,4Mbps。
  • 支持自选波特率,即使使用非整数时钟分频器
  • 支持基于中断或基于 DMA 的模式
  • 支持 5-8l 位宽度传输

驱动代码


kernel/drivers/tty/serial/8250$ tree 
.
├── 8250_accent.c
├── 8250_acorn.c
├── 8250_boca.c
├── 8250_core.c
├── 8250_dma.c
├── 8250_dw.c
├── 8250_early.c
├── 8250_em.c
├── 8250_exar_st16c554.c
├── 8250_fintek.c
├── 8250_fourport.c
├── 8250_fsl.c
├── 8250_gsc.c
├── 8250.h
├── 8250_hp300.c
├── 8250_hub6.c
├── 8250_ingenic.c
├── 8250_lpc18xx.c
├── 8250_mid.c
├── 8250_mtk.c
├── 8250_omap.c
├── 8250_pci.c
├── 8250_pnp.c
├── 8250_port.c
├── 8250_uniphier.c
├── Kconfig
├── Makefile
└── serial_cs.c

串口设备


ls -al dev/tty*
crw-rw-rw- 1 root      root           5,   0 2013-01-18 16:50 dev/tty
crw------- 1 root      root         254,   0 2013-01-18 16:50 dev/ttyFIQ0                   // debug uart2_c
crw-rw---- 1 bluetooth net_bt_stack   4,  64 2013-01-18 16:50 dev/ttyS0                     // uart0
lrwxrwxrwx 1 root      root               10 2013-01-18 16:50 dev/ttyS3 -> /dev/ttyS4       // RS485 uart4
crwxrwxrwx 1 root      root           4,  68 2013-01-18 16:50 dev/ttyS4
crw-rw-rw- 1 radio     radio        188,   0 2013-01-18 16:50 dev/ttyUSB0                   // RS232
crw-rw-rw- 1 radio     radio        188,   1 2013-01-18 16:50 dev/ttyUSB1                   // RS232

原理图

RS485

rk3399_uart_485

rk3399_uart_485_2

RS232

rk3399_usb_to_uart

rk3399_uart_232

rk3399_uart_232_2

UART DEBUG

rk3399_uart_debug

DTS 配置

./arch/arm64/boot/dts/rockchip/rk3399.dtsi


        aliases {
                i2c0 = &i2c0;
                i2c1 = &i2c1;
                i2c2 = &i2c2;
                i2c3 = &i2c3;
                i2c4 = &i2c4;
                i2c5 = &i2c5;
                i2c6 = &i2c6;
                i2c7 = &i2c7;
                i2c8 = &i2c8;
                serial0 = &uart0;
                serial1 = &uart1;
                serial2 = &uart2;
                serial3 = &uart3;
                serial4 = &uart4;
                dsi0 = &dsi;
                dsi1 = &dsi1;
        };


	uart0: serial@ff180000 {
		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
		reg = <0x0 0xff180000 0x0 0x100>;
		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
		clock-names = "baudclk", "apb_pclk";
		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>;
		reg-shift = <2>;
		reg-io-width = <4>;
		pinctrl-names = "default";
		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
		status = "disabled";
	};

	uart1: serial@ff190000 {
		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
		reg = <0x0 0xff190000 0x0 0x100>;
		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
		clock-names = "baudclk", "apb_pclk";
		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH 0>;
		reg-shift = <2>;
		reg-io-width = <4>;
		pinctrl-names = "default";
		pinctrl-0 = <&uart1_xfer>;
		status = "disabled";
	};

	uart2: serial@ff1a0000 {
		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
		reg = <0x0 0xff1a0000 0x0 0x100>;
		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
		clock-names = "baudclk", "apb_pclk";
		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>;
		reg-shift = <2>;
		reg-io-width = <4>;
		pinctrl-names = "default";
		pinctrl-0 = <&uart2c_xfer>;
		status = "disabled";
	};

	uart3: serial@ff1b0000 {
		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
		reg = <0x0 0xff1b0000 0x0 0x100>;
		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
		clock-names = "baudclk", "apb_pclk";
		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>;
		reg-shift = <2>;
		reg-io-width = <4>;
		pinctrl-names = "default";
		pinctrl-0 = <&uart3_xfer &uart3_cts &uart3_rts>;
		status = "disabled";
	};

        uart4: serial@ff370000 {
                compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
                reg = <0x0 0xff370000 0x0 0x100>;
                clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>;
                clock-names = "baudclk", "apb_pclk";
                interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH 0>;
                reg-shift = <2>;
                reg-io-width = <4>;
                pinctrl-names = "default";
                pinctrl-0 = <&uart4_xfer>;
                status = "disabled";
        };


	pinctrl: pinctrl {
		compatible = "rockchip,rk3399-pinctrl";
		rockchip,grf = <&grf>;
		rockchip,pmu = <&pmugrf>;
		#address-cells = <0x2>;
		#size-cells = <0x2>;
		ranges;

		uart0 {
			uart0_xfer: uart0-xfer {
				rockchip,pins =
					<2 16 RK_FUNC_1 &pcfg_pull_up>,
					<2 17 RK_FUNC_1 &pcfg_pull_none>;
			};

			uart0_cts: uart0-cts {
				rockchip,pins =
					<2 18 RK_FUNC_1 &pcfg_pull_none>;
			};

			uart0_rts: uart0-rts {
				rockchip,pins =
					<2 19 RK_FUNC_1 &pcfg_pull_none>;
			};
		};

		uart1 {
			uart1_xfer: uart1-xfer {
				rockchip,pins =
					<3 12 RK_FUNC_2 &pcfg_pull_up>,
					<3 13 RK_FUNC_2 &pcfg_pull_none>;
			};
		};

		uart2a {
			uart2a_xfer: uart2a-xfer {
				rockchip,pins =
					<4 8 RK_FUNC_2 &pcfg_pull_up>,
					<4 9 RK_FUNC_2 &pcfg_pull_none>;
			};
		};

		uart2b {
			uart2b_xfer: uart2b-xfer {
				rockchip,pins =
					<4 16 RK_FUNC_2 &pcfg_pull_up>,
					<4 17 RK_FUNC_2 &pcfg_pull_none>;
			};
		};

		uart2c {
			uart2c_xfer: uart2c-xfer {
				rockchip,pins =
					<4 19 RK_FUNC_1 &pcfg_pull_up>,
					<4 20 RK_FUNC_1 &pcfg_pull_none>;
			};
		};

		uart3 {
			uart3_xfer: uart3-xfer {
				rockchip,pins =
					<3 14 RK_FUNC_2 &pcfg_pull_up>,
					<3 15 RK_FUNC_2 &pcfg_pull_none>;
			};

			uart3_cts: uart3-cts {
				rockchip,pins =
					<3 16 RK_FUNC_2 &pcfg_pull_none>;
			};

			uart3_rts: uart3-rts {
				rockchip,pins =
					<3 17 RK_FUNC_2 &pcfg_pull_none>;
			};
		};

		uart4 {
			uart4_xfer: uart4-xfer {
				rockchip,pins =
					<1 7 RK_FUNC_1 &pcfg_pull_up>,
					<1 8 RK_FUNC_1 &pcfg_pull_none>;
			};
		};

        }

使能 rk3399-evb.dtsi


        wireless-bluetooth {
                uart0_gpios: uart0-gpios {
                        rockchip,pins = <2 19 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };

        wireless-bluetooth {
                compatible = "bluetooth-platdata";
                clocks = <&rk808 1>;
                clock-names = "ext_clock";
                //wifi-bt-power-toggle;
                uart_rts_gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; /* GPIO2_C3 */
                pinctrl-names = "default", "rts_gpio";
                pinctrl-0 = <&uart0_rts>;
                pinctrl-1 = <&uart0_gpios>;
                //BT,power_gpio  = <&gpio3 19 GPIO_ACTIVE_HIGH>; /* GPIOx_xx */
                BT,reset_gpio    = <&gpio0 9 GPIO_ACTIVE_HIGH>; /* GPIO0_B1 */
                BT,wake_gpio     = <&gpio2 27 GPIO_ACTIVE_HIGH>; /* GPIO2_D3 BT_WAKE */
                BT,wake_host_irq = <&gpio0 4 GPIO_ACTIVE_HIGH>; /* GPIO0_A4 */
                status = "okay";
        };

&uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_xfer &uart0_cts>;
        status = "okay";
};

&uart2 {
        status = "okay";
};

&uart4{
        status = "okay";
};

串口调试 rk3399-android.dtsi

该节点驱动加载后会注册/dev/ttyFIQ0 设备,需要注意的是 rockchip,serial-id 即便改了,注册的也是ttyFIQ0。


        chosen {
                bootargs = "earlycon=uart8250,mmio32,0xff1a0000 swiotlb=1 coherent_pool=1m";  /*0xff1a0000 是 uart2 的物理基地址,不同的串口基地址不一样*/
        };

        fiq_debugger: fiq-debugger {
                compatible = "rockchip,fiq-debugger";
                rockchip,serial-id = <2>;        /* 设置串口id,如果想换不同的串口就改这个ID*/
                rockchip,wake-irq = <0>;
                rockchip,irq-mode-enable = <0>;  /* If enable uart uses irq instead of fiq */
                rockchip,baudrate = <1500000>;  /* Only 115200 and 1500000 */
                pinctrl-names = "default";
                pinctrl-0 = <&uart2c_xfer>;  /*换了不同的串口后,需要配置iomux*/
                interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH 0>;
        };

&uart2 {
        status = "disabled";
};

启动日志


[    0.000000] bootconsole [uart0] enabled
[    0.000000] Kernel command line: earlycon=uart8250,mmio32,0xff1a0000 swiotlb=1 coherent_pool=1m console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00002000@0x00006000(misc),0x00008000@0x00008000(resource),0x0000C000@0x00010000(kernel),0x00010000@0x0001C000(boot),0x00020000@0x0002C000(recovery),0x00038000@0x0004C000(backup),0x00040000@0x00084000(cache),0x00300000@0x000C4000(system),0x00008000@0x003C4000(metadata),0x00000040@0x003CC000(verity_mode),0x00002000@0x003CC040(reserved),0x00000400@0x003CE040(frp),0x00004000@0x004EE000(oem),-@0x003CE440(userdata) storagemedia=emmc androidboot.oem_unlocked=0 uboot_logo=0x02000000@0x7dc00000 loader.timestamp=2022-09-14_14:31:14 SecureBootCheckOk=0
[    0.177845] fiq debugger fiq mode enabled
[    0.178491] console [ttyFIQ0] enabled
[    0.179184] bootconsole [uart0] disabled
[    0.179752] Registered fiq debugger ttyFIQ0
[    0.389369] ff180000.serial: ttyS0 at MMIO 0xff180000 (irq = 36, base_baud = 1500000) is a 16550A
[    0.389831] ff370000.serial: ttyS4 at MMIO 0xff370000 (irq = 38, base_baud = 1500000) is a 16550A
[    2.668311] usbserial: USB Serial support registered for ch341-uart
[    3.419270] ch341 1-1.2:1.0: ch341-uart converter detected
[    3.421184] usb 1-1.2: ch341-uart converter now attached to ttyUSB0
[    3.432463] ch341 2-1.2:1.0: ch341-uart converter detected
[    3.434389] usb 2-1.2: ch341-uart converter now attached to ttyUSB1