(杭州电子科技大学微电子CAD研究所,浙江 杭州310018)
U-boot是目前被广泛采用并支持数十种cpu 架构和400 多种开发板的开源系统[1],被许多学者和公司用于研究和学习,并添加自己编写的代码到u-boot中,如轻量级安全TFTP 协议的研究[2]。但是U-boot 只是给具体架构的cpu 编写配置内存代码,无法判断内存的大小配置是否正确,不具备自动检测系统内存容量的机制。由于不同的系统所使用的内存不同,而大多数系统的解决办法是在U-boot中配置适合自己系统的这一型号的内存。有的在cpu_init.S 文件中增加了适合TQ6410系统的内存识别功能和合适的配置,并没有介绍在不知内存容量的情况下是如何获得内存容量[3]。有的介绍了内存的分布,却没有实现在不同内存容量的条件下U-boot 还能运行的功能[4]。如果将这些U-boot 用到其他不同内存的系统中就无法工作,这导致对U-boot 移植的难度增加了,同时也增加了开发时间并降低了应用的广泛度,基于这一背景,本文介绍了一种自动检测内存容量的机制,根据检测的结果重新配置参数,实现了在不同内存的系统中都可以正常运行和引导操作系统的功能。
目前绝大多数处理器包括arm系列支持外接两片16/32位的存储器。处理器上电后,初始化内存控制器,外设存储器就会映射到处理器内部逻辑空间。自动检测内存容量机制是先假定一个实际内存大小,然后根据这一假设进行内存控制器的配置,接着对存储空间进行访问,根据反馈的信息验证假设是否成立,如果不成立进行下一个假设,直至假设成立。本文以三星S3C6410为例进行说明,S3C6410支持两片外接16/32位的存储器,最大内存为256 MB。首先假设内存是256 MB,并配置DRAM控制器为256 MB 内存的参数。如果内存是128 MB,会出现一种现象:由于XM1_ADDR[13]没有连接,DDR内存的第1个32 MB和第2个32 MB 存储的内容对应相同,第3个32 MB和第4个32 MB 存储的内容对应也是相同,根据这一现象可以推断,一共有2 对相同大小的存储空间的内容互相对应相同。如果内存容量是64 MB,也会有类似的现象:DDR 内存的第1个16 MB、第2个16 MB、第3个16 MB和第4个16 MB 存储的内容对应是相同的;第5个16 MB、第6个16 MB、第7个16 MB和第8个16 MB 存储的内容对应也是相同的,也是2 对相同大小的存储空间的内容互相对应相同。如果XM1_ADDR[13]位连接,内存是256 MB 容量时,没有出现大段内容互相相同的现象。验证这种现象,便能检测出连接的内存容量。以128 MB的内存为例,在U-boot中向内存的第1个32 MB的0x0 地址写一个32 bit的特殊数据0xdeadbeef,接着读取第2个32 MB 对应的偏移内存地址的内容,假如读取的数据和写的数据相同,便说明这两个内存段对应的内容相同。为了避免特殊性(这两个地址的数据本身就是一样的),向第2个32 MB的同一地址处写入另一个数据0xbeefdead,接着读取第1个32 MB 对应的偏移内存地址的内容,假如读写的数据相同,便证明这两个内存段对应的内容相同。
对于OK6410,128 MB 内存用的是两片K4X51163PC 芯片构成一个128 MB的内存;256 MB 内存用的是两片K4X1G163PC 芯片构成一个256 MB的内存。地址线连接如下:
1)128MB 容量的内存。XM1_ADDR[15∶14]([ba1∶ba0]):XM1_ADDR[12∶0](row addr):XM1_ADDR[9∶0](column addr)。XM1_ADDR[15∶14]是芯片选择位,与13位行地址和10位列地址组成寻址为128 MB的内存;
2)256MB 容量的内存。XM1_ADDR[15∶14]([ba1∶ba0]):XM1_ADDR[13∶0](行地址):XM1_ADDR[9∶0](列地址)。XM1_ADDR[15∶14]也是是芯片选择位,与14位行地址和10位列地址组成寻址为256 MB的内存;
内存映射后,如果检测的结果和假设的不同,则要对S3C6410的内存控制器进行重新配置。配置程序要放在启动代码的前4 kB(cpu 片上内存)中,不能放在DDR中,因为内存控制器重新配置后会使得内存无法正常运行。所以配置程序必须存储在U-boot 把自己复制到内存之前的位置,存储在cpu_init.S 文件中能够很好地解决这一问题。cpu_init.S 文件中的内存初始化函数mem_ctrl_asm_init 对DRAM控制器和DDR 做了初始化。识别内存的关键代码如下:
0x50000000是第1个32 MB的起始地址,0x52000000是第2个8 M×32 bit的起始地址,对这个两个地址进行读写,先读它们的内存值,如果内存值不一样,说明这两个区域不是镜像,进入内存识别后的函数mem_rec_end 中处理下一步。但是这两个内存值相同这还不能说明内存是128 MB,因为存在这两个值本身就是相同的情况。继续进行检查分析,将一个比较特殊的数0xdeadbeef 写到地址0x50000000,接着读地址0x52000000,如果地址的内容相同,就证明这两个区域是镜像的,从而证明内存是128 MB,否则就是256 MB。
如果上面的步骤中测试出了镜像的存在,说明假设内存为256 MB是错误的,实际内存为128 MB,之前的内存是根据256 MB 内存配置的,所以必须重新配置内存控制器,配置流程如图1所示。配置内存控制器步骤如下[5]:
1)设置DRAM控制器的状态为paused;
2)循环检测内存状态寄存器P1MEMSTAT 低两位,确认DRAM控制器的状态paused 状态;
3)设置DRAM控制器的状态为config 状态;
4)循环读内存状态寄存器P1MEMSTAT 低两位,确认DRAM控制器的状态config 状态;
5)根据检测结果修改内存配置寄存器;
6)设置DRAM控制器为运行go 状态,重新启动内存;
7)循环读内存状态寄存器P1MEMSTAT 低两位,确认DRAM控制器的状态为ready 状态。
图1 内存控制器配置图
把自动检测内存容量的机制应用在内存为128 MB和256 MB的OK6410 开发板,识别内存容量后,并重新配置内存控制器,系统上电后加载U-boot,U-boot 启动后,内存分布如图2、图3所示。
图2 256 MB 内存空间分布图
图3 128 MB 内存空间分布图
在图2和图3中,图的左边是U-boot 启动后分配的内存地址,格子里面是内存区域存放的代码,图的右边是各区域的代码指针。根据图2和图3可以看出,对于不同容量的内存,U-boot 各段代码代码存放的内存区域不同,根据地址的大小和内存分配可以看出U-boot 已经检测出内存并配置成功,U-boot相同段的内容在容量不同的内存中分配的地址不尽相同。这说明自动检测内存容量的机制应用在容量为128 MB和256 MB 内存的OK6410 开发板是可行的,这个机制是正确的,且该机制的代码只需要不到1 k 字节的存储空间就实现了这一功能。
本文面向U-boot 设计了一种自动检测内存容量大小的机制,并在基于S3C6410的开发板OK6410上进行实例验证。实现这一机制所需要的代码不到1k 字节的存储空间。这一机制使一个U-boot可以支持多个不同内存大小的S3C6410 开发板,减少了开发人员的工作量。
[1]DENX Software Engineering.Das U-Boot[EB/OL].http://en.wikipedia.org/wiki/Das_U-Boot.2013-07-22.
[2]Mohd Anuar Mat Isa,Nur Nabila Mohamed,Habibah Hashim,et al.A lightweight and secure TFTP protocol for smart environment[C].Kota Kinabalu:Computer Applications and Industrial Electronics,2012:302-306.
[3]周健昌,李振兴.基于S3C6410的u-boot 分析与移植[J].电子设计工程,2012,17(20):53-56.
[4]Ding X C,Liao Y G,Fu J G,et al.Analysis of Bootloader and Transplantation of U-boot Based on S5PC100 Processor[C].Hangzhou:Intelligent Human-Machine Systems and Cybernetics.2011:61-64.
[5]Samsung.S3C6410X user's manual Rev 1.20[EB/OL].http://www.Samsungsemi.com.2008-08-22.