当前位置: 首页 > news >正文

Qemu-NUC980(四):SDRAM Interface Controller

概述

本文描述了980 CPU下SDRAM 接口的qemu框架代码。为了便于阅读,我删除了部分代码,完整的代码请查看文后的工程链接。

添加步骤

1、在include/hw/misc/目录下创建nuc980_sdic.h,如下所示:

+号部分为新增加内容

diff --git a/include/hw/misc/nuc980_sdic.h b/include/hw/misc/nuc980_sdic.h
new file mode 100644
index 00000000..39564fe6
--- /dev/null
+++ b/include/hw/misc/nuc980_sdic.h
@@ -0,0 +1,60 @@
+/*
+ * NUC980 SDRAM Interface Controller emulation.
+ *
+ * Copyright (c) 2025 ~ by yanl1229@163.com.
+ * Written by yanl1229
+ *
+ * This code is licensed under the GPL.
+ */
+#ifndef NUC980_SDIC__H
+#define NUC980_SDIC__H
+
+#include "hw/sysbus.h"
+
+#define SDIC_OPMCTL             0x00
+#define SDIC_CMD                0x04
+#define SDIC_REFCTL             0x08
+#define SDIC_SIZE0              0x10
+#define SDIC_SIZE1              0x14
+#define SDIC_MR                 0x18
+#define SDIC_EMR                0x1c
+#define SDIC_EMR2               0x20
+#define SDIC_EMR3               0x24
+#define SDIC_TIME               0x28
+#define SDIC_DQSODS             0x30
+#define SDIC_CKDQSDS            0x34
+#define SDIC_DAENSEL            0x38
+
+#define SDRAM_BASE      0x0000000
+#define SDRAM_SIZE      (64 *1024 * 1024)
+
+#define SDRAM_SIZE_32M  (0x5 << 0)
+
+#define TYPE_NUC980_SDIC "nuc980-sdic"
+#define NUC980_SDIC(obj) \
+    OBJECT_CHECK(NUC980SDICState, (obj), TYPE_NUC980_SDIC)
+
+typedef struct {
+    /* <private> */
+    SysBusDevice parent_obj;
+
+    /* <public> */
+    MemoryRegion mmio;
+
+    uint32_t sdic_opmctl;
+    uint32_t sdic_cmd;
+    uint32_t sdic_refctl;
+    uint32_t sdic_size0;
+    uint32_t sdic_size1;
+    uint32_t sdic_mr;
+    uint32_t sdic_emr;
+    uint32_t sdic_emr2;
+    uint32_t sdic_emr3;
+    uint32_t sdic_time;
+    uint32_t sdic_dqsods;
+    uint32_t sdic_ckdqsds;
+    uint32_t sdic_daensel;
+
+} NUC980SDICState;
+
+#endif

2、在hw/misc/目录下创建nuc980_sdic.c,如下所示:

+号部分为新增加内容

diff --git a/hw/misc/nuc980_sdic.c b/hw/misc/nuc980_sdic.c
new file mode 100644
index 00000000..488965fe
--- /dev/null
+++ b/hw/misc/nuc980_sdic.c
@@ -0,0 +1,219 @@
+/*
+ * NUC980 SDRAM Interface Controller emulation.
+ *
+ * Copyright (c) 2025 ~ by yanl1229@163.com.
+ * Written by yanl1229
+ *
+ * This code is licensed under the GPL.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "hw/misc/nuc980_sdic.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+
+#ifndef ADC_ERR_DEBUG
+#define ADC_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (ADC_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void nuc980_sdic_reset(DeviceState *dev)
+{......
+}
+
+static uint64_t nuc980_sdic_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{......
+}
+
+static void nuc980_sdic_write(void *opaque, hwaddr addr,
+                                uint64_t val64, unsigned int size)
+{......
+}
+
+static const MemoryRegionOps nuc980_sdic_ops = {
+    .read = nuc980_sdic_read,
+    .write = nuc980_sdic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_nuc980_sdic = {
+    .name = TYPE_NUC980_SDIC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(sdic_opmctl, NUC980SDICState),
+        VMSTATE_UINT32(sdic_cmd,    NUC980SDICState),
+        VMSTATE_UINT32(sdic_refctl, NUC980SDICState),
+        VMSTATE_UINT32(sdic_size0,  NUC980SDICState),
+        VMSTATE_UINT32(sdic_size1,  NUC980SDICState),
+        VMSTATE_UINT32(sdic_mr,     NUC980SDICState),
+        VMSTATE_UINT32(sdic_emr,    NUC980SDICState),
+        VMSTATE_UINT32(sdic_emr2,   NUC980SDICState),
+        VMSTATE_UINT32(sdic_emr3,   NUC980SDICState),
+        VMSTATE_UINT32(sdic_time,   NUC980SDICState),
+        VMSTATE_UINT32(sdic_dqsods, NUC980SDICState),
+        VMSTATE_UINT32(sdic_ckdqsds, NUC980SDICState),
+        VMSTATE_UINT32(sdic_daensel, NUC980SDICState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void nuc980_sdic_realize(DeviceState *dev, Error **errp)
+{
+    NUC980SDICState *s = NUC980_SDIC(dev);
+
+    memory_region_init_io(&s->mmio, OBJECT(s), &nuc980_sdic_ops, s,
+                          TYPE_NUC980_SDIC, 0x1000);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+}
+
+static void nuc980_sdic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = nuc980_sdic_realize;
+    dc->reset = nuc980_sdic_reset;
+    dc->vmsd = &vmstate_nuc980_sdic;
+}
+
+static const TypeInfo nuc980_sdic_info = {
+    .name          = TYPE_NUC980_SDIC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(NUC980SDICState),
+    .class_init    = nuc980_sdic_class_init,
+};
+
+static void nuc980_sdic_register_types(void)
+{
+    type_register_static(&nuc980_sdic_info);
+}
+
+type_init(nuc980_sdic_register_types)

3、修改hw/misc/目录下创建Kconfig,如下所示:

+号部分为新增加内容

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index de6dc940..cc261841 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -131,4 +131,7 @@ config NUC980_SYSconfig NUC980_CLKbool+config NUC980_SDIC
+    bool
+    source macio/Kconfig

4、修改hw/misc目录下创建Makefile.objs,如下所示:

+号部分为新增加内容

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c3c352d5..4c6fbfab 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -85,4 +85,5 @@ common-obj-$(CONFIG_GRLIB) += grlib_ahb_apb_pnp.oobj-$(CONFIG_NUC980_SYS) += nuc980_sys.oobj-$(CONFIG_NUC980_CLK) += nuc980_clk.o
+obj-$(CONFIG_NUC980_SDIC) += nuc980_sdic.o

5、修改hw/arm/目录下创建Kconfig,如下所示:

+号部分为新增加内容

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index db86365b..3d24f9f0 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -117,6 +117,7 @@ config NUC980boolselect NUC980_CLKselect NUC980_SYS
+    select NUC980_SDICconfig NUC980_EVBbool

6、修改hw/arm/目录下创建nuc980_soc.c,如下所示:

+号部分为新增加内容

diff --git a/hw/arm/nuc980_soc.c b/hw/arm/nuc980_soc.c
index 0223d550..1b0a05f2 100644
--- a/hw/arm/nuc980_soc.c
+++ b/hw/arm/nuc980_soc.c
@@ -31,6 +31,9 @@ static void nuc980_init(Object *obj)sysbus_init_child_obj(obj, "clk", &s->clk, sizeof(s->clk), TYPE_NUC980_CLK);/* system manage */sysbus_init_child_obj(obj, "sys", &s->sys, sizeof(s->sys), TYPE_NUC980_SYSTEM);
+    /* sdic*/
+    sysbus_init_child_obj(obj, "sdic", &s->sdic, sizeof(s->sdic), TYPE_NUC980_SDIC);
+}static void nuc980_realize(DeviceState *dev, Error **errp)
@@ -55,6 +58,13 @@ static void nuc980_realize(DeviceState *dev, Error **errp)/* system manage */sysbus_mmio_map(SYS_BUS_DEVICE(&s->sys), 0, SYSTEM_MANAGE_BASE);+    /* sdic */
+    object_property_set_bool(OBJECT(&s->sdic), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdic), 0, SDIC_BASE);}static void nuc980_class_init(ObjectClass *oc, void *data)

7、修改/include/hw/arm/目录下创建nuc980.h,如下所示:

+号部分为新增加内容

diff --git a/include/hw/arm/nuc980.h b/include/hw/arm/nuc980.h
index 353adb72..f24d5a82 100644
--- a/include/hw/arm/nuc980.h
+++ b/include/hw/arm/nuc980.h
@@ -15,6 +15,7 @@#include "hw/misc/nuc980_clk.h"#include "hw/misc/nuc980_sys.h"
+#include "hw/misc/nuc980_sdic.h"#define SDRAM_BASE      0x0000000#define SDRAM_SIZE      (64 *1024 * 1024)
@@ -25,6 +26,8 @@#define SDRAM_SIZE_32M  (0x5 << 0)+#define SDIC_BASE       0xb0002000
+#define TYPE_NUC980 "nuc980"#define NUC980(obj) OBJECT_CHECK(NUC980State, (obj), TYPE_NUC980)@@ -39,6 +42,7 @@ typedef struct NUC980State {NUC980ClockState clk;NUC980SystemState sys;
+    NUC980SDICState sdic;} NUC980State;

总结

本文描述了添加980 CPU中SDRAM Interface Controller的qemu框架代码的添加步骤,在描述过程中,删除了部分代码。

工程链接

https://gitee.com/yanl1229/qemu.git


文章转载自:

http://5dXC1QgQ.khfmq.cn
http://vSPHouoJ.khfmq.cn
http://BtejhHK5.khfmq.cn
http://OufJTAZL.khfmq.cn
http://duHhanen.khfmq.cn
http://Bsyap3wA.khfmq.cn
http://b3nMnHjl.khfmq.cn
http://AaKyonak.khfmq.cn
http://4jr24AR3.khfmq.cn
http://3cTVykXx.khfmq.cn
http://93EzjhXA.khfmq.cn
http://eJNZ0hTT.khfmq.cn
http://fEy7rvdW.khfmq.cn
http://TCDuPSPc.khfmq.cn
http://S85Zxvds.khfmq.cn
http://jihtqNbM.khfmq.cn
http://EwP7A4Ci.khfmq.cn
http://XXGj8ftE.khfmq.cn
http://mvdjfZPo.khfmq.cn
http://Pikuroki.khfmq.cn
http://uLvMNhT7.khfmq.cn
http://fdLz60L8.khfmq.cn
http://zIl7RB3s.khfmq.cn
http://O7v0ZUF4.khfmq.cn
http://GIJMw8Ld.khfmq.cn
http://q1GAMdff.khfmq.cn
http://obJcbB2P.khfmq.cn
http://aamK078m.khfmq.cn
http://wTpwv4Ip.khfmq.cn
http://B0Dl7gar.khfmq.cn
http://www.dtcms.com/a/371028.html

相关文章:

  • 输入1.8~5.5V 输出1A 超级适合软包锂电池产品的DCDC升降压芯片TX4401
  • javascript 国际化方法
  • Spring核心-Bean周期
  • 【Android 消息机制】Handler
  • JobManager 初始化流程解析
  • 天气预报云服务器部署实战
  • 【C++ 双指针技巧】
  • Leetcode77:组合问题
  • Java多线程学习笔记
  • 命令行工具集 CDO 功能总结
  • ​抢占AI搜索新入口:2025年五大专业GEO优化服务商解析
  • 使用Ansible自动化部署Hadoop集群(含源码)--环境准备
  • FlashAttention:突破Transformer内存瓶颈的IO感知革命
  • C++ 并发编程指南 实现无锁队列
  • 制衣跟单高效管理软件推荐
  • lesson55:CSS导航组件全攻略:从基础导航条到动态三级菜单与伸缩菜单实现
  • Typora处理markdown文件【给.md文档加水印】
  • MySQL 视图全方位解析
  • 基于SVN搭建企业内部知识库系统实践
  • 编排与存储
  • Ai8051 2.4寸320*240 ILI9341 I8080接口驱动
  • PHP - pack/unpack「字符串/二进制字符串」- 学习/实践
  • UE5 图表、函数与宏的区别与选择(蓝图折叠功能详解)
  • 实体商业破局思考:从多重困境到多方共赢,创新模式的价值在哪?
  • 中州养老项目:利用Redis解决权限接口响应慢的问题
  • 轻量应用服务器具体指的是什么?
  • 3.进程调度:常见算法
  • LeetCode - 202. 快乐数
  • Docker容器安全最佳实践:镜像扫描、权限控制与逃逸防范
  • 【攻防实战】浅谈Cobalt Strike远控实战