在计算机系统中,串口是“古老”的通信方式,和它同时代的“并口”通信方式已经消失了。但它仍然顽强的存活着,主要原因是在开发和调试底层软件时还经常用到串口。
正因为有这样的需求,幽兰代码本是支持串口的,而且有两种方式。第一种是主板上接头,需要打开后盖。第二种方式是通过SD卡接口,不需要打开后盖,非常方便,得到很多兰友的好评。
比幽兰更早的GDK8也支持串口,但是要打开后盖。不够方便,因为此,这几天在准备GDK8的新版本镜像时,我根据GDK8用户的意见提了一个需求,把幽兰的SD串口做法应用到GDK8上。
格蠹的小伙伴Jack接到这个需求,这两天在着手实现。
Jack是格蠹的老程序员了,有比较丰富的底层开发经验。为了方便写代码和试验,他轻车熟路地选择用“刘姥姥”驱动做原型。
GDK8使用的是RK3328 SoC。与幽兰使用的RK3588 SoC相似,3328的串口信号也是与SD卡信号复用的,而且复用的都是2号串口,即UART2。
不同的是,3328的UART2有两种连接模式,分别称为UART2m0和UART2m1。下面这张表来自RK3328 TRM的第17章接口描述一节。
对于上表中的m缩写,手册中没有给出任何解释,很让软件工程师困惑。
虽然m的含义不是很明确,但因为m0接口是与SD信号复用的,所以应该按m0方式来设置寄存器。Jack这样修改刘姥姥驱动,把改寄存器的想法转化为代码。
临近中饭时,Jack报告第一个坏消息,“寄存器不能写”。
考虑到这个任务有难度和重要性,我走过去和他一起看寄存器的描述。
首先,RK的SPEC中有时也有明显的错误,比如上面截图中的GRF_COM_MUX应该是GRF_CON_MUX,CON是Control的缩写,MUX是复用的缩写。
RK的很多寄存器都是一个套路:高16位是掩码,低16位负责具体功能,高位为1时,低位的值才有效。但这个规则在上表中解释的很啰嗦。Jack说话很少,交流一番,他可能是被解释中的“when bit16=0, bit 0 cannot be written by software”迷惑了。也可能是被冗长的spec搞晕头了。
午饭后,我看Jack的代码,发现一个明显的问题。
我们要选择m0模式,按照第一张截图中表格下面的描述,需要把GRF_CON_MUX[0]写为0。写寄存器时应该写0x10000。但可能是被SPEC中的真真假假搞晕,Jack的代码里把本来想写的0x30000写成了30000。16进制变成10进制了。
纠正了这个bug后,寄存器写成功了。GRF_CON_IOMUX[0]位成功被设置为0。
这个比特位的设置之前为1,说明是工作在m1模式。我特意与GDK8的硬件工程师确认,GDK8主板上的串口使用的正是UART2m1。
但寄存器写成功的喜悦还没持续几分钟,Jack报告了第二个坏消息:接了SD串口转接头后,主机端还是收不到串口数据。
我说是不是软件写的设备文件不对,Jack说他写了个脚本,把dev下的所有串口设备都试过了。
对于通信问题来说,收不到数据是最让人头痛的。刚好今天早上,我顺手把调试WIFI驱动的几张截图发到WOA技术群,引来多位同行发表感想,普遍觉得涉及到通信的问题有很多坑。
还有真实的案例。
看到Jack前进受挫,我决定放下手头的其它事情,进来助力。
一方面,先汇总手头的各种信息,做些归纳和总结,夯牢基础。查看RK3328硬件设计手册,3328的最初开发板EVB也是使用UART2m1方式来做调试口。根据硬件工程师的回复,GDK8是沿用了EVB的设计。GDK8主板背面的TX、RX、GND三个信号是便是UART2m1实物。
其实,这个设计也延续到幽兰使用的RK3588,也是使用UART2做为默认的调试口。
另一方面,我联系做硬件的Intel老同事,请他帮忙解释SPEC中m缩写的含义。
术业有专攻,硬件工程师果然不一样,明确给出了m缩写的含义。
清楚了m缩写的含以后,我彻底明白了SPEC的意思,脑海中浮现出一张比较清晰的硬件路线图。
有了这个路线图之后,我更加坚定了信念,认为这个方向是可以走的通的。为了避免单一试验的局限性,我决定增大投入,安排小伙伴Bob也投入战斗,搭建环境,编译新代码。
但还没有等到Bob把新环境搭建好,Jack发出好消息:
上面这条信息是从GDK8上通过SD转接头发送到主机端的,也就是说,是以新规划的m0路线传递的。这条消息代表新的串口通道打通了!
我询问Jack哪里做了改动,原来只是改了波特率。因为以前使用m1方式调试时,dts里配置的波特率是115200,所以下午试验时误以为还是这个值,但其实根据UART_DLL和UART_DLH寄存器的值计算,应该是1.5M。
dlh=1,uart_clk_sel=2’b10-24mhz,波特率=24m/(1*16)=1.5
经过一天的努力,期待许久的串口新通道终于打通了。回顾整个过程,其实主要的改动就是配置寄存器。
一件事情,做成功了之后,再回头看就觉得没什么复杂,但是在没有做成之前,则充满了困惑。对于这个问题,有很多可能失败和放弃。虽然失败也是一种选项,可它是无法和成功相比的。
GDK8是2021年发布的,在硬件高速度发展的今天,有些人可能觉得它有些老了,但其实,对于很多用户来说,GDK8具有很多不可多得的优点,比如:
- 非常稳定地支持JTAG调试。
- 超低功耗,开机半个月也用不到一度电,所以有些用户从不关机。
- 积累了大量文档、代码以及开发经验,比如今天这样的踩坑实践。
- 小巧玲珑,节约空间。
今天,它又多了一个优点,可以非常方便的通过SD插槽连接串口。手里有GDK8的小伙伴可以亲自体验一下!对于没有GDK8的朋友,有一种特殊的方式可以得到GDK8 + 挥码枪伴侣,那就是参加格蠹的调试研习班,人手一套。研习班的上海站正在招生之中。
(写文章很辛苦,恳请各位读者点击“在看”,也欢迎转发)
*************************************************
正心诚意,格物致知,以人文情怀审视软件,以软件技术改变人生
扫描下方二维码或者在微信中搜索“盛格塾”小程序,可以文章和有声读物
也欢迎关注格友公众号