Browse Source

OK. 2021-10-03 19:39

zry 2 years ago
parent
commit
86e20f9520
11 changed files with 461 additions and 2 deletions
  1. 1 0
      .gitignore
  2. 80 0
      Makefile
  3. 55 2
      README.md
  4. 0 0
      asm/FOR_GIT_COMMIT
  5. 0 0
      inc/FOR_GIT_COMMIT
  6. 50 0
      linker-script.ld
  7. 0 0
      out/FOR_GIT_COMMIT
  8. 0 0
      src/FOR_GIT_COMMIT
  9. 15 0
      startup.s
  10. 67 0
      tools/qemu-rv32-spike.dts
  11. 193 0
      tools/qemu-rv32-virt.dts

+ 1 - 0
.gitignore

@@ -28,6 +28,7 @@
 *.i*86
 *.x86_64
 *.hex
+*.bin
 
 # Debug files
 *.dSYM/

+ 80 - 0
Makefile

@@ -0,0 +1,80 @@
+NAME = play_rv32_with_qemu_template
+
+# ==== Toolchain Configure ====
+PREFIX = W:/WCH/MounRiverStudio/toolchain/RISC-V Embedded GCC/bin
+CC = "$(PREFIX)/riscv-none-embed-gcc.exe"
+AS = "$(PREFIX)/riscv-none-embed-as.exe"
+LD = "$(PREFIX)/riscv-none-embed-ld.exe"
+OBJCOPY = "$(PREFIX)/riscv-none-embed-objcopy.exe"
+SIZE = "$(PREFIX)/riscv-none-embed-size.exe"
+QEMU_RV32 = "W:/QEMU/qemu-20210825/qemu-system-riscv32.exe"
+RM_CMD = ./tools/rm4win.exe -rf
+
+# ==== Path Configure ====
+SRC_DIR = ./src
+ASM_DIR = ./asm
+INC_DIR = ./inc
+OUT_DIR = ./out
+LINKER_SCRIPT = ./linker-script.ld
+STARTUP_SRC = ./startup.s
+
+# ==== Other Arguments ====
+CC_ARGS = -O0
+AS_ARGS =
+LD_ARGS =
+OBJCOPY_ARGS =
+SIZE_ARGS = --format=berkeley
+QEMU_ARGS = -nographic -bios none
+QEMU_MACHINE = virt
+
+# ===========================
+STARTUP_OBJ = $(patsubst %.s,$(OUT_DIR)/%.o,$(STARTUP_SRC))
+C_SRC = $(wildcard $(SRC_DIR)/*.c)
+C_OBJ = $(patsubst $(SRC_DIR)/%.c,$(OUT_DIR)/%.o,$(C_SRC))
+AS_SRC = $(wildcard $(ASM_DIR)/*.s)
+AS_OBJ = $(patsubst $(ASM_DIR)/%.s,$(OUT_DIR)/%.o,$(AS_SRC))
+
+
+.PHONY : all
+.PHONY : bin
+.PHONY : hex
+.PHONY : clean
+.PHONY : qemu
+.PHONY : size
+.IGNORE : qemu
+
+all : bin hex size
+
+bin : $(NAME).bin
+
+hex : $(NAME).hex
+
+$(NAME).hex : $(NAME).elf
+	$(OBJCOPY) $(OBJCOPY_ARGS) -O ihex $< $@
+
+$(NAME).bin : $(NAME).elf
+	$(OBJCOPY) $(OBJCOPY_ARGS) -O binary $< $@
+
+size : $(NAME).elf
+	$(SIZE) $(SIZE_ARGS) $<
+
+$(NAME).elf : $(LINKER_SCRIPT) $(STARTUP_OBJ) $(C_OBJ) $(AS_OBJ)
+	$(LD) -T $(LINKER_SCRIPT) $(LD_ARGS) -o $@ $(STARTUP_OBJ) $(C_OBJ) $(AS_OBJ)
+
+$(STARTUP_OBJ) : $(STARTUP_SRC)
+	$(AS) $(AS_ARGS) -o $@ $<
+
+$(OUT_DIR)/%.o : $(ASM_DIR)/%.s
+	$(AS) $(AS_ARGS) -o $@ $^
+
+$(OUT_DIR)/%.o : $(SRC_DIR)/%.c
+	$(CC) $(CC_ARGS) -o $@ $<
+
+clean :
+	-$(RM_CMD) ./$(NAME).bin
+	-$(RM_CMD) ./$(NAME).hex
+	-$(RM_CMD) ./$(NAME).elf
+	-$(RM_CMD) ./$(OUT_DIR)/*
+
+qemu : $(NAME).bin
+	$(QEMU_RV32) -machine $(QEMU_MACHINE) $(QEMU_ARGS) -kernel $<

+ 55 - 2
README.md

@@ -1,3 +1,56 @@
-# play-rv32-with-qemu-template
+# 文档
 
-A template for playing rv32 clang/asm programming with qemu.
+## 目录说明
+
+* `./asm/` 存放除startup以外的汇编源代码
+* `./inc/` 存放C语言头文件
+* `./src/` 存放C语言源代码
+* `./out/` 临时存放编译中间文件
+* `./linker-script.ld` 链接脚本
+* `./startup.s` 启动汇编文件
+* `./tools/` 存放额外的工具
+* `./tools/qemu-rv32-spike.dts` 从QEMU中dump出来的spike机器的设备树,这个文件本身不被编译所需,但是可以给您参考
+* `./tools/qemu-rv32-virt.dts` 从QEMU中dump出来的virt机器的设备树,这个文件本身不被编译所需,但是可以给您参考
+
+## Makefile变量说明
+
+### Toolchain Configure部分
+
+* `PREFIX` 指向GCC工具链的路径
+* `CC` C编译器
+* `AS` 汇编器
+* `LD` 链接器
+* `OBJCOPY` objcopy程序
+* `SIZE` size程序
+* `QEMU_RV32` QEMU的RV32可执行文件
+* `RM_CMD` 用于`make clean`的删除命令,在Windows上保持原值 `./tools/rm4win.exe -rf` 即可。 在Linux/Unix上修改为`rm -rf`
+
+### Path Configure部分
+
+通常无需修改
+
+### Other Arugments
+
+各命令的附加参数,可根据需要修改
+
+* `CC_ARGS` C编译器附加参数
+* `AS_ARGS` 汇编器附加参数
+* `LD_ARGS` 链接器附加参数
+* `OBJCOPY_ARGS` objcopy附加参数
+* `SIZE_ARGS` size附加参数
+* `QEMU_ARGS` QEMU附加参数
+* `QEMU_MACHINE` QEMU模拟的目标机器类型
+
+注:一般常用的机器类型会选择 `virt` 或者 `spike` ,virt和spike的区别可以参考`tools`目录下的设备树文件。关于`virt`机器,还可以参考<https://mth.st/blog/riscv-qemu/>。
+
+## 使用说明
+
+在开始之前,您需要先安装GCC RISC-V工具链和QEMU。
+
+先编辑Makefile,将Toolchain部分修改成您的工具链所在的位置。
+
+* `make all` 编译全部目标
+* `make clean` 清理编译结果和中间产物
+* `make qemu` 使用QEMU模拟器运行
+
+如果需要使用gdb调试,请在Makefile的QEMU附加参数变量`QEMU_ARGS`中增加参数`-s`,若希望QEMU启动后不运行CPU而是先等待gdb,还需要加`-S`参数。

+ 0 - 0
asm/FOR_GIT_COMMIT


+ 0 - 0
inc/FOR_GIT_COMMIT


+ 50 - 0
linker-script.ld

@@ -0,0 +1,50 @@
+/*
+	Linker Script For QEMU RV32 Virtual Machine Type `virt`
+*/
+
+OUTPUT_ARCH( "riscv" )
+
+ENTRY( _start )
+
+MEMORY
+{
+  ram   (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 128M
+}
+
+PHDRS
+{
+  text PT_LOAD;
+  data PT_LOAD;
+  bss PT_LOAD;
+}
+
+SECTIONS
+{
+  .text : {
+    PROVIDE(_text_start = .);
+    *(.text.init) *(.text .text.*)
+    PROVIDE(_text_end = .);
+  } >ram AT>ram :text
+
+  .rodata : {
+    PROVIDE(_rodata_start = .);
+    *(.rodata .rodata.*)
+    PROVIDE(_rodata_end = .);
+  } >ram AT>ram :text
+
+  .data : {
+    . = ALIGN(4096);
+    PROVIDE(_data_start = .);
+    *(.sdata .sdata.*) *(.data .data.*)
+    PROVIDE(_data_end = .);
+  } >ram AT>ram :data
+
+  .bss :{
+    PROVIDE(_bss_start = .);
+    *(.sbss .sbss.*) *(.bss .bss.*)
+    PROVIDE(_bss_end = .);
+  } >ram AT>ram :bss
+
+  PROVIDE(_memory_start = ORIGIN(ram));
+  PROVIDE(_memory_end = ORIGIN(ram) + LENGTH(ram));
+}

+ 0 - 0
out/FOR_GIT_COMMIT


+ 0 - 0
src/FOR_GIT_COMMIT


+ 15 - 0
startup.s

@@ -0,0 +1,15 @@
+.section .init
+.global _start
+_start:
+    li s1, 0x10000000 # s1 := 0x1000_0000
+    la s2, message    # s2 := <message>
+    addi s3, s2, 46   # s3 := s2 + 14
+1:
+    lb s4, 0(s2)      # s4 := (s2)
+    sb s4, 0(s1)      # (s1) := s4
+    addi s2, s2, 1    # s2 := s2 + 1
+    blt s2, s3, 1b    # if s2 < s3, branch back to 1
+
+.section .data
+message:
+  .string "Hello, world!\nHello, gensokyo!\nHello, RISC-V~\n"

+ 67 - 0
tools/qemu-rv32-spike.dts

@@ -0,0 +1,67 @@
+/dts-v1/;
+
+/ {
+	#address-cells = < 0x02 >;
+	#size-cells = < 0x02 >;
+	compatible = "ucbbar,spike-bare-dev";
+	model = "ucbbar,spike-bare,qemu";
+
+	chosen {
+		bootargs = [ 00 ];
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = < 0x00 0x80000000 0x00 0x8000000 >;
+	};
+
+	cpus {
+		#address-cells = < 0x01 >;
+		#size-cells = < 0x00 >;
+		timebase-frequency = < 0x989680 >;
+
+		cpu@0 {
+			phandle = < 0x01 >;
+			device_type = "cpu";
+			reg = < 0x00 >;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv32imafdcsu";
+			mmu-type = "riscv,sv32";
+
+			interrupt-controller {
+				#interrupt-cells = < 0x01 >;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = < 0x02 >;
+			};
+		};
+
+		cpu-map {
+
+			cluster0 {
+
+				core0 {
+					cpu = < 0x01 >;
+				};
+			};
+		};
+	};
+
+	soc {
+		#address-cells = < 0x02 >;
+		#size-cells = < 0x02 >;
+		compatible = "simple-bus";
+		ranges;
+
+		clint@2000000 {
+			interrupts-extended = < 0x02 0x03 0x02 0x07 >;
+			reg = < 0x00 0x2000000 0x00 0x10000 >;
+			compatible = "sifive,clint0\0riscv,clint0";
+		};
+	};
+
+	htif {
+		compatible = "ucb,htif0";
+	};
+};

+ 193 - 0
tools/qemu-rv32-virt.dts

@@ -0,0 +1,193 @@
+/dts-v1/;
+
+/ {
+	#address-cells = < 0x02 >;
+	#size-cells = < 0x02 >;
+	compatible = "riscv-virtio";
+	model = "riscv-virtio,qemu";
+
+	fw-cfg@10100000 {
+		dma-coherent;
+		reg = < 0x00 0x10100000 0x00 0x18 >;
+		compatible = "qemu,fw-cfg-mmio";
+	};
+
+	chosen {
+		bootargs = [ 00 ];
+		stdout-path = "/soc/uart@10000000";
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = < 0x00 0x80000000 0x00 0x8000000 >;
+	};
+
+	cpus {
+		#address-cells = < 0x01 >;
+		#size-cells = < 0x00 >;
+		timebase-frequency = < 0x989680 >;
+
+		cpu@0 {
+			phandle = < 0x01 >;
+			device_type = "cpu";
+			reg = < 0x00 >;
+			status = "okay";
+			compatible = "riscv";
+			riscv,isa = "rv32imafdcsu";
+			mmu-type = "riscv,sv32";
+
+			interrupt-controller {
+				#interrupt-cells = < 0x01 >;
+				interrupt-controller;
+				compatible = "riscv,cpu-intc";
+				phandle = < 0x02 >;
+			};
+		};
+
+		cpu-map {
+
+			cluster0 {
+
+				core0 {
+					cpu = < 0x01 >;
+				};
+			};
+		};
+	};
+
+	soc {
+		#address-cells = < 0x02 >;
+		#size-cells = < 0x02 >;
+		compatible = "simple-bus";
+		ranges;
+
+		flash@20000000 {
+			bank-width = < 0x04 >;
+			reg = < 0x00 0x20000000 0x00 0x2000000 0x00 0x22000000 0x00 0x2000000 >;
+			compatible = "cfi-flash";
+		};
+
+		rtc@101000 {
+			interrupts = < 0x0b >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x101000 0x00 0x1000 >;
+			compatible = "google,goldfish-rtc";
+		};
+
+		uart@10000000 {
+			interrupts = < 0x0a >;
+			interrupt-parent = < 0x03 >;
+			clock-frequency = < 0x384000 >;
+			reg = < 0x00 0x10000000 0x00 0x100 >;
+			compatible = "ns16550a";
+		};
+
+		poweroff {
+			value = < 0x5555 >;
+			offset = < 0x00 >;
+			regmap = < 0x04 >;
+			compatible = "syscon-poweroff";
+		};
+
+		reboot {
+			value = < 0x7777 >;
+			offset = < 0x00 >;
+			regmap = < 0x04 >;
+			compatible = "syscon-reboot";
+		};
+
+		test@100000 {
+			phandle = < 0x04 >;
+			reg = < 0x00 0x100000 0x00 0x1000 >;
+			compatible = "sifive,test1\0sifive,test0\0syscon";
+		};
+
+		pci@30000000 {
+			interrupt-map-mask = < 0x1800 0x00 0x00 0x07 >;
+			interrupt-map = < 0x00 0x00 0x00 0x01 0x03 0x20 0x00 0x00 0x00 0x02 0x03 0x21 0x00 0x00 0x00 0x03 0x03 0x22 0x00 0x00 0x00 0x04 0x03 0x23 0x800 0x00 0x00 0x01 0x03 0x21 0x800 0x00 0x00 0x02 0x03 0x22 0x800 0x00 0x00 0x03 0x03 0x23 0x800 0x00 0x00 0x04 0x03 0x20 0x1000 0x00 0x00 0x01 0x03 0x22 0x1000 0x00 0x00 0x02 0x03 0x23 0x1000 0x00 0x00 0x03 0x03 0x20 0x1000 0x00 0x00 0x04 0x03 0x21 0x1800 0x00 0x00 0x01 0x03 0x23 0x1800 0x00 0x00 0x02 0x03 0x20 0x1800 0x00 0x00 0x03 0x03 0x21 0x1800 0x00 0x00 0x04 0x03 0x22 >;
+			ranges = < 0x1000000 0x00 0x00 0x00 0x3000000 0x00 0x10000 0x2000000 0x00 0x40000000 0x00 0x40000000 0x00 0x40000000 0x3000000 0x03 0x00 0x03 0x00 0x01 0x00 >;
+			reg = < 0x00 0x30000000 0x00 0x10000000 >;
+			dma-coherent;
+			bus-range = < 0x00 0xff >;
+			linux,pci-domain = < 0x00 >;
+			device_type = "pci";
+			compatible = "pci-host-ecam-generic";
+			#size-cells = < 0x02 >;
+			#interrupt-cells = < 0x01 >;
+			#address-cells = < 0x03 >;
+		};
+
+		virtio_mmio@10008000 {
+			interrupts = < 0x08 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10008000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10007000 {
+			interrupts = < 0x07 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10007000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10006000 {
+			interrupts = < 0x06 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10006000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10005000 {
+			interrupts = < 0x05 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10005000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10004000 {
+			interrupts = < 0x04 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10004000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10003000 {
+			interrupts = < 0x03 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10003000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10002000 {
+			interrupts = < 0x02 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10002000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		virtio_mmio@10001000 {
+			interrupts = < 0x01 >;
+			interrupt-parent = < 0x03 >;
+			reg = < 0x00 0x10001000 0x00 0x1000 >;
+			compatible = "virtio,mmio";
+		};
+
+		plic@c000000 {
+			phandle = < 0x03 >;
+			riscv,ndev = < 0x35 >;
+			reg = < 0x00 0xc000000 0x00 0x210000 >;
+			interrupts-extended = < 0x02 0x0b 0x02 0x09 >;
+			interrupt-controller;
+			compatible = "sifive,plic-1.0.0\0riscv,plic0";
+			#interrupt-cells = < 0x01 >;
+			#address-cells = < 0x00 >;
+		};
+
+		clint@2000000 {
+			interrupts-extended = < 0x02 0x03 0x02 0x07 >;
+			reg = < 0x00 0x2000000 0x00 0x10000 >;
+			compatible = "sifive,clint0\0riscv,clint0";
+		};
+	};
+};