2. 自制操作系统: risc-v virt board output “hello world“

746 阅读1分钟

平台

查看qemu支持的riscv64的board

$ qemu-system-riscv64 -machine help
Supported machines are:
none                 empty machine
sifive_e             RISC-V Board compatible with SiFive E SDK
sifive_u             RISC-V Board compatible with SiFive U SDK
spike                RISC-V Spike Board (default)
spike_v1.10          RISC-V Spike Board (Privileged ISA v1.10)
spike_v1.9.1         RISC-V Spike Board (Privileged ISA v1.9.1)
virt                 RISC-V VirtIO board

手里没有riscv64的board,使用virt board

DTS文件

查看virt的dts

$ qemu-system-riscv64 -machine virt,dumpdtb=qemu-riscv64-virt.dtb
$ dtc qemu-riscv64-virt.dtb > qemu-riscv64-virt.dts

如果提示dtc命令不存在,安装

$ sudo apt install device-tree-compiler

生成文件:qemu-riscv64-virt.dts

查看内存布局

memory@80000000 {
        device_type = "memory";
        reg = <0x00 0x80000000 0x00 0x8000000>;
};

根据内存起始地址,设置链接脚本的开始地址为0x80000000

查看uart布局

uart@10000000 {
        interrupts = <0x0a>;
        interrupt-parent = <0x03>;
        clock-frequency = <0x384000>;
        reg = <0x00 0x10000000 0x00 0x100>;
        compatible = "ns16550a";
};

可以将字符输出到0x10000000的内存地址。

代码解析

.section .text.boot  #指定此文件编译出的代码在.text.boot段
 
 
.globl _start
_start:
    li s1, 0x10000000 # s1寄存器赋值为uart内存的地址
    la s2, message    # s2寄存器赋值为message的首地址
    addi s3, s2, 14   # s3寄存器赋值为message的结束地址
1:
    lb s4, 0(s2)      # s4赋值为s2内存中的值
    sb s4, 0(s1)      # s4寄存器内的值输出到s1(uart)内存中
    addi s2, s2, 1    # s2 := s2 + 1
    blt s2, s3, 1b    # if s2 < s3, branch back to 1
 
 
.section .data
message:
  .string "Hello, world!\n"

测试

make

$ make
rm -rf build *.img kernel.map
mkdir -p build
riscv64-linux-gnu-gcc -g -Wall -nostdlib  -Iinclude  -MMD -c src/start.c -o build/start_c.o
riscv64-linux-gnu-gcc -g -Iinclude  -MMD -c -D__ASSEMBLY__ src/startup.S -o build/startup_s.o
riscv64-linux-gnu-ld -T src/linker.ld -Map kernel.map -o build/kernel.elf  build/start_c.o build/startup_s.o
riscv64-linux-gnu-objcopy build/kernel.elf -O binary kernel.img

run

make run
qemu-system-riscv64 -machine virt -bios none -kernel build/kernel.elf  -nographic
Hello, world!

参考代码

点我