iMX6Q SABRESD 开发板的板载 DDR 内存大小为 1GB 其配套的 codebase 也只针对 1GB 内存大小适配。我们的运行平台上配备了 2GB 内存,直接使用原有 codebase 将只能使用其中一半内存空间。以下将介绍如何让系统识别并使用 2GB 内存。
系统启动过程现象
系统启动过程中可看到 U-Boot 输出如下信息:
1 | U-Boot 2019.10-rc1-00134-gacda5922db-dirty (Mar 16 2020 - 15:27:54 +0800) |
其中 DRAM: 1 GiB
这一行表示 U-Boot 识别到的内存空间大小为 1GB。
进入操作系统之后,终端执行如下命令:
1 | ubuntu@arm:~$ cat /proc/meminfo |
可知操作系统识别到的内存空间大小也是 1GB。
识别内存大小的过程
查看 U-Boot 源码,初始化函数 board_init_f
会执行一系列初始化操作:
1 | if (initcall_run_list(init_sequence_f)) |
init_sequence_f
是一个数组,所有初始化函数都放在这个数组中,其中有2个函数:
1 | static const init_fnc_t init_sequence_f[] = { |
announce_dram_init
函数只有一行代码作用是输出 DRAM:
。真正需要我们关心的是 dram_init
,这个函数继续调用了另一个函数 imx_ddr_size
,接着往下追发现如下注释信息:
1 | /* |
可看到函数 imx_ddr_size
根据 MMDC
的配置返回内存空间大小,配置信息存储在寄存器 MMDC_MDCTL
中。
适配 2GB 内存
从前面的代码中可看到寄存器 MMDC_MDCTL
的地址在定义 MEMCTL_BASE
中,接着查看 MEMCTL_BASE 的定义,可得到如下信息:
1 | MEMCTL_BASE |
所以 MMDC_MDCTL 寄存器地址为 0x021b0000
。此处代码是从寄存器中读取配置的值,那么一定会有其他的代码去配置这个寄存器的值,继续查找可发现:
1 | static int mx6q_dcd_table[] = { |
原始 codebase 中向寄存器 MMDC_MDCTL 配置了值 0x831A0000
以及向寄存器 MMDC_MDASP 配置了值 0x00000027
。
接着从 iMX6Q 芯片参考手册中可查到寄存器 MMDC_MDCTL 数据位的分配:

从而得知原始代码中,寄存器 MMDC_MDCTL 配置的含义为:
- 使能 CS0
- 关闭 CS1
- 行地址宽度 14bit
- 列地址宽度 10bit
- burst 长度 8
- 数据总线大小 64bit
我们运行平台上的内存芯片和 iMX6Q SABRESD 开发板上的内存芯片是一样的封装,只是容量是后者的2倍,也就是行地址宽度
多了1bit,所以将 MMDC_MDCTL 寄存器的值配置为 0x841A0000
。
对于寄存器 MMDC_MDASP
,芯片手册中描述如下:
MMDCx_MDASP[CS0_END] should be set to DDR_CS_SIZE/32MB + 0x7 (DDR base address begins at 0x10000000)
所以寄存器 MMDC_MDASP 的值应该配置为 内存大小/32MB + 0x7
也就是 0x00000047
,最后配置如下:
1 | static int mx6q_dcd_table[] = { |
设备树修改
将 U-Boot 以及内核设备树与内存大小相关的地方修改为 2GB:
1 | memory@10000000 { |
最后,将以上修改保存到设备中,启动系统之后可以看到 U-Boot 以及操作系统均识别到 2GB 内存空间。
总结
本文介绍了 U-Boot 在启动时识别内存大小的过程,以及 iMX6Q 关于内存信息的几个寄存器的配置,最终实现让系统平台识别并且使用 2GB 内存空间。