QEMU RISC-V环境下用C语言写UART无输出,求问题排查
问题排查与解决
1. 链接脚本的核心错误
你的链接脚本中.text段仅指定包含hello.o(.text.bios),但C编译器生成的_start函数实际位于普通.text段(而非.text.bios),这会导致链接后的可执行文件中,代码未被正确放入指定内存区域,QEMU加载后无法执行到你的逻辑。
修改链接脚本,确保包含所有必要的代码和数据段:
ENTRY(_start) MEMORY { dram_space (rwx) : ORIGIN = 0x80000000, LENGTH = 1024K } SECTIONS { .text : { *(.text) *(.text.*) } > dram_space .rodata : { *(.rodata) *(.rodata.*) } > dram_space .data : { *(.data) *(.data.*) } > dram_space .bss : { *(.bss) *(.bss.*) } > dram_space }
注:将内存长度从1024改为1024K,避免代码和字符串空间不足。
2. 编译命令优化与修正
当前编译步骤冗余且缺少裸机环境必要的编译选项,直接用gcc生成目标文件更可靠:
# 直接编译为目标文件,添加裸机编译参数 riscv64-linux-gnu-gcc -march=rv64i -mabi=lp64 -ffreestanding -nostdlib -c hello.c -o hello.o
-ffreestanding:告知编译器当前是无操作系统的独立环境-nostdlib:不链接标准库,避免引入不必要的依赖
链接命令简化为:
riscv64-linux-gnu-ld -T linker.ld -m elf64lriscv -static -nostdlib -o hello hello.o
移除--no-dynamic-linker和-s(-s会剥离符号,不利于调试)。
3. UART访问逻辑验证
你指定的UART地址0x10000000是正确的(QEMU virt平台UART0基址),且用volatile char*确保编译器不会优化写入操作,这部分逻辑没问题。
4. 调试建议
若修改后仍无输出,可通过QEMU调试确认代码是否执行:
# 启动QEMU并等待调试连接 qemu-system-riscv64 -machine virt -bios hello -s -S
打开另一个终端用gdb连接:
riscv64-linux-gnu-gdb hello (gdb) target remote :1234 (gdb) break _start (gdb) continue
检查是否能命中_start断点,确认代码是否被正确加载。
内容的提问来源于stack exchange,提问作者Jip Helsen
相关产品推荐
相关产品推荐

