世界观察:RK3588-UART
前言
专栏总目录本文主要讲解如何关于RK3588开发板UART的使用和调试方法,包括UART作为普通串口和控制台两种不同使用场景一. 功能特点
RockchipUART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准,完整模块支持以下功能:
(相关资料图)
支持5、6、7、8 bits数据位。支持1、1.5、2 bits停止位。支持奇校验和偶校验,不支持mark校验和space校验。支持接收FIFO和发送FIFO,一般为32字节或者64字节。支持最高4M波特率,实际支持波特率需要芯片时钟分频策略配合。支持中断传输模式和DMA传输模式。 支持硬件自动流控,RTS+CTS。二、代码位置
在Linuxkernel 中,使用8250串口通用驱动,以下为主要驱动文件:
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驱动
SDK中提供的UART默认配置已经使用了8250驱动我们就不需要修改
三、硬件原理图
串口功能的硬件上比较简单,这是只附上调试串口的原理图
四、设备树配置
rk平台的设备树修改路径都是在kernel\\arch\\arm64\\boot\\dts\\rockchip下面,具体哪个文件根据对应开发板来决定,通常描述设备硬件配置在rkxxxx.dtsi中,比如在rk3588s.dtsi中:
uart2: serial@feb50000 {compatible = "rockchip,rk3588-uart", "snps,dw-apb-uart";reg = < 0x0 0xfeb50000 0x0 0x100 >;interrupts = < GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH >;clocks = < &cru SCLK_UART2 >, < &cru PCLK_UART2 >;clock-names = "baudclk", "apb_pclk";reg-shift = < 2 >;reg-io-width = < 4 >;dmas = < &dmac0 10 >, < &dmac0 11 >;pinctrl-names = "default";pinctrl-0 = < &uart2m1_xfer >;status = "disabled";};
4.1作为普通串口
假入我们想使用w3开发板上40PIN上的uart7
我们在dts可以使用如下配置打开
&uart7 {status = "okay";pinctrl-names = "default";pinctrl-0 = < &uart7m1_xfer >;};
4.2作为调试串口
Rockchip UART作为控制台,使用fiq_debugger流程。
在dts中fiq_debugger节点配置如下。由于fiq_debugger和普通串口互斥,在使能fiq_debugger节点后必须禁用对应的普通串口uart节点。
chosen: chosen {bootargs = "earlycon=uart8250,mmio32,0xfe660000 console=ttyFIQ0";};fiq-debugger {compatible = "rockchip,fiq-debugger";rockchip,serial-id = < 2 >;rockchip,wake-irq = < 0 >;/* If enable uart uses irq insteadof fiq */rockchip,irq-mode-enable = < 1 >;rockchip,baudrate = < 1500000 >; /* Only 115200 and 1500000 */interrupts = < GIC_SPI 252 IRQ_TYPE_LEVEL_LOW >;pinctrl-names = "default";pinctrl-0 = < &uart2m0_xfer >;status = "okay";};&uart2 {status = "disabled";};
rockchip,serial-id:使用的UART编号。修改serial-id到不同UART,fiq_debugger设备也会注册成ttyFIQ0设备。 rockchip,irq-mode-enable:配置为1使用irq中断,配置为0使用fiq中断。interrupts:配置的辅助中断,保持默认即可。pinctrl-0:使用的串口引脚rockchip,baudrate:波特率配置五、串口相关问题
5.1设备注册
普通串口设备将会根据dts中的aliase来对串口进行编号,对应注册成ttySx设备。注册的节点为/dev/ttyS4,命名规则是通过dts中的aliases来的。
aliases {serial0 = &uart0;serial1 = &uart1;serial2 = &uart2;serial3 = &uart3;}
对应uart0注册为ttyS0,uart0注册为ttyS1,如果需要把uart3注册成ttyS1,可以进行以下修改
serial1 = &uart3; serial3 = &uart1;
5.2控制台打印相关
Rockchip UART打印通常包括DDR阶段、Miniloader阶段、TF-A (Trusted Firmware-A)阶段、OP-TEE阶段、Uboot阶段和Kernel阶段,我们平时主要关注的是uboot阶段和kernel阶段的打印,在这两个阶段我们可以尝试关闭所有打印或切换所有打印到其他UART,RK平台默认的调试串口是uart2_m0这一组引脚,假如现在我将打印换成其他串口,可以尝试以下做法。
5.2.1DDR Loader修改方法
DDR Loader中关闭或切换打印,需要修改DDR Loader中的UART打印配置,修改文件rkbin/tools/ddrbin_param.txt中的以下参数:
uart id= # UART控制器id,配置为0xf为关闭打印
uart iomux= # 复用的IOMUX引脚 uart
baudrate= # 115200 or 1500000
修改完成后,使用以下命令重新生成ddr.bin固件。
./ddrbin_tool ddrbin_param.txt rk3588_ddr_lp4_2112MHz_lp5_2736MHz_v1.09.bin
5.2.2Uboot修改方法
Uboot中关闭打印,需要在menuconfig中,打开配CONFIG_DISABLE_CONSOLE,保存到.config文件
Uboot中切换打印,由传参机制决定,不需要进行额外修改。uboot解析传参机制相关代码在arch/arm/mach-rockchip/board.c的board_init_f_init_serial()函数中。
5.2.3kernel修改方法
去掉打印需要在menuconfig中,关闭配置CONFIG_SERIAL_8250_CONSOLE。
Device Drivers --->
Character devices --->
Serial drivers --->
[ ]Console on 8250/16550 and compatible serial port
在dts配置中找到类似以下内容,并去掉UART基地址和console相关配置参数
chosen: chosen {bootargs = "earlycon=uart8250,mmio32,0xfeb50000 console=ttyFIQ0 irqchip.gicv3_pseudo_nmi=0 root=PARTUUID=614e0000-0000 rw rootwait";};
将0xfeb50000 console=ttyFIQ0 去掉,然后找到fiq-debugger节点,修改serial-id为0xffffffff,去掉UART引脚复用相关配置。注意,需要保持fiqdebugger节点使能,保持fiq-debugger流程系统才能正常启动
fiq_debugger: fiq-debugger {compatible = "rockchip,fiq-debugger";rockchip,serial-id = < 0xffffffff >;rockchip,wake-irq = < 0 >;/* If enable uart uses irq instead of fiq */rockchip,irq-mode-enable = < 1 >;rockchip,baudrate = < 1500000 >; /* Only 115200 and 1500000 */interrupts = < GIC_SPI 423 IRQ_TYPE_LEVEL_LOW >;status = "okay";};
切换打印串口例如将Kernel打印从UART2切换到UART3,在dts配置中找到类似以下内容,将UART基地址由UART2改为UART3.
bootargs = "earlycon=uart8250,mmio32,0xfe670000 console=ttyFIQ0";
0xfe670000是UART3基地址,然后找到fiq-debugger节点,修改serial-id为3,修改UART3引脚复用配置pinctrl-0 = <&uart3m0_xfer>。注意,同时需要将切换为打印串口的UART3作为普通串口的节点禁用。
六、串口测试
在开发板上跑一套应用程序,可以发送数据,可以接收数据,测试方法可以短接TX_RX
#include < stdio.h >#include < stdlib.h >#include < errno.h >#include < unistd.h >#include < fcntl.h >#include < string.h >#include < termio.h >#include < time.h >#include < pthread.h >int read_data(int fd, void *buf, int len);int write_data(int fd, void *buf, int len);int setup_port(int fd, int baud, int databits, int parity, int stopbits);void print_usage(char *program_name);pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER;int data_available = 0;void *read_thread(void *arg) { int fd = *(int *)arg; char buffer[1024]; // 存储读取的数据 while (1) { int bytes_read = read_data(fd, buffer, sizeof(buffer)); if (bytes_read > 0) { printf("Read Thread: Read %d bytes: %s\\n", bytes_read, buffer); } else { // 处理读取错误或设备关闭的情况 break; } } pthread_exit(NULL);}void *write_thread(void *arg) { int fd = *(int *)arg;char input[1024]; // 存储用户输入的数据 while (1) { printf("Enter data to write (or "q" to quit): "); fgets(input, sizeof(input), stdin); if (strcmp(input, "q\\n") == 0 || strcmp(input, "Q\\n") == 0) { // 用户输入 "q" 或 "Q",退出循环 break; } int len = strlen(input); int bytes_written = write_data(fd, input, len); if (bytes_written > 0) { printf("Write Thread: Wrote %d bytes: %s\\n", bytes_written, input); } } pthread_exit(NULL);}int main(int argc, char *argv[]) //./a.out /dev/ttyS4 115200 8 0 1{ int fd; int baud; int len; int count; int i; int databits; int stopbits; int parity; if (argc != 6) { print_usage(argv[0]); return 1; } baud = atoi(argv[2]); if ((baud < 0) || (baud > 921600)) { fprintf(stderr, "Invalid baudrate!\\n"); return 1; } databits = atoi(argv[3]); if ((databits < 5) || (databits > 8)) { fprintf(stderr, "Invalid databits!\\n"); return 1; } parity = atoi(argv[4]); if ((parity < 0) || (parity > 2)) { fprintf(stderr, "Invalid parity!\\n"); return 1; } stopbits = atoi(argv[5]); if ((stopbits < 1) || (stopbits > 2)) { fprintf(stderr, "Invalid stopbits!\\n"); return 1; } fd = open(argv[1], O_RDWR, 0); if (fd < 0) { fprintf(stderr, "open < %s > error %s\\n", argv[1], strerror(errno)); return 1; } if (setup_port(fd, baud, databits, parity, stopbits)) { fprintf(stderr, "setup_port error %s\\n", strerror(errno)); close(fd); return 1; }pthread_t read_tid, write_tid; int ret; // 创建读取线程 ret = pthread_create(&read_tid, NULL, read_thread, &fd); if (ret != 0) { fprintf(stderr, "Failed to create read thread\\n"); return 1; } // 创建写入线程 ret = pthread_create(&write_tid, NULL, write_thread, &fd); if (ret != 0) { fprintf(stderr, "Failed to create write thread\\n"); return 1; } // 等待读取线程和写入线程结束 pthread_join(read_tid, NULL); pthread_join(write_tid, NULL); close(fd); return 0;}static int baudflag_arr[] = { B921600, B460800, B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1800, B1200, B600, B300, B150, B110, B75, B50};static int speed_arr[] = { 921600, 460800, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300, 150, 110, 75, 50};int speed_to_flag(int speed){ int i; for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) { if (speed == speed_arr[i]) { return baudflag_arr[i]; } } fprintf(stderr, "Unsupported baudrate, use 9600 instead!\\n"); return B9600;}static struct termio oterm_attr;int setup_port(int fd, int baud, int databits, int parity, int stopbits){ struct termio term_attr; if (ioctl(fd, TCGETA, &term_attr) < 0) { return -1; } memcpy(&oterm_attr, &term_attr, sizeof(struct termio)); term_attr.c_iflag &= ~(INLCR | IGNCR | ICRNL | ISTRIP); term_attr.c_oflag &= ~(OPOST | ONLCR | OCRNL); term_attr.c_lflag &= ~(ISIG | ECHO | ICANON | NOFLSH); term_attr.c_cflag &= ~CBAUD; term_attr.c_cflag |= CREAD | speed_to_flag(baud); term_attr.c_cflag &= ~(CSIZE); switch (databits) { case 5: term_attr.c_cflag |= CS5; break; case 6: term_attr.c_cflag |= CS6; break; case 7: term_attr.c_cflag |= CS7; break; case 8: default: term_attr.c_cflag |= CS8; break; } switch (parity) { case 1: term_attr.c_cflag |= (PARENB | PARODD); break; case 2: term_attr.c_cflag |= PARENB; term_attr.c_cflag &= ~(PARODD); break; case 0: default: term_attr.c_cflag &= ~(PARENB); break; } switch (stopbits) { case 2: term_attr.c_cflag |= CSTOPB; break; case 1: default: term_attr.c_cflag &= ~CSTOPB; break; } term_attr.c_cc[VMIN] = 1; term_attr.c_cc[VTIME] = 0; if (ioctl(fd, TCSETAW, &term_attr) < 0) { return -1; } if (ioctl(fd, TCFLSH, 2) < 0) { return -1; } return 0;} int read_data(int fd, void *buf, int len){ int count; int ret; ret = 0; count = 0; //while (len > 0) { ret = read(fd, (char*)buf + count, len); if (ret < 1) { fprintf(stderr, "Read error %s\\n", strerror(errno)); //break; } count += ret; len = len - ret; //} *((char*)buf + count) = 0; return count;} int write_data(int fd, void *buf, int len){ int count; int ret; ret = 0; count = 0; while (len > 0) { ret = write(fd, (char*)buf + count, len); if (ret < 1) { fprintf(stderr, "Write error %s\\n", strerror(errno)); break; } count += ret; len = len - ret; } return count;}void print_usage(char *program_name){ fprintf(stderr, "*************************************\\n" " A Simple Serial Port Test Utility\\n" "*************************************\\n\\n" "Usage:\\n %s < device > < baud > < databits > < parity > < stopbits > \\n" " databits: 5, 6, 7, 8\\n" " parity: 0(None), 1(Odd), 2(Even)\\n" " stopbits: 1, 2\\n" "Example:\\n %s /dev/ttyS4 115200 8 0 1\\n\\n", program_name, program_name );}
运行效果如下:
审核编辑:汤梓红
标签:
- 世界观察:RK3588-UART
- 天天快消息!旱碱麦成“名片”迎来丰收 盐碱地特色农业开出“增收花”
- 关于铁路计次票、定期票 如何购买使用
- 全球新动态:刘奕君:逆反大叔的坚韧
- 天天要闻:超好听的qq分组符号(qq分组名称唯美带符号)
- 八年级上册语文课件ppt七彩课堂(八年级上册语文课件ppt) 每日讯息
- 中国药品批准文号查询(国家药品批准文号查询)
- lh是什么激素(fsh是什么激素) 今日播报
- 环球信息:aw是什么意思(awd是什么意思)
- 员工培训计划实施方案(员工培训计划要怎么写)_热推荐
- 徐英浩是什么担当_徐英浩
- 7744小游戏盒_7743小游戏
- 电锤冲击钻电钻三用哪个品牌好_冲击电钻什么牌子好 天天播报
- 每日讯息!1.85英雄合击版哪两个组合厉害_1 80英雄合击版本
- 环球今日讯!江苏省教育考试院、省反诈中心联合发布涉高考诈骗重要提醒
- 天天实时:非遗融入生活 文化自信自强
- 今日热门!繁花嫩叶的意思在《春》(繁花嫩叶的意思)
- 当前信息:商户poss机刷卡手续费(poss机刷卡手续是多少)
- 全球看点:查手机号码吉凶(查手机)
- 怎样按姓氏笔画排序WPS(怎样按姓氏笔画排序)
- 中国移动招标与采购网登陆不了(中国移动招标与采购网) 每日速读
- 天天动态:陈美玲歌曲原野牧歌(陈美玲经典歌曲)
- 青山有幸埋忠骨白铁无辜铸佞臣的意思是什么_青山有幸埋忠骨白铁无辜铸佞臣的意思
- 孙俪电影电视剧大全_孙俪电影 世界观天下
- become是系动词吗_become|每日播报
- 母亲节送妈妈什么花好_父亲节送什么花好
- loud怎么读_loud-头条
- 中国女人和欧洲人结婚会疼吗_欧洲女性和中国女性外阴有区别吗-环球头条
- 瑞恩·雷诺兹要拍冒险动作片《Mayday》 《龙与地下城》导演操刀 环球聚看点
- 每日简讯:《透明侠侣》转运曲《好事会发生》,史策王皓出租车甜蜜穿越透明浪漫宇宙
- 2023世界动力电池大会在宜宾开幕 全球球精选
- 爵士鼓基础教程书籍_爵士鼓入门教程 2009年中国戏剧出版社出版的图书
- 当前头条:红烧甲鱼的做法 甲鱼的做法
- 艾炙多久能改善身体_艾灸是靠烟还是靠热 每日短讯
- 当前通讯!失落的星球_关于失落的星球的介绍
- 姓氏笔画排序规则(姓氏笔画排序方法) 环球消息
- 零声母分几类(零声母)
- dnf名字特殊符号打法比心(dnf名字特殊符号)
- 萨克斯指法表大全图片(萨克斯指法表)
- 清水鼻涕流不停什么原因(清水鼻涕)
- AMD超威卓越平台全面登陆国内式机市场:为游戏玩家和创作者提供卓越解决方案
- 和稀泥不会解决基层的矛盾,只会使矛盾积累积累再积累
- 动态:本人是70年代人,我可以非常肯定的告诉你:现在没有什么食物没有问题
- 为什么惩治腐败不能用重典?
- 【世界时快讯】提高科学素养 “深海发现之旅”在国家海博馆启动
- RK3588-CAN总线|世界时快讯
- 天天热资讯!严正化不敢看《车贞淑医生》首播,被夸后中断录影爆哭半小时
- 萨克斯指法表大全图片(萨克斯指法表)
- 地包天自我矫正方法(地包天矫正方法) 当前热文
- 在平面直角坐标系中 已知点A 负根号5(在平面直角坐标系中 已知点a)
- 当前头条:高质量发展调研行 | 在智慧港口见证大湾区经济活力——广州南沙港走访一线见闻
- 证监会就公募基金投顾业务管理规定公开征求意见
- 世界速递!中阿两国央行续签双边本币互换协议 有效期三年
- 千足虫是什么
- 想告别黑眼圈?试试红光眼部美容仪!
- 想自己做补水面膜吗? 当前观点
- 肌肤暗黄是哪六大元凶?有什么简单九招可以去暗黄还美白肌肤?
- 环球动态:揭秘!分分彩一星技巧,这位专家传授的实用心得!
- 环球微动态丨腌鱼怎么做好吃_燕鱼怎么做好吃
- 黑衣人1网盘(黑衣人百度云链接)
- 监控怎么在电脑上看
- 氧化铝的用途是什么(氧化铝的用途)
- 滚动:西安高新区2023“文化和自然遗产日”主题活动启动
- 国铁:今起12306试行在线选铺服务 想要下铺以后要拼手速啦!
- 白鹅潭万象城奠基开工 广州三大地标综合体两个已官宣
- 图灵奖得主杨立昆:AI的逻辑推理和规划能力有限,会犯事实错误和逻辑错误_每日精选
- “这些空姐,立即停飞!”网友怒了
- 崩坏星穹铁道漫藏诲盗其一攻略 漫藏诲盗其一图文过关一览[多图]
- 卖果丹皮偶遇淄博八大局书画大师出摊获赠招牌 网友:招牌最值钱
- 天天时讯:延安市人民医院顺利完成2023年医师资格实践技能陕北片区考试任务
- 西安高新区2023“文化和自然遗产日”主题活动启动|环球新消息
- 第12届金交会开幕,现场签约总金额超3500亿元
- 天天新消息丨莫扎特的一句话(关于莫扎特的话例如说他天真)
- 天天观焦点:全自动马桶水箱盖怎么打开(马桶水箱盖怎么打开)
- 讯息:厦门有什么好吃的(厦门有什么特色小吃)
- 北京人遗址传说(北京人遗址) 环球快消息
- 重点聚焦!最短的季节是什么(最短的季节)
- 福建多地为何纷纷成立这一机构?
- 以文塑旅 以旅彰文 融合发展 广东文旅市场强劲复苏
- 每日信息:聚焦深圳文博会 | 一本书演绎的奏鸣曲
- 速看:聚焦深圳文博会 | 中外游客在云南展区体验“有一种叫云南的生活”
- 夜幕下,一个群体带动城市消费新热潮
- 聚焦:昔日荒山变为幸福“金山” 桃园变成农民增收“致富园”
- 安慕希多少钱一箱10瓶装 安慕希多少钱一箱 天天讯息
- 大仲马的代表作之一 大仲马的代表作
- 漂洋过海来看你歌曲的故事 漂洋过海来看你歌曲 热讯
- 天天精选!说说自己作文300字作文 说说自己作文300字
- 文化的概念包括什么(文化的概念和定义) 环球快报
- 诗意盎然的意思(盎然的意思)-世界快报
- 热门:广汽埃安副总经理:原来车厂不是为电池厂打工 而是为材料厂打工且还是打长工
- 报考这所学院,让你“玩转”智慧城市
- 今日热文:梅西,到北京了!
- 环球微头条丨旱碱麦成“名片”迎来丰收 盐碱地特色农业开出“增收花”
- 全球今亮点!梅西小字一签,贝克汉姆小赚40倍
- 这家公司董事长、独董突然辞职!近年来股权不断变更 “牛散”身影频现 今日看点
- 全球热资讯!《有利的诈欺》绿叶抢眼,尹博再次伙拍金东旭斗戏
- 热门看点:刘亚仁涉嫌使用毒品种类追加, 新发现2种一共七种
- 75部影片已定档,暑期档票房有望冲击150亿
- 瑞恩·雷诺兹要拍冒险动作片《Mayday》 《龙与地下城》导演操刀
- 四川一中学不让学生带书离校售卖,“校内3毛/斤,校外6毛/斤”,县教育局回应