学习使用一个最简单的RISCV项目 ---- riscv-probe
项目地址: https://github.com/michaeljclark/riscv-probe
项目简介:
riscv探头
简单的机器模式程序,用于探测RISC-V控制和状态寄存器。riscv-probe目前主要用于 Spike, QEMU和 SiFive E21内核。riscv-probe是一种测试工具,用于比较多个RISC-V仿真器和RISC-V硬件实现之间的CSR(控制和状态寄存器)。
riscv-probe包含libfemto,它是一个轻量级的裸金属C库,符合POSIX.1-2017 / IEEE 1003.1-2017标准的简化集。libfemto可以用作需要中断处理,基本字符串例程和printf的裸机RISC-V程序的起点。
项目构建:
构建系统使用CROSS_COMPILE工具链前缀并期望工具链存在于PATH环境变量中。然而,默认值CROSS_COMPILE是riscv64-unknown-elf-可以覆盖的,例如make CROSS_COMPILE=riscv64-unknown-linux-gnu-。构建系统需要一个multilib工具链,因为它使用相同的工具链来构建riscv32和riscv64。确保--enable-multilib在配置riscv-gnu-toolchain时使用。这些示例都是-nostartfiles -nostdlib -nostdinc使用RISC-V GCC Newlib工具链或RISC-V GCC Glibc Linux工具链构建的。
要在environent设置后构建示例,请键入:
make
使用方法:
要在spike和RISC-V QEMU中调用探测器示例:
$ spike --isa=RV32IMAFDC build/bin/rv32imac/spike/probe
$ spike --isa=RV64IMAFDC build/bin/rv64imac/spike/probe
$ qemu-system-riscv32 -nographic -machine spike_v1.10 -kernel build/bin/rv32imac/spike/probe
$ qemu-system-riscv64 -nographic -machine spike_v1.10 -kernel build/bin/rv64imac/spike/probe
$ qemu-system-riscv32 -nographic -machine virt -kernel build/bin/rv32imac/virt/probe
$ qemu-system-riscv64 -nographic -machine virt -kernel build/bin/rv64imac/virt/probe
$ qemu-system-riscv32 -nographic -machine sifive_e -kernel build/bin/rv32imac/qemu-sifive_e/probe
$ qemu-system-riscv64 -nographic -machine sifive_e -kernel build/bin/rv64imac/qemu-sifive_e/probe
$ qemu-system-riscv32 -nographic -machine sifive_u -kernel build/bin/rv32imac/qemu-sifive_u/probe
$ qemu-system-riscv64 -nographic -machine sifive_u -kernel build/bin/rv64imac/qemu-sifive_u/probe
离线
按上面的流程编译,参考晕哥前面发的帖子, 运行都没有问题, 起码链接出来的 hello 程序在 qemu 虚拟机下面跑是完全正常的。
离线
但是我想自己用 gcc 编译链接却卡在那个汇编文件了
lilo@ubuntu:/opt/riscv-probe# riscv64-unknown-elf-as -Ienv/common-I./libfemto/include/-I./env/common/rv64/ -I./libfemto/include/ -I./env/common/ -c ./env/virt/crt.s
./env/common//crtm.s: Assembler messages:
./env/common//crtm.s:3: Error: can't open macros.s for reading: No such file or directory
./env/common//crtm.s:39: Error: illegal operands `addi sp,sp,-CONTEXT_SIZE'
./env/common//crtm.s:40: Error: unrecognized opcode `sxsp ra,0'
./env/common//crtm.s:41: Error: unrecognized opcode `sxsp a0,1'
./env/common//crtm.s:42: Error: unrecognized opcode `sxsp a1,2'
./env/common//crtm.s:43: Error: unrecognized opcode `sxsp a2,3'
./env/common//crtm.s:44: Error: unrecognized opcode `sxsp a3,4'
./env/common//crtm.s:45: Error: unrecognized opcode `sxsp a4,5'
./env/common//crtm.s:46: Error: unrecognized opcode `sxsp a5,6'
./env/common//crtm.s:47: Error: unrecognized opcode `sxsp a6,7'
./env/common//crtm.s:48: Error: unrecognized opcode `sxsp a7,8'
./env/common//crtm.s:49: Error: unrecognized opcode `sxsp t0,9'
./env/common//crtm.s:50: Error: unrecognized opcode `sxsp t1,10'
./env/common//crtm.s:51: Error: unrecognized opcode `sxsp t2,11'
./env/common//crtm.s:52: Error: unrecognized opcode `sxsp t3,12'
./env/common//crtm.s:53: Error: unrecognized opcode `sxsp t4,13'
./env/common//crtm.s:54: Error: unrecognized opcode `sxsp t5,14'
./env/common//crtm.s:55: Error: unrecognized opcode `sxsp t6,15'
./env/common//crtm.s:64: Error: unrecognized opcode `lxsp ra,0'
./env/common//crtm.s:65: Error: unrecognized opcode `lxsp a0,1'
./env/common//crtm.s:66: Error: unrecognized opcode `lxsp a1,2'
./env/common//crtm.s:67: Error: unrecognized opcode `lxsp a2,3'
./env/common//crtm.s:68: Error: unrecognized opcode `lxsp a3,4'
./env/common//crtm.s:69: Error: unrecognized opcode `lxsp a4,5'
./env/common//crtm.s:70: Error: unrecognized opcode `lxsp a5,6'
./env/common//crtm.s:71: Error: unrecognized opcode `lxsp a6,7'
./env/common//crtm.s:72: Error: unrecognized opcode `lxsp a7,8'
./env/common//crtm.s:73: Error: unrecognized opcode `lxsp t0,9'
./env/common//crtm.s:74: Error: unrecognized opcode `lxsp t1,10'
./env/common//crtm.s:75: Error: unrecognized opcode `lxsp t2,11'
./env/common//crtm.s:76: Error: unrecognized opcode `lxsp t3,12'
./env/common//crtm.s:77: Error: unrecognized opcode `lxsp t4,13'
./env/common//crtm.s:78: Error: unrecognized opcode `lxsp t5,14'
./env/common//crtm.s:79: Error: unrecognized opcode `lxsp t6,15'
./env/common//crtm.s:80: Error: illegal operands `addi sp,sp,CONTEXT_SIZE'
./env/virt/crt.s: Error: invalid operands (*ABS* and *UND* sections) for `*' when setting `CONTEXT_SIZE'
https://github.com/michaeljclark/riscv-probe/blob/master/env/virt/crt.s
https://github.com/michaeljclark/riscv-probe/blob/master/env/common/constants.s
https://github.com/michaeljclark/riscv-probe/blob/master/env/common/crtm.s
https://github.com/michaeljclark/riscv-probe/blob/master/env/common/rv64/macros.s
看起来包含目录也是没有问题的.
离线
实在没办法了,把三个 .s 文件手动合并成 crt.s 文件:
# See LICENSE for license details.
# See LICENSE for license details.
.equ REGBYTES, 8
.macro lx a, b
ld \a, \b
.endm
.macro sx a, b
sd \a, \b
.endm
.macro lxsp a, b
ld \a, ((\b)*REGBYTES)(sp)
.endm
.macro sxsp a, b
sd \a, ((\b)*REGBYTES)(sp)
.endm
.macro .ptr a
.8byte \a
.endm
# See LICENSE for license details.
.equ MAX_HARTS, 4
.equ SAVE_REGS, 16
.equ STACK_SIZE, 1024
.equ STACK_SHIFT, 10
.equ CONTEXT_SIZE, (SAVE_REGS * REGBYTES)
.globl _text_start
.globl _text_end
.globl _rodata_start
.globl _rodata_end
.globl _data_start
.globl _data_end
.globl _bss_start
.globl _bss_end
.global _memory_start;
.global _memory_end;
#
# start of trap handler
#
.section .text.init,"ax",@progbits
.globl _start
_start:
# setup default trap vector
la t0, trap_vector
csrw mtvec, t0
# set up stack pointer based on hartid
csrr t0, mhartid
slli t0, t0, STACK_SHIFT
la sp, stacks + STACK_SIZE
add sp, sp, t0
# park all harts excpet hart 0
csrr a0, mhartid
bnez a0, park
# jump to libfemto_start_main
j libfemto_start_main
# sleeping harts mtvec calls trap_fn upon receiving IPI
park:
wfi
j park
.align 2
trap_vector:
# Save registers.
addi sp, sp, -CONTEXT_SIZE
sxsp ra, 0
sxsp a0, 1
sxsp a1, 2
sxsp a2, 3
sxsp a3, 4
sxsp a4, 5
sxsp a5, 6
sxsp a6, 7
sxsp a7, 8
sxsp t0, 9
sxsp t1, 10
sxsp t2, 11
sxsp t3, 12
sxsp t4, 13
sxsp t5, 14
sxsp t6, 15
# Invoke the handler.
mv a0, sp
csrr a1, mcause
csrr a2, mepc
jal trap_handler
# Restore registers.
lxsp ra, 0
lxsp a0, 1
lxsp a1, 2
lxsp a2, 3
lxsp a3, 4
lxsp a4, 5
lxsp a5, 6
lxsp a6, 7
lxsp a7, 8
lxsp t0, 9
lxsp t1, 10
lxsp t2, 11
lxsp t3, 12
lxsp t4, 13
lxsp t5, 14
lxsp t6, 15
addi sp, sp, CONTEXT_SIZE
# Return
mret
.bss
.align 4
.global stacks
stacks:
.skip STACK_SIZE * MAX_HARTS
然后执行编译, 生成 crt.o:
riscv64-unknown-elf-gcc -c -march=rv64imac -mabi=lp64 -mcmodel=medany -ffunction-sections -fdata-sections crt.s
再编译其他的 .c 文件
riscv64-unknown-elf-gcc -Ienv/common \
-I./libfemto/include/ \
-I./env/common/rv64 \
-I./libfemto/include/ \
-I./env/common/ \
-c \
./examples/hello/hello.c \
./libfemto/std/strncmp.c \
./libfemto/std/abort.c \
./libfemto/std/memcpy.c \
./libfemto/std/ctz.c \
./libfemto/std/printf.c \
./libfemto/std/strcmp.c \
./libfemto/std/putchar.c \
./libfemto/std/memset.c \
./libfemto/std/getchar.c \
./libfemto/std/clz.c \
./libfemto/std/strlen.c \
./libfemto/std/memchr.c \
./libfemto/std/vsnprintf.c \
./libfemto/std/exit.c \
./libfemto/std/strchr.c \
./libfemto/std/malloc.c \
./libfemto/std/puts.c \
./libfemto/std/vprintf.c \
./libfemto/std/strncpy.c \
./libfemto/std/memcmp.c \
./libfemto/std/snprintf.c \
./libfemto/arch/riscv/device.c \
./libfemto/arch/riscv/csr.c \
./libfemto/arch/riscv/trap.c \
./libfemto/arch/riscv/pmp.c \
./libfemto/arch/riscv/memory.c \
./libfemto/arch/riscv/auxval.c \
./libfemto/arch/riscv/start.c \
./libfemto/drivers/ns16550a.c \
./libfemto/drivers/sifive_test.c \
./env/virt/setup.c \
-march=rv64imac -mabi=lp64 \
-mcmodel=medany -ffunction-sections -fdata-sections
链接成 hello:
riscv64-unknown-elf-gcc -o hello \
hello.o \
strncmp.o \
abort.o \
memcpy.o \
ctz.o \
printf.o \
strcmp.o \
putchar.o \
memset.o \
getchar.o \
clz.o \
strlen.o \
memchr.o \
vsnprintf.o \
exit.o \
strchr.o \
malloc.o \
puts.o \
vprintf.o \
strncpy.o \
memcmp.o \
snprintf.o \
device.o \
csr.o \
trap.o \
pmp.o \
memory.o \
auxval.o \
start.o \
ns16550a.o \
sifive_test.o \
setup.o \
crt.o \
-T env/virt/default.lds \
-mcmodel=medany -ffunction-sections -fdata-sections -nostartfiles -nostdlib -nostdinc -static -lgcc -Wl,--nmagic -Wl,--gc-sections
运行:
qemu-system-riscv64 -nographic -machine virt -kernel hello
运行一切正常:
lilo@ubuntu:/opt/riscv-probe# qemu-system-riscv64 -nographic -machine virt -kernel hello
hello
lilo@ubuntu:/opt/riscv-probe#
离线
riscv64-unknown-elf-gcc -o hello \
hello.o \
printf.o \
putchar.o \
getchar.o \
vsnprintf.o \
exit.o \
malloc.o \
puts.o \
vprintf.o \
snprintf.o \
device.o \
csr.o \
trap.o \
memory.o \
auxval.o \
start.o \
ns16550a.o \
sifive_test.o \
setup.o \
crt.o \
-T env/virt/default.lds \
-mcmodel=medany -ffunction-sections -fdata-sections -nostartfiles -nostdlib -nostdinc -static -lgcc -Wl,--nmagic -Wl,--gc-sections
这个差不多是 ns16550串口(qemu virt 模拟器)模拟 printf输出 RISCV程序 的最精简版本了.
如果不使用 printf 可以更精简一些.
离线