最近开新项目用到新唐的nuc972平台,由于硬件工程师为了方便布线,所以将原本用于调试口的uart0改成了485,需要将uart1更改为调试串口。最初从nuc972开发文档开始看,看uboot配置和修改的地方,最初查看uboot下include/configs/nuc970_evb.h文件,里面有不少宏,这些宏是用于配置相关的硬件接口,如果宏打开的话,相应的驱动文件可以被编译进uboot中,可以通过修改部分宏实现数据更改,但串口这里只有一个CONFIG_NUC970_CONSOLE,搜索这个宏之后,发现了这个宏控制着nuc970串口驱动程序,通过此宏可以将串口的驱动编译到uboot中去。
那想要更改uboot调试串口,肯定就这个串口驱动文件相关,打开drivers/serial/serial_nuc970.c文件,可以看到串口初始化的地方使用的就是uart0的接口信息
于是我将uart0相关的寄存器更改为uart1,其实也就是下面这一行
//#define UART0_BA 0xB8000000 /* UART0 Control (High-Speed UART) */
更改为:
#define UART0_BA 0xB8000100 /* UART1 Control (High-Speed UART) */
当然这个寄存器地址是从手册上面找到的,修改完毕之后,保存、编译、烧录,然后把串口查到uart1上面,复位后,发现uart1口啥东西都没用,很显然只改这个地方根本没用。
下面这个地方应该也要改成uart1的才对,但是怎么改,还得去查手册
uart0位于PE.0和PE.1口,而uart1位于PE.2和PE.3口,在手册中找到GPIOE口的复用功能配置
可以看到每个口不光可以做串口,还可以配置为普通的GPIO口,蓝色部分是uart0口的的发送和接收引脚,红色部分是uart1口的发送和接收,原来程序里面是将uart0口配置成txd和rxd,现在我们需要将uart1口PE.2和PE.3配置成串口。
0x1001 = 9
通过__raw_readl(REG_MFP_GPE_L) & 0xffff00ff)先读取到PE.2和PE.3的配置状态,然后&0xFFFF00FF将PE.2和PE.3两个口的配置清理,然后再|0x9900,就将这2个口配置成串口输入和输出,然后通过外面的__raw_writel()函数将新的数据写进寄存器。
__raw_writel((__raw_readl(REG_MFP_GPE_L) & 0xffff00ff) | 0x9900, REG_MFP_GPE_L); // UART1 multi-function
这样uart1口就被配置成了串口
保存后编译烧录,上电后发现uart1口还是没有输出,估计还是哪里不对,原来的uart0能工作估计其他地方还有配置,继续找
后面在board/nuvoton/nuc970.c文件中发现了对uart0进行了时钟配置操作
刚才上面我只是把uart1管脚复用功能配置成了串口模式,但是还没给uart1配置时钟,所以uart1没办法工作,只能再看芯片手册,根据上面的PCLKEN0去文档里面搜索,终于找到了下面这个图
每个uart都有单独的时钟,看来需要配置uart1的时钟,再往下翻,找到了这个图
只要将第17位设置为1就可以开启uart1的时钟了,而原来程序里面配置的uart0时用的时0x10000
而0x10000的第bit16刚好时1,所以要开启uart1的时钟,我们就需要将bit17位设置为1
也就是0x20000,如下图:
配置完毕后,立马编译,烧录,可是uart1还是没用数据出来,还能哪里有问题呢,这个地方我卡了好久,后面去github上面下了一个新的uboot,我这个版本是2013版的,下载地址在这里:https://github.com/OpenNuvoton/NUC970_U-Boot_v2016.11
下下来之后打开serial_nuc970.c看到串口初始化的地方跟我这个版本有区别
串口初始化有3行,其中第一行是开启时钟的,我的uboot是在板子里的nuc970.c里面已经初始化过了,多了中间一行,RX拉高的操作,而uart1的RX是PE.3,所以我又做了拉高RX的操作
再编译烧录后测试,还是不行,真是无语了
接下来我把新的uboot里面的3行全部拷贝下来,都更改成uart1的,把之前boards/nuvoton/nuc970evb/nuc970里面串口初始化里的回复成原来的。
即串口驱动文件里面修改成这样
编译后烧录,板子上电,然后就看到串口出现了熟悉的uboot数据,到此终于成功了。
后面我把串口RX拉高这一步去掉发现也是可以的
那主要其实就是前面2句在起作用。