imx6dl芯片手册中内存映射(Memory Maps)章节自我理解


在解析内存映射章节之前,先明确以下几个定义说明

物理地址: CPU地址总线上发出的地址,即CPU进行地址空间寻址的地址(作用:用于cpu地址空间寻址).

物理内存: 主板上的物理内存条所提供的内存空间定义为物理内存(嵌入式中一般指DRAM的空间), 它属于物理地址的一部分, 也就是说每个物理内存单元的实际地址就是物理地址

IO内存: 对外设寄存器的编址方式, 将物理地址的一部分划分出来用作IO地址空间(在这里指, 一类CPU(如Power PC、ARM等)把这些外设寄存器看做是内存的一部分、寄存器参与内存统一编址,通过一般的内存指令来访问这些外设寄存器,称为“I/O内存”), 比如imx6dl中gpio寄存器(0x209c000-0x20b7fff), MMDC寄存器(0x21b0000-0x21b3fff)(这里MMDC是DDR控制器)等等都看成IO内存

虚拟地址: 应用程序看到的内存空间定义为虚拟地址空间, 其地址就叫做虚拟地址. 虚拟地址是硬件MMU与软件内存管理结合的产物,方便更高效率的使用RAM. 即需要MMU(内存管理单元)的支持.

  注意: 不管是在linux还是windows下编程,程序所操作地址都是虚拟地址。

这里以imx6dl芯片为例, imx6dl系统内存映射如下图

 

 从图中可知系统内存映射共4G: 0x00000000 - 0xFFFFFFFF, 即CPU可寻址范围为0 - 4G, 也就是说物理地址为0 - 4G

 物理内存范围是0x10000000 - 0xFFFFFFFF共3G, 即理论上可外接3G内存DDR, 实际接多大看具体应用, 比如外接了1G内存DDR

 IO内存比如GPIO的寄存器范围是0x2090000 - 0x20B7FFF, I2C, SPI, IPU等等IO内存

 这里着重分析下物理内存, 即CPU是如何寻址DDR的, 以下是项目中系统外接了1GB的DDR, 注意下面第一张是CPU内部的DDR控制器, 第二张是DDR(NT5CC256M16DP有DRAM_A14 pin脚, 但是原理图中用的NT5CC128M16DP封装, 所以少了DRAM_A14 pin脚, 实际PCB中DRAM_A14也连接上了DDR控制器, 只是原理图的封装没画出来)

由此可知, DDR控制器外接了两片DDR, DDR型号为NT5CC256M16DP, 硬件连接如下:

第一片16bit DDR3BA0,BA1,BA2连接CPU DDR控制器BA0, BA1, BA2
第二片16bit DDR3 BA0,BA1,BA2连接CPU DDR控制器BA0, BA1, BA2
第一片16bit DDR3A0~A14连接CPU DDR控制器A0~A14
第二片16bit DDR3A0~A14连接CPU DDR控制器A0~A14
第一片16bit DDR3D0~D15连接CPU DDR控制器D0~D15
第二片16bit DDR3D0~D15连接CPUD16~D31

由型号可知一片DDR大小为:4Gbit, 分析如下

有8个banks ---> 3根bank地址线, BA0, BA1, BA2 ---> 8 = 2^3

从datasheet分析有15bit row行地址, 10bit coloumn列地址, 所以每个bank有32M(2^15*2^10)个单元格(基本存储单位), 即每个bank有32M个地址可寻, 且每个单元格占16bit

所以一片DDR共有32M * 8 = 256M个地址可寻

所以一片DDR总大小为32M * 16bit * 8 = 4Gbit

由型号可知一片DDR大小为:4Gbit, 分析如下
bank地址线是3bit所以单个16bit DDR3内部有8个bank(BA0, BA1, BA2 ---> 8 = 2^3)
行地址(row)A0~A14共15bit说明每个bank有2^15行
列地址(column)A0~A9共10bit说明每个bank有2^10列

每个bank有32M(2^15*2^10)个单元格(基本存储单位), 也就是每个bank有32M个地址可寻, 每个bank大小是2^15 * 2^10 * 16bit = 32M * 16bit = 64MB

所以一片DDR共有32M * 8 = 256M个地址可寻

所以单个16bit DDR3芯片容量总大小是32M * 16bit * 8 = 4Gbit

从前面的连线可知两块16bit DDR3的BA0~BA2和A0~A13是并行连接到内存控制器,所以内存控制器认为只有一块内存,访问的时候按照BA0~BA2和A0~A13给出地址。两块16bit DDR3都收到了该地址,给出的反应是要么将给定地址上的2个字节读到数据线上,要么是将数据线上的两个字节写入到指定的地址。

此时内存控制器认为自己成功的访问的了一块32bit的内存,

所以内存控制器每给出一个地址,将访问4个字节的数据,读取/写入。这4字节数据对应到内存控制器的D0~D31,又分别被连接到两片DDR3芯片的D0~D15,这样32bit就被拆成了两个16bit分别去访问单个DDR3芯片的基本存储单元。 所以说这种接法只能4字节(32位)访问(Only 32-bit access is supported), 与GPIO内存映射一样的, 就是说内存访问地址只能+4, 比如GPIO内存地址是0x209c000 -> 0x209c004 -> 0x209c008... 地址只能4字节增加. 这里这种DDR接法也限定了访问内存地址只能4字节增加

注意:尽管每个DDR3芯片识别的地址只有256M(由上面可知2^15 * 2^10 * 8= 256M)个,但由于内存控制器每访问一个内存地址,将访问4个字节数据,所以对于内存控制器来说,能访问的内存大小仍是1GB,只不过在内存控制器将地址传给DDR3芯片时,低两位被忽略,也就是说DDR3芯片识别的地址只有256M个。
比如内存控制器访问地址0x000000000x000000010x000000020x00000003,但对DDR3来说,都是访问地址0x00000000

我们可以通过以下命令获取到内存映射表(其实就是对应用户应用手册中的memory map章节):

cat /proc/iomem

00110000-00111fff : /soc/dma-apbh@00110000          
00120000-00128fff : 120000.hdmi_core
00905000-0091ffff : /soc/sram@00905000
02008000-0200bfff : /soc/aips-bus@02000000/spba-bus@02000000/ecspi@02008000
0200c000-0200ffff : /soc/aips-bus@02000000/spba-bus@02000000/ecspi@0200c000
02020000-02023fff : /soc/aips-bus@02000000/spba-bus@02000000/serial@02020000
02080000-02083fff : /soc/aips-bus@02000000/pwm@02080000
02084000-02087fff : /soc/aips-bus@02000000/pwm@02084000
02088000-0208bfff : /soc/aips-bus@02000000/pwm@02088000
0208c000-0208ffff : /soc/aips-bus@02000000/pwm@0208c000
02090000-02093fff : /soc/aips-bus@02000000/can@02090000
0209c000-0209ffff : /soc/aips-bus@02000000/gpio@0209c000
020a0000-020a3fff : /soc/aips-bus@02000000/gpio@020a0000
020a4000-020a7fff : /soc/aips-bus@02000000/gpio@020a4000
020a8000-020abfff : /soc/aips-bus@02000000/gpio@020a8000
020ac000-020affff : /soc/aips-bus@02000000/gpio@020ac000
020b0000-020b3fff : /soc/aips-bus@02000000/gpio@020b0000
020b4000-020b7fff : /soc/aips-bus@02000000/gpio@020b4000
020c0000-020c3fff : /soc/aips-bus@02000000/wdog@020c0000
020c9000-020c9fff : /soc/aips-bus@02000000/usbphy@020c9000
020ca000-020cafff : /soc/aips-bus@02000000/usbphy@020ca000
020cc034-020cc08b : /soc/aips-bus@02000000/snvs@020cc000/snvs-rtc-lp@34
020e0000-020e3fff : /soc/aips-bus@02000000/iomuxc@020e0000
020ec000-020effff : 20ec000.sdma
020f0000-020f3fff : /soc/aips-bus@02000000/pxp@020f0000
02184000-021841ff : /soc/aips-bus@02100000/usb@02184000
  02184000-021841ff : /soc/aips-bus@02100000/usb@02184000
02184200-021843ff : /soc/aips-bus@02100000/usb@02184200
  02184200-021843ff : /soc/aips-bus@02100000/usb@02184200
02184800-021849ff : /soc/aips-bus@02100000/usbmisc@02184800
02188000-0218bfff : /soc/aips-bus@02100000/ethernet@02188000
02198000-0219bfff : mmc2
0219c000-0219ffff : mmc3
021a0000-021a3fff : /soc/aips-bus@02100000/i2c@021a0000
021a4000-021a7fff : /soc/aips-bus@02100000/i2c@021a4000
021a8000-021abfff : /soc/aips-bus@02100000/i2c@021a8000
021b8000-021bbfff : /soc/aips-bus@02100000/weim@021b8000
021bc000-021bffff : /soc/aips-bus@02100000/ocotp-fuse@021bc000
021d8000-021dbfff : /soc/aips-bus@02100000/audmux@021d8000
021e4000-021e7fff : /soc/aips-bus@02100000/vdoa@021e4000
021ec000-021effff : /soc/aips-bus@02100000/serial@021ec000
021f4000-021f7fff : /soc/aips-bus@02100000/serial@021f4000
02400000-027fffff : 2400000.ipu
10000000-4fffffff : System RAM
  10008000-1088e217 : Kernel code
  108e2000-1099e69b : Kernel data

“System RAM” 就是物理内存(DRAM)的空间, 0x10000000 - 0x4fffffff共1GB(就是实际DRAM接了1GB的内存条)

另注意: 市面上说的手机内存有两种含义, 一种是系统内存RAM, 一种是存储内存ROM, 手机的运行速度跟系统内存RAM大小有关, 而系统存放文件大小跟存储内存ROM有关. 还有系统   内存理论大小跟CPU处理器地址线位宽有关, 比如32位的处理器, 它的理论系统内存可达到4G, 64位的处理器, 他的理论系统内存可达到2^64bit(足够大). 还有就是说手机系统内存4G, 其实手机运行内存肯定不足4G, 因为系统会占用一部分内存(比如外设会占用IO内存), 而真正划分给运行内存的大小(即外接DDR的大小)会小于4G. 因为应用程序代码是运行在DDR上的,所以真正影响手机速度的是运行内存大小.


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM