uart相关的代码参考自xfel/payloads/d1_f133/d1-ddr/source/sys-uart.c ,刚开始看代码时有几处看起来有些迷惑:
// 保持0x0c的UART_LCR高4:31位不变,将低2位设置为11,表示数据长度为8bit
// 第3位设置为0,表示stop比特的长度为1、第4位设置为0表示不对数据进行校验
val = read32(addr + 0x0c);
val &= ~0x0f;
val |= (0x3 << 0) | (0x0 << 2) | (0x0 << 3);
write32(addr + 0x0c, val);
这里(0x3 << 0) | (0x0 << 2) | (0x0 << 3)
第一眼看上去等价于0x3
,似乎写成val |= 0x3
更合适。
后面了解到,这样写算一种规范;用d << d
的方式表示这个数字有特殊含义,表示这是在针对寄存器中的某一位进行读写,这种方式更加清晰。虽然我们也可以写成val |= 0b0011
,但val |= (0x3 << 0) | (0x0 << 2) | (0x0 << 3)
的写法语意更加明确。它表示针对低2位将其设置为11、针对第3位设置为0、针对第4位设置为0。
我们可以从D1手册中翻阅UART_LCR低4位的用途(省略图示)。可以看到低4位分为了3块:低2位用于控制数据长度、第3位用于表示stop比特的长度、第4位用于表示是否进行校验。
在设置波特率时,有这样的代码:
// 设置0x00的UART_DLL为0x0d,即13,对应波特率为115200
write32(addr + 0x00, 0xd);
// 设置0x04的UART_DLM为0x00,即将波特率的高8位设置位0
write32(addr + 0x04, 0xd >> 8);
对于0x0d >> 8
感到疑惑,直接写成0不就好了,为啥还要右移8位?
波特率由16个字节组成,低8位通过UART_DLL
设置,高8位通过UART_DLH
设置;右移8位其实就是获得波特率的高8位,写成下面的方式更好理解:
write32(addr + 0x00, 0x0d);
write32(addr + 0x04, 0x000d >> 8);
用0x000d
表示这是16位的数据,右移8位获取其高8位数值。
之前一直觉得LicheeRV Dock、D1、XuanTie C906表示同一个东西,当我说D1的时候就是在说LicheeRV Dock。。。
后面发现不是这么回事,LicheeRV Dock指的是开发板,D1指的是嵌在开发板上的芯片,而XuanTie C906则是芯片上采用的CPU。Lichee RV Nezha、Lichee RV-86 Panel、Lichee RV Dock开发板上用的也是D1芯片,而D1、D1s和F133芯片上使用的都是XuanTie C906。所以开发板是开发板,芯片是芯片,CPU是CPU,是三种不同的东西。
在针对发开板进行编程时,我们最需要去看的是芯片手册,因为芯片上的限定了引脚的地址,而芯片手册上则有对于这些地址的详细信息。通过这些详细信息我们可以知道DRAM的起始地址、UART中各个寄存器的作用。在完成这个项目时,主要翻阅的也是D1芯片手册。