QEMU添加设备相关-中断控制器、串口、pflash支持

QEMU添加设备相关-中断控制器、串口、pflash支持

一、添加串口支持:

真实板卡的初期调试中,串口打印可谓神器,几乎所有的SOC都会带有串口这个外设,因此我们也需要添加串口到我们的定义中。

  • 首先添加几个串口的基地址,添加多个串口的目的是为了后面在读个权限空间内跑不同的系统因此需要不同的权限的串口打印输出。

    [SIFIVE_U_UART0] = { 0x10013000, 0x1000 },

    [SIFIVE_U_UART1] = { 0x10023000, 0x1000 },

  • 在初始化函数中调用serial_mm_init创建串口实例,这个串口仿真ns16550a的定义,在后续opensbi、u-boot、kernel中有这个串口的驱动,方面移植。在sifive_u模拟板中,我们使用的是sifive_uart_create函数来实现uart实例的实现,它的仿真驱动文件位于同级的sifive_uart.c中。

serial_mm_init(system_memory,
memmap[QUARD_STAR_UART0].base, 0, qdev_get_gpio_in(DEVICE(mmio_plic),
QUARD_STAR_UART0_IRQ), 399193, serial_hd(0),
DEVICE_LITTLE_ENDIAN); serial_mm_init(system_memory,
memmap[QUARD_STAR_UART1].base, 0, qdev_get_gpio_in(DEVICE(mmio_plic),
QUARD_STAR_UART1_IRQ), 399193, serial_hd(1),
DEVICE_LITTLE_ENDIAN);

其中,qdev_get_gpio_in函数用来配置串口中断信号,必须要添加中断控制器相关的函数才能正确使用串口。

二、添加中断控制器:

外设是需要中断器的,所以说中断控制器是必不可少的。

RISCV标准的中断控制器分为两部分内核中断CLINT(Core
Local Interrupt)和外设中断控制器Platform-Level Interrupt
Controller(PLIC),CLINT在每一个smp架构下每个core都各有自己私有的中断,PLIC则是所以core共用的外部中断控制器。

[SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },

[SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },

在初始化函数内,分别使用下面的两个函数创建相关的ip,注意要根据内核中smp个数为每个core创建对应的资源。

sifive_clint_create

sifive_plic_create

添加上述ip后,就有了中断控制器和串口,就可以进行简单的串口功能测试,现在需要固件的载体使其工作,这里使用到qemu中对于flash的仿真设备,也就是pflash。

三、添加pflash支持

pflash是并行flash,目前真实的器件已经很少见了,市面上常见的是qspi的nor flash作为低阶固件的载体,而nor flash一般都支持XIP运行,那么基本上等同于pflash了,那么为了方便我们就使用qemu提供的plash作为早期固件的载体。

依然是增加pflash的基地址,这里不是寄存器,而是pflash的数据起始地址,大小是32M,完全足够我们存放固件了。

{

[SIFIVE_U_FLASH] = {

0x20000000, 0x2000000 },

}

创建pflash器件并映射到我们的系统总线对应地址上,最后将其关联到“-drive if=pflash,bus=0,unit=0,…………”的qemu参数上,这样启动仿真时就可以加载固件文件到这片flash上,以下这些代码都不难理解,这里不在赘述

static PFlashCFI01 *sfive_u_flash_create(RISCVVirtState *s,

                                   const

char *name,

                                   const

char *alias_prop_name)

{

DeviceState *dev =

qdev_new(TYPE_PFLASH_CFI01);

qdev_prop_set_uint64(dev,

“sector-length”, QUARD_STAR_FLASH_SECTOR_SIZE);

qdev_prop_set_uint8(dev, "width",

4);

qdev_prop_set_uint8(dev,

“device-width”, 2);

qdev_prop_set_bit(dev,

“big-endian”, false);

qdev_prop_set_uint16(dev, "id0",

0x89);

qdev_prop_set_uint16(dev, "id1",

0x18);

qdev_prop_set_uint16(dev, "id2",

0x00);

qdev_prop_set_uint16(dev, "id3",

0x00);

qdev_prop_set_string(dev, "name",

name);

object_property_add_child(OBJECT(s), name,

OBJECT(dev));

object_property_add_alias(OBJECT(s),

alias_prop_name,

                          OBJECT(dev),

“drive”);

return PFLASH_CFI01(dev);

}

static
void sfive_u_flash_map(PFlashCFI01 *flash,

                        hwaddr base, hwaddr

size,

                        MemoryRegion

*sysmem)

{

DeviceState *dev = DEVICE(flash);

assert(QEMU_IS_ALIGNED(size,

QUARD_STAR_FLASH_SECTOR_SIZE));

assert(size / QUARD_STAR_FLASH_SECTOR_SIZE

<= UINT32_MAX);

qdev_prop_set_uint32(dev,

“num-blocks”, size / QUARD_STAR_FLASH_SECTOR_SIZE);

sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);

memory_region_add_subregion(sysmem, base,

                            sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),

                                                   0));

}

s->flash = sfive_u_flash_create(s, “sifive_u.flash0”, “pflash0”);

pflash_cfi01_legacy_drive(s->flash,
drive_get(IF_PFLASH, 0, 0));

sifiv_u_flash_map(s->flash, virt_memmap[SIFIVE_U_FLASH].base,

                    virt_memmap[SIFIVE_U_FLASH].size, system_memory);
<think>嗯,用户想知道如何在QEMU中配置和使用NorFlash。首先,我需要回顾一下QEMU的设备添加流程,特别是存储设备部分。记得NorFlash属于非易失性存储,通常用于嵌入式系统,所以可能需要使用pflash设备。 首先,QEMU中的pflash设备应该就是模拟NorFlash的。用户之前提到的参考内容里提到添加pflash支持,可能需要通过-drive参数来指定。例如,使用`-drive if=pflash,format=raw,file=...`这样的命令。但具体参数可能需要注意,比如format是否为raw还是其他格式,以及file的生成方式。 然后,可能需要分两种情况:带CFI接口的普通NorFlash和映射到系统地址空间的镜像。对于前者,可能需要指定设备型号,比如`-device pflash1=...`,不过具体的设备名称可能需要查QEMU文档。另外,pflash的镜像文件需要提前准备好,可能需要用dd命令创建空白文件,或者用其他工具生成包含固件的内容。 还有,用户可能需要知道如何验证配置是否成功。例如,在客户机启动后查看dmesg输出,或者通过QEMU monitor的信息。另外,参考引用里提到中断控制器串口添加,但用户的问题集中在NorFlash,所以可能不需要涉及中断部分,但可能需要确保地址空间正确映射,避免冲突。 另外,需要注意QEMU版本不同可能导致参数差异,比如旧版本可能使用不同的选项。可能需要提醒用户根据自己使用的QEMU版本来调整命令。同时,pflash的大小需要符合客户机系统的要求,否则可能导致启动失败。 最后,应该举一个具体的配置示例,帮助用户理解如何组合这些参数。比如启动命令中包含两个pflash设备,一个是BIOS镜像,另一个是系统固件。可能需要解释每个参数的作用,比如if=pflash、unit=0或1的区别,以及如何指定只读或可写属性。 总结步骤应该是:准备镜像文件、编写QEMU启动命令、验证配置。同时提醒常见问题,比如镜像格式、大小,以及地址冲突的可能性。可能还需要提到如何在内核中查看NorFlash设备是否被正确识别,比如通过/proc/mtd或者dmesg日志。</think>### QEMU中配置和使用NorFlash的步骤 在QEMU中,NorFlash通常通过`pflash`设备模拟实现,以下是具体配置方法: --- #### 1. **准备镜像文件** - 使用`dd`命令生成空白镜像文件(例如64MB大小): ```bash dd if=/dev/zero of=norflash.img bs=1M count=64 ``` - 若需预加载固件(如U-Boot),可直接将二进制文件写入镜像: ```bash cp u-boot.bin norflash.img ``` --- #### 2. **QEMU启动命令配置** - **基础配置**:通过`-drive`参数指定pflash设备: ```bash qemu-system-arm -M virt \ -drive if=pflash,format=raw,unit=0,file=u-boot.bin,readonly=on \ -drive if=pflash,format=raw,unit=1,file=norflash.img ``` - `unit=0`:通常用于只读的BIOS/U-Boot镜像[^1]。 - `unit=1`:用于可读写的系统NorFlash存储。 - `format=raw`:指定镜像格式为原始二进制。 - **带CFI接口的NorFlash**(需指定设备型号): ```bash qemu-system-arm -M versatilepb \ -drive if=pflash,format=raw,file=norflash.img \ -device "cfi.pflash01,size=64M" ``` --- #### 3. **验证配置** - **客户机系统内验证**: - 在Linux中检查MTD设备: ```bash dmesg | grep -i "flash" cat /proc/mtd ``` - 若显示类似`mtd0: 00400000 00004000 "norflash"`的条目,则配置成功。 - **QEMU Monitor调试**: - 进入Monitor界面(默认快捷键`Ctrl + A C`),使用`info mtree`查看内存映射,确认pflash地址范围。 --- #### 常见问题 1. **镜像大小不匹配** - 镜像文件需与设备声明的大小一致,否则QEMU会报错`Invalid pflash size`。 2. **地址空间冲突** -pflash的地址与其他设备(如RAM)重叠,需通过`-global driver=property`调整基地址: ```bash -global driver=cfi.pflash01,property=base,value=0x20000000 ``` 3. **只读属性配置** - 对固件镜像添加`readonly=on`,防止客户机意外修改。 --- ### 相关配置示例 ```bash # 启动ARM Virt机器,包含两个pflash设备 qemu-system-arm -M virt -kernel zImage \ -drive if=pflash,format=raw,unit=0,file=u-boot.bin,readonly=on \ -drive if=pflash,format=raw,unit=1,file=app_fw.img \ -append "console=ttyAMA0" ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值