Hello RVOS(上)
这个virt_memmap
是一个虚拟地址到物理地址的映射,虚拟地址被分成了很多很多,比如看内存的虚拟地址,就被分到了0x80000000 ...
系统引导
的过程:
当上电的时候,CPU开始运行,硬件首先跑到0x1000这个地址,这是一个烧录的ROM,里面有boot的汇编指令,这里的代码可以做一些初始化硬件等事情,然后跳转到Kernel代码的``0x80000000`去执行,所以要把第一条指令放在0x80000000.
在我们的Qemu中,是将代码放到0x80000000,然后boot之后就会自动执行这部分代码:
可以看到,这部分指定了代码放到0x80000000
- 硬件上,8个核同时都会去执行0x80000000的代码,这里为了讲解方便,就让以额
我们这里的课程做一个简化,就是只用一个核
,实际上还是8个核. 由于每个核都会执行一遍这个引导程序,所以做一个判断即可,是否是第一个hart,是第一个hart才正常去跑,不是第一个hart的都空转
如何判断当前 hart 是不是第一 个 hart?
每个权限Level都有自己的一组
控制寄存器
,高级别Level的可以访问低级别Level的CSR.
一上电的时候是在Machine模式,所以我们先关注M模式下的CSR:
CSR寄存器的读写不能用通用寄存器那种读写来操作,是要用新的指令:
我们关注CSRRW和CSRRS
一、CSRRW (Atomic Read/Write CSR)
CSRRW RD,CSR,RS1
:先CSR的值写到RD,RS1的值写到CSR (这两步是原子的)即 RD=CSR , CSR = RS1
由这个产生一个常用的伪指令——
csrw
——csrw csr,rs
等价于csrrw x0,csr,rs
,即将rs的值赋值给csr寄存器二、CSRRS(Atomic Read and Set Bits in CSR)
CSRRS RD,CSR,RS1
: RD = CSR , CSR |= RS1 (这两步原子操作完成)利用CSRRS产生一个常用的伪指令——
csrr
——csrr rd,csr
:等价于csrrs rd,csr,x0
,即将csr赋值给rd,即``rd=csr`
ok,我们进入正题了.
mhartid
存放着当前hart的ID.
当上电后,跳转到0x80000000时:
csrr t0,mhartid
:t0=mhartid
mv tp,t0
:tp=t0
bnez t0,park
:如果t0的值不等于0,就跳转到park,park这边的逻辑是一个死循环
Hello RVOS(下)
- UART:
串口通信
(Universal Asynchronous Receiver/Transmitter异步收发传输器
)
1.UART 的硬件连接方式
像显示器等复杂的东西,一般都不会在开发板上就直接做出来,往往是通过上面这根红色的串口线
来连到我们的主机上,我们的主机上运行一个串口的接收程序
(可以认为是一个客户端),这样就可以把信息打印到我们的屏幕上
我们使用的是模拟器,所以内部不会实际上去接这样的串口线,但要知道,实际上是模拟了这样的串口线.
串口线
其实就是一收一发,TX是发送端(Transmitter),RX是接收端(Receiver)
2.UART 的 特点
3.UART 的通讯协议
4.NS16550a 编程接口介绍
NS16550a是我们的模拟器模拟的串口收发器的型号.
地址0x1000-0000 ~ 0x1000-0100是留给串口设备的寄存器使用,通过这个地址来访问这些寄存器
5.NS16550a 的初始化
6.NS16550a 的数据读写
UART里面有一个寄存器来存当前的传来的字节,我们需要用轮询(一直检查是否空闲,可以发下个字节了)或中断(空闲了触发中断)处理的方式知道这个字节什么时候发出去了,发出去了才能传下个字节
THR
:这个就是放数据的寄存器LSR
:这里有一个特殊的bit来告知当前是否空闲了
这两个配合就可以完成数据发送的任务,
代码如下:
可以看到,就是如果LSR的第5位是0,那么一直空转,直到第5位是1了,说明空闲了,才将这个字节放到THR:这是一种轮询方式