• 正文
  • 相關推薦
申請入駐 產業(yè)圖譜

瑞芯微|rk3568 uart快速上手

01/10 15:30
808
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

一、調試環(huán)境

平臺: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字節(jié)的?FIFO,用于接收和傳輸??
-?支持流控
-?支持速率?115.2Kbps,?460.8Kbps,?921.6Kbps,?1.5Mbps,?3Mbps,?4Mbps
-?支持5、6、7、8?bits數據位。
-?支持1、1.5、2?bits停止位。
-?支持奇校驗和偶校驗。
-?支持基于中斷/DMA?模式

2. UART控制器架構

APB INTERFACE
處理器通過APB接口訪問UART的數據,做控制,以及狀態(tài)信息。
UART支持8、16和32位的APB數據總線寬度。

Register block
負責UART的主要功能,包括控制、狀態(tài)和中斷產生。

Modem Synchronization block
同步modem輸入信號.

FIFO block
負責FIFO控制和存儲或向發(fā)送信號以控制外部RAM。

Baud Clock Generator
收發(fā)比特率設置。

Serial Transmitter
數據發(fā)送模塊。

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;
......
@kernelarcharm64bootdtsrockchiprk3568.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 dmapinctrl-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 1status:
    • "okay" 打開
    "disabled" 關閉

引腳說明在下面定義:
以UART6為例:

@kernelarcharm64bootdtsrockchiprk3568-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. 使用串口喚醒系統(tǒng)

串口喚醒系統(tǒng)功能是在系統(tǒng)待機時串口保持打開,并且把串口中斷設置為喚醒源。使用時需要在dts中增
加以下參數:

?&uart1?{
??wakeup-source;
?};

注意,串口喚醒系統(tǒng)需要同時修改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會有沖突:

@kernelarcharm64bootdtsrockchiprk3568-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使用到的引腳如下:

請?zhí)砑訄D片描述

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的收發(fā)引腳,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

五、編寫自己的測試程序

下面是一口君自己編寫的測試程序,可以實現簡單的數據收發(fā),

#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!nr");
?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:%sn",buf);
?close(fd1);
?return?0;
}

工具ts_uart.uart s獲取,公眾號【一口Linux】后臺回復:rxw

瑞芯微電子

瑞芯微電子

瑞芯微專注于移動互聯網、數字多媒體芯片設計,是專業(yè)的個人移動信息終端SOC解決方案供應商。瑞芯微在移動互聯網領域有多個較完整的自主創(chuàng)新的知識產權群,為中國電子業(yè)發(fā)展做出積極努力。目前產品涵蓋Android平板電腦、Android電視機頂盒(智能電視)、電子書、WIFI/藍牙音頻解決方案等。

瑞芯微專注于移動互聯網、數字多媒體芯片設計,是專業(yè)的個人移動信息終端SOC解決方案供應商。瑞芯微在移動互聯網領域有多個較完整的自主創(chuàng)新的知識產權群,為中國電子業(yè)發(fā)展做出積極努力。目前產品涵蓋Android平板電腦、Android電視機頂盒(智能電視)、電子書、WIFI/藍牙音頻解決方案等。收起

查看更多

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

公眾號『一口Linux』號主彭老師,擁有15年嵌入式開發(fā)經驗和培訓經驗。曾任職ZTE,某研究所,華清遠見教學總監(jiān)。擁有多篇網絡協(xié)議相關專利和軟件著作。精通計算機網絡、Linux系統(tǒng)編程、ARM、Linux驅動、龍芯、物聯網。原創(chuàng)內容基本從實際項目出發(fā),保持原理+實踐風格,適合Linux驅動新手入門和技術進階。