使用 c

问题描述 投票:0回答:1

我使用 UART 在 RISC-V qemu 上制作了一个 helloworld 程序,使用 https://popovicu.com/posts/bare-metal-programming-risc-v/ Uros Popovicu 的 RISC-V 汇编指南。我想知道如何使用 c 和 RISC-V qemu 写入 UART。 我试过了:

#define UART_TX 0x10000000  

void _start() {
    char *str = "Hello, World!\n";
    for (int i = 0; str[i] != '\0'; ++i) {
        *(volatile char*)UART_TX = str[i];
    }

    while (1);
}

我尝试编译c代码:

riscv64-linux-gnu-gcc -S -o hello.s hello.c
riscv64-linux-gnu-as -march=rv64i -mabi=lp64 -o hello.o -c hello.s

到 RISC-V 并使用与 popovicu 示例中相同的链接器文件:

 riscv64-linux-gnu-ld -T linker.ld --no-dynamic-linker -m elf64lriscv -static -nostdlib -s -o hello hello.o

使用以下链接器文件(仅进行一些细微修改):

ENTRY(_start)

MEMORY {
  dram_space (rwx) : ORIGIN = 0x80000000, LENGTH = 1024
}

SECTIONS {
  .text : {
    hello.o(.text.bios)
  } > dram_space
}

并使用以下命令运行它:

qemu-system-riscv64 -machine virt -bios hello

这会导致不打印任何内容。这是访问 UART 的正确方法还是我的错误出在其他地方?预先感谢。

c linker qemu uart riscv
1个回答
1
投票

您尝试做的问题是您没有正确设置 C 可以使用的环境。

_start
符号通常总是在汇编中。

特别是,使用 GDB 附加到 QEMU,我看到堆栈指针

sp
仍将具有默认的
0x0
值。 C 代码依赖于有效内存中的堆栈,并且系统在程序的第二条指令处崩溃,该指令尝试写入堆栈上的区域。

使用

-bios
QEMU 标志,您表示您将完成所有设置工作(除了将 HART ID 加载到
a0
然后跳转到您的代码的一些指令之外。)您需要从汇编开始,设置一个可用的环境(包括加载具有所需值的寄存器),然后您可以跳转到 C 代码。


顺便说一句,所有内容都在您链接到的文章中汇编程序的

.text.bios
部分中。 C 程序的情况并非如此,您应该使用较少的链接器脚本。虽然链接了正确的部分,但
hello.o(.text.bios)
并没有按照您的想法进行操作。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.