QEMU双实例Arm Cortex-M7共享内存读写无输出问题排查
问题:独立QEMU实例无法访问自定义共享内存地址0x10000000
我编写了两段代码:一段将字符串“Hello”写入内存地址0x10000000,另一段从该地址读取内容并打印。两段代码的链接脚本中均将0x10000000定义为共享内存,在两个独立的QEMU实例中运行(模拟Arm Cortex-M7处理器,目标机为lm3s811evb)。目前两段代码均已运行,但控制台无任何输出。使用GDB调试时,无法访问0x10000000地址的内存。
写入代码
// 写入目标内存地址 #define MEMORY_ADDRESS 0x10000000 // 将字符串写入指定内存地址的函数 void write_string_to_memory(char* address, const char* str) { while (*str != '\0') { *address = *str; address++; str++; } // 字符串末尾添加终止符 *address = '\0'; } // 入口函数 void main() { // 将内存地址转换为字符指针 char* memory_address = (char*)MEMORY_ADDRESS; // 向指定地址写入字符串"hello" write_string_to_memory(memory_address, "hello"); // 无限循环(暂停程序) while (1); }
链接脚本
MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00010000 SHARED_MEMORY (rwx) : ORIGIN = 0x10000000, LENGTH = 0x00001000 SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000 } SECTIONS { .text : { _text = .; KEEP(*(.isr_vector)) *(.text*) *(.rodata*) _etext = .; } > FLASH .data : AT(ADDR(.text) + SIZEOF(.text)) { _sdata = .; *(vtable) *(.data*) _edata = .; } > SRAM .bss : { _sbss = .; *(.bss*) *(COMMON) _ebss = .; } > SRAM .shared_memory : { /* 定义共享内存段 */ _shared_memory_start = .; *(.shared_memory*) _shared_memory_end = .; } > SHARED_MEMORY }
编译运行命令
arm-none-eabi-ld -T linker_lm3s811.ld main1-string.o startup1.o -o main1-string.elf ./qemu-system-arm -M lm3s811evb -kernel main1-string.elf -nographic
GDB调试信息
Breakpoint 1, main () at main1-string.c:18 18 char* memory_address = (char*)MEMORY_ADDRESS; (gdb) x/s 0x10000000 0x10000000: <error: Cannot access memory at address 0x10000000>
解决方案
1. QEMU lm3s811evb默认不识别自定义地址空间
QEMU对lm3s811evb的模拟严格遵循真实芯片的内存映射,而真实LM3S811芯片不存在0x10000000起始的内存区域。你在链接脚本中自定义的地址空间,QEMU不会主动创建,因此无法访问。
2. 跨QEMU实例实现共享内存的正确方法
两个独立QEMU实例默认完全隔离,需借助主机共享内存文件实现数据互通:
步骤1:在主机创建共享内存文件
# 创建4KB大小的共享内存文件(匹配你定义的0x1000长度) truncate -s 4k /tmp/qemu_shared_mem
步骤2:启动QEMU时映射共享内存到目标地址
修改QEMU启动命令,通过参数将主机共享内存映射到目标机的0x10000000地址:
# 启动写入程序的QEMU实例 ./qemu-system-arm -M lm3s811evb -kernel main1-string.elf -nographic \ -device virtio-mem-pci,memdev=shmem0 -object memory-backend-file,id=shmem0,path=/tmp/qemu_shared_mem,size=0x1000,share=on # 启动读取程序的QEMU实例,绑定同一个共享内存文件 ./qemu-system-arm -M lm3s811evb -kernel main2-read.elf -nographic \ -device virtio-mem-pci,memdev=shmem0 -object memory-backend-file,id=shmem0,path=/tmp/qemu_shared_mem,size=0x1000,share=on
3. 修复内存访问权限问题
即使完成映射,Cortex-M的MPU(内存保护单元)可能阻止地址访问:
- 若启用MPU,需添加对0x10000000~0x10000FFF区域的读写权限配置
- 你的链接脚本已将
SHARED_MEMORY设为rwx,这部分无需修改
4. 控制台无输出排查点
如果读取程序有打印逻辑但无输出,检查:
- 是否正确初始化UART串口(lm3s811evb的UART0默认对应QEMU控制台)
- 打印函数是否基于裸机实现(裸机环境无标准库
printf支持,需自行实现串口发送逻辑)
内容的提问来源于stack exchange,提问作者ankita7
相关产品推荐
相关产品推荐

