You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM小型OS开发:Bootloader与Kernel无输出问题排查求助

ARM小型OS Bootloader无输出问题排查与修复

问题背景

开发ARM架构小型OS,编写了Bootloader汇编代码、Kernel C代码及编译Makefile,使用QEMU运行后未看到预期的Hello, ARM world!输出。相关代码及运行命令如下:

Bootloader代码(bootloader.s)

.global _start

.text
_start:
    /* Set up the stack */
    ldr sp, =stack_top

    /* Call the kernel entry point */
    bl kernel_entry

    /* Infinite loop */
hang:
    b hang

.bss
.space 1024
stack_top:

Kernel代码(kernel.c)

void kernel_entry(void) {
    const char *msg = "Hello, ARM world!\n";
    char *uart = (char *)0x101f1000;  // UART base address for ARM

    while (*msg) {
        *uart = *msg++;
    }

    while (1);
}

Makefile代码

all: bootloader.bin

bootloader.bin: bootloader.elf
    arm-none-eabi-objcopy -O binary bootloader.elf bootloader.bin

bootloader.elf: bootloader.o kernel.o
    arm-none-eabi-ld -Ttext 0x8000 -o bootloader.elf bootloader.o kernel.o

kernel.o: kernel.c
    arm-none-eabi-gcc -ffreestanding -nostdlib -c -o kernel.o kernel.c

bootloader.o: bootloader.s
    arm-none-eabi-as -o bootloader.o bootloader.s

run: bootloader.bin kernel.img
    ./run.sh

clean:
    rm -f *.o *.elf *.bin

原QEMU运行命令

qemu-system-arm -M versatilepb -m 128M -kernel "C:/Users/Ukraine/Documents/FlowyOS/bootloader.bin" -initrd "C:/Users/Ukraine/Documents/FlowyOS/kernel.img" -d int

问题分析

导致无输出的核心问题集中在UART操作逻辑、QEMU启动参数及Makefile冗余配置三个方面:

  • UART寄存器操作未等待发送就绪,硬件可能未及时处理写入的数据
  • QEMU命令错误使用-initrd参数,且未配置串口重定向到终端
  • Makefile中存在无意义的kernel.img依赖,且run脚本未正确配置启动参数

修复方案

1. 修正QEMU启动命令

去掉冗余的-initrd参数(bootloader.bin已包含kernel代码,无需初始RAM盘),添加-serial stdio将UART输出重定向到终端:

qemu-system-arm -M versatilepb -m 128M -kernel "C:/Users/Ukraine/Documents/FlowyOS/bootloader.bin" -serial stdio

2. 修复Kernel的UART发送逻辑

添加等待UART发送寄存器就绪的逻辑,确保硬件能正确接收并发送数据,同时用volatile避免编译器优化硬件寄存器访问:

void kernel_entry(void) {
    const char *msg = "Hello, ARM world!\n";
    // 用volatile确保硬件寄存器访问不被优化
    volatile unsigned int *uart_base = (volatile unsigned int *)0x101F1000;
    
    #define UART_DR    0x00  // 数据寄存器偏移
    #define UART_LSR   0x14  // 线路状态寄存器偏移
    #define LSR_THRE   (1 << 5)  // 发送保持寄存器空标志位

    while (*msg) {
        // 等待发送寄存器为空,确保上一个字节已发送完成
        while (!(uart_base[UART_LSR / 4] & LSR_THRE));
        // 写入当前字符到UART数据寄存器
        uart_base[UART_DR / 4] = *msg++;
    }

    while (1);
}

3. 修正Makefile配置

删除无意义的kernel.img依赖,直接在run目标中调用正确的QEMU命令:

all: bootloader.bin

bootloader.bin: bootloader.elf
    arm-none-eabi-objcopy -O binary bootloader.elf bootloader.bin

bootloader.elf: bootloader.o kernel.o
    arm-none-eabi-ld -Ttext 0x8000 -o bootloader.elf bootloader.o kernel.o

kernel.o: kernel.c
    arm-none-eabi-gcc -ffreestanding -nostdlib -c -o kernel.o kernel.c

bootloader.o: bootloader.s
    arm-none-eabi-as -o bootloader.o bootloader.s

run: bootloader.bin
    qemu-system-arm -M versatilepb -m 128M -kernel bootloader.bin -serial stdio

clean:
    rm -f *.o *.elf *.bin

4. 验证链接地址(可选)

用以下命令确认符号地址是否正确:

arm-none-eabi-nm bootloader.elf | grep -E "_start|kernel_entry|stack_top"

确保_start地址为0x8000,kernel_entry和stack_top地址在合理范围内。


内容的提问来源于stack exchange,提问作者Dmytro Parkhomenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 13:07:32