Qemu-NUC980(一):SOC框架代码添加
概述
从这篇博文开始,作者开始连载NUC980 arm的qemu仿真实现,实现Nuc980 CPU上的大部分控制器的实现,并同时使用FreeRTOS和linux系统来验证qemu nuc980的仿真结果。
添加步骤
1、在include/hw/arm/目录下创建nuc980.h,如下所示:
+号部分为新增加内容
diff --git a/include/hw/arm/nuc980.h b/include/hw/arm/nuc980.h
new file mode 100644
index 00000000..fe7f2270
--- /dev/null
+++ b/include/hw/arm/nuc980.h
@@ -0,0 +1,35 @@
+/*
+ * NUC980 SOC System emulation.
+ *
+ * Copyright (c) 2025- yanl1229@163.com.
+ * Written by yanl1229
+ *
+ * This code is licensed under the GPL.
+ */
+#ifndef NUC980_H
+#define NUC980_H
+
+#include "hw/arm/boot.h"
+#include "exec/memory.h"
+#include "target/arm/cpu.h"
+
+#define SDRAM_BASE 0x0000000
+#define SDRAM_SIZE (64 *1024 * 1024)
+
+#define SDRAM_SIZE_32M (0x5 << 0)
+
+#define TYPE_NUC980 "nuc980"
+#define NUC980(obj) OBJECT_CHECK(NUC980State, (obj), TYPE_NUC980)
+
+typedef struct NUC980State {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ MemoryRegion rom;
+ MemoryRegion ram;
+ /*< public >*/
+ ARMCPU cpu;
+
+} NUC980State;
+
+#endif
\ No newline at end of file
2、在hw/arm/下创建nuc980_soc.c,如下所示:
+号部分为新增加内容
diff --git a/hw/arm/nuc980_soc.c b/hw/arm/nuc980_soc.c
new file mode 100644
index 00000000..3de9d712
--- /dev/null
+++ b/hw/arm/nuc980_soc.c
@@ -0,0 +1,54 @@
+/*
+ * NUC980 SOC System emulation.
+ *
+ * Copyright (c) 2025- yanl1229@163.com.
+ * Written by yanl1229
+ *
+ * This code is licensed under the GPL.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "hw/i2c/i2c.h"
+#include "hw/sysbus.h"
+#include "hw/arm/nuc980.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+#include "hw/qdev-properties.h"
+#include "chardev/char.h"
+
+
+static void nuc980_init(Object *obj)
+{
+}
+
+static void nuc980_realize(DeviceState *dev, Error **errp)
+{
+}
+
+static void nuc980_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = nuc980_realize;
+ dc->desc = "NUVOTON NUC980 SOC";
+ /*
+ * Reason: uses serial_hds in realize
+ */
+ dc->user_creatable = false;
+}
+
+static const TypeInfo nuc980_type_info = {
+ .name = TYPE_NUC980,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(NUC980State),
+ .instance_init = nuc980_init,
+ .class_init = nuc980_class_init,
+};
+
+static void nuc980_register_types(void)
+{
+ type_register_static(&nuc980_type_info);
+}
+
+type_init(nuc980_register_types)
3、在hw/arm/下创建nuc980_evb.c,如下所示:
+号部分为新增加内容
diff --git a/hw/arm/nuc980_evb.c b/hw/arm/nuc980_evb.c
new file mode 100644
index 00000000..f3aa6d32
--- /dev/null
+++ b/hw/arm/nuc980_evb.c
@@ -0,0 +1,63 @@
+/*
+ * NUC980 evb board System emulation.
+ *
+ * Copyright (c) 2025- yanl1229@163.com.
+ * Written by yanl1229
+ *
+ * This code is licensed under the GPL.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "hw/arm/nuc980.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
+
+#define SRAM_BASE 0x3c000000
+#define SRAM_SIZE 0x4000
+
+typedef struct NUC980EVBBoard {
+ NUC980State soc;
+ MemoryRegion sdram;
+ MemoryRegion sram;
+} NUC980EVBBoard;
+
+static struct arm_boot_info nuc980_evb_binfo;
+
+static void nuc980_evb_init(MachineState *machine)
+{
+ NUC980EVBBoard *s = g_new0(NUC980EVBBoard, 1);
+
+ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
+ TYPE_NUC980, &error_abort, NULL);
+
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
+
+ machine->ram_size = SDRAM_SIZE;
+ memory_region_allocate_system_memory(&s->sdram, NULL, "nuc980_evb.sdram",
+ machine->ram_size);
+ memory_region_add_subregion(get_system_memory(), SDRAM_BASE, &s->sdram);
+
+
+ memory_region_allocate_system_memory(&s->sram, NULL, "nuc980_evb.sram",
+ SRAM_SIZE);
+ memory_region_add_subregion(get_system_memory(), SRAM_BASE, &s->sram);
+
+ nuc980_evb_binfo.ram_size = machine->ram_size;
+ nuc980_evb_binfo.loader_start = SDRAM_BASE;
+ nuc980_evb_binfo.board_id = 4577,
+ nuc980_evb_binfo.nb_cpus = 1;
+ arm_load_kernel(&s->soc.cpu, machine, &nuc980_evb_binfo);
+}
+
+static void nuc980_evb_machine_init(MachineClass *mc)
+{
+ mc->desc = "NUVOTON NUC980 EVB board (ARM926EJ-S)";
+ mc->init = nuc980_evb_init;
+ mc->block_default_type = IF_SD;
+ mc->ignore_memory_transaction_failures = true;
+}
+
+DEFINE_MACHINE("nuc980-evb", nuc980_evb_machine_init)
\ No newline at end of file
4、在default-configs/arm-softmmu.mak文件中,加入nuc980平台的编译,如下所示:
+号部分为新增加内容
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 1f2e0e7f..38b3ee26 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -40,3 +40,4 @@ CONFIG_FSL_IMX25=yCONFIG_FSL_IMX7=yCONFIG_FSL_IMX6UL=yCONFIG_SEMIHOSTING=y
+CONFIG_NUC980_EVB=y
5、在hw/arm/Kconfig中添加nuc980的配置选项
+号部分为新增加内容
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index c6e77825..2a604c83 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -113,6 +113,13 @@ config NSERIESselect TWL92230 # energy-managementselect TUSB6010+config NUC980
+ bool
+
+config NUC980_EVB
+ bool
+ select NUC980
+
6、在hw/arm/Makefile.objs中,加入nuc980的编译,如下所示:
+号部分为新增加内容
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index fe749f65..8ba9d64d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -10,6 +10,8 @@ obj-$(CONFIG_INTEGRATOR) += integratorcp.oobj-$(CONFIG_MAINSTONE) += mainstone.oobj-$(CONFIG_MICROBIT) += microbit.oobj-$(CONFIG_MUSICPAL) += musicpal.o
+obj-$(CONFIG_NUC980) += nuc980_soc.o
+obj-$(CONFIG_NUC980_EVB) += nuc980_evb.oobj-$(CONFIG_NETDUINO2) += netduino2.oobj-$(CONFIG_NSERIES) += nseries.oobj-$(CONFIG_SX1) += omap_sx1.o
7、编译运行
添加完后,再qemu源码路径下,执行:
./configure --target-list=arm-softmmu
make && sudo make install
8、执行 qemu-system-arm -M ? 就可以看到新增加的980平台
总结
本文主要描述了nuc980的qemu soc框架代码的添加,感兴趣的同学可以在ubuntu 20.04系统上进行下载和编译验证。
工程链接
https://gitee.com/yanl1229/qemu.git