17.初始化SDRAM和代码重定位


17.1.代码重定位原理分析
(1)在SRAM中将代码从0xd0020010重定位到0xd0024000,本来代码是运行在0xd0020010的,但是我们又希望代码实际是在0xd0024000位置运行,此刻就需要重定位了,此次重定位实践纯粹是为了练习重定位技能,但某些情况重定位就是必须的,譬如在uboot中。
(2)通过链接脚本将代码链接到0xd0024000;通过dnw下载时将bin文件下载到0xd0020010/BL0直接从SD卡中读取bin文件到0xd0020010处;保证代码实际下载运行在0xd0020010,但一开始就被链接在0xd0024000,从而实现简单的重定位。
(3)我们把代码链接地址设置为0xd0024000(该段代码将来必须放在0xd0024000位置才能正确执行,若实际运行地址不是该地址就要出事(除非代码是PIC位置无关码));重定位代码的实质->在PIC执行完之前(在代码中第1句位置有关码执行之前)必须将整个代码搬移到0xd0024000位置去执行(代码执行时通过代码前段的少量位置无关码将整个代码搬移到0xd0024000;然后使用1个长跳转指令跳转到0xd0024000处的代码继续执行,重定位完成)。
(4)长跳转->首先该行代码是1句跳转指令(ARM中的跳转指令作用类似于分支指令B和BL),跳转指令通过给PC(r15)赋1个新值来完成代码段的跳转执行,长跳转指的是跳转到的地址和当前地址差异比较大,跳转的范围比较宽广;当我们执行完代码重定位后,实际上在SRAM中有2份代码的镜像(1份是我们下载到0xd0020010处开头的,另1份是重定位代码复制到0xd0024000处开头的),这两份内容完全相同,仅仅代码起始地址不同。
(5)短跳转和长跳转的区别->重定位之后使用”ldr-pc,=water_lights”该句长跳转指令从0xd0020010开头的代码处直接跳转到0xd0024000开头的代码的water_lights函数处去执行(实际上在SRAM中有2个water_lights函数镜像,两个都能执行,如果短跳转”bl-water_lights”则执行的是0xd0020010开头的这1份,如果长跳转”ldr-pc,=water_lights”则执行的是0xd0024000开头处的这1份)。
(6)当链接地址和运行地址相同时,短跳转和长跳转实际效果是一样的;但是当链接地址不等于运行地址时,短跳转实际执行的是运行地址处的那1份代码,而长跳转执行的是链接地址处那1份代码。重定位实际就是在运行地址处执行1段位置无关码PIC,让这段PIC(重定位代码)从运行地址处把整个程序镜像拷贝1份到链接地址处,然后使用1句长跳转指令从运行地址处直接跳转到链接地址处去执行同1个函数(water_lights)。


17.2.代码重定位实践
(1)adr与ldr伪指令的区别->ldr和adr都是伪指令,区别是ldr是长加载,adr是短加载(adr指令加载符号地址,加载的是运行时地址;ldr指令加载符号地址,加载的是链接地址)。
(2)重定位(代码拷贝)->重定位的实现即汇编代码中的copy_loop函数,该函数的作用是使用循环结构来逐句复制代码到链接地址;复制的源地址是SRAM的0xd0020010,复制目标地址是SRAM的0xd0024000,复制长度是bss_start减去_start;则复制的长度是整个重定位需要重定位的代码长度,即整个程序中代码段+数据段的长度,bss段(bss段中就是0初始化的全局变量)不需要重定位。
(3)清bss段->清除bss段是为了满足C语言的运行时要求(C语言要求显式初始化为0的全局变量,或者未显式初始化的全局变量的值为0,实际上C语言编译器就是通过清bss段来实现C语言的该特性的);我们的程序在平常是不需要负责清零bss段的(C语言编译器和链接器会帮我们的程序自动添加1段头程序,该段头程序会在我们的main函数之前运行,该段代码就负责清除bss);在我们代码重定位了之后,因为编译器帮我们附加的代码只是帮我们清除了运行地址那1份代码中的bss,而未清除重定位地址处开头的那1份代码的bss,则重定位之后需要自己去清除bss。
(4)长跳转->清理完bss段后重定位就结束了;此时当前运行地址还在0xd0020010开头的(重定位前的)那1份代码中运行着;此时SRAM中已经有了2份代码,1份在d0020010开头,另1份在d0024000开头的位置;然后就要长跳转了(ldr-pc,=water_lights)。


17.3.SDRAM初步引入
(1)SDRAM(同步动态随机存储器);DDR(双倍速度的SDRAM,是SDRAM的升级版,DDR有好多代->DDR1+DDR2+DDR3+DDR4+LPDDR);SDRAM的特性(容量大+价格低+掉电易失性+随机读写+总线式访问);SDRAM/DDR都属于动态内存(相对于静态内存SRAM),都需要先运行初始化代码进行初始化OK后才能正常使用,不像SRAM开机上电后就可以直接运行(类似于SDRAM和SRAM的区别的,还有NorFlash和NandFlash(硬盘))。
(2)SDRAM在系统中属于SoC外接设备;现在还长期在SoC外部的外设为Flash+SDRAM/DDR+网卡芯片如DM9000+音频Codec;SDRAM通过地址总线接口和数据总线接口与SoC通信。
(3)GEC210开发板上的DDR的丝印型号为”K4T1G164QE”(128MB字节);全球做SDRAM的厂商不多,二线厂家做的产品参数都是向一线厂家(三星/KingSton)看齐,目的是兼容一线厂家的设计,然后让在意成本的厂商选择它的内存芯片替代一线厂家的内存芯片;SDRAM的市场特征导致其中比较标准化,大部分时候细节参数官方(芯片原厂)都会提供参考值给你。
(4)K4T1G164QE->K表示三星产品;4表示是DRAM;T表示产品号码;1G表示容量(1Gb=128MB,GEC210开发板上共用了4片相同的内存,总容量=128MB×4=512MB字节);16表示单芯片是16位宽的;4表示是8bank。
(5)核心板原理图中SDRAM相关部分->S5PV210共有2个内存端口(Memory_Port1和Memory_Port2);再结合查阅数据手册中内存映射部分->两个内存端口分别叫DRAM0(内存地址范围0x20000000~0x3FFFFFFF(512MB),对应引脚是Xm1xxxx)和DRAM1(内存地址范围0x40000000~0x7FFFFFFF(1024MB),对应引脚是Xm2xxxx)。
(6)整个210最多支持内存为1.5GB,如果给210更多的内存CPU就无法识别;GEC210开发板上512MB内存的连接方法是在DRAM0端口分布256MB,在DRAM1端口分布256MB;GEC210开发板上内存合法地址为0x20000000~0x2FFFFFFF(256MB)+0x40000000~0x4FFFFFFF(256MB);当板子上DDR初始化完成之后,这些地址都是可以正常使用的。


17.4.SDRAM矩阵式寻址方式
(1)在核心板上的SoC的内存端口(MemoryPort)外设的原理图->每个DDR端口都由3类总线构成=地址总线(XMnADDR0~XMnADDR12共13根地址线)+控制总线+数据总线(XMnDATA0~XMnDATA31共32根数据线)。
(2)GEC210开发板共使用了4片内存(每片1Gb=128MB);每片内存的数据总线都是16位的(单芯片是16位内存);在原理图上横向的2颗内存芯片是并联连接的,并联时地址总线接法一样,但是数据总线要加起来,在逻辑上即可以把这2颗16位的内存芯片看成是1颗32位的内存芯片连接在端口上。
(3)在SDRAM中寻址是首先通过bank寻址线寻址到某个具体的bank;然后在具体的某个bank中再通过行地址(row-address)和列地址(column-address)寻址到某个具体的存储单元(一般的存储单元的大小为4bit/8bit/16bit);行列地址值由相应的地址线引脚分时复用得到。
(4)譬如GEC210中的某块”K4T1G164QE”内存芯片;此芯片有容量为128MB=8bank*16MB=8bank*64Mb*16bit(存储单元为16bit);210的DDR端口信号中有BA0~BA2,接在内存芯片的BA0~BA2上(该3个引脚即”bank寻址线”,用来选择bank);每个bank通过行地址(13位)+列地址(10位)的方式来综合寻址(矩阵式寻址);则一共能寻址的范围->2^13*2^10*16bit=2的24次方;即2^7Mbit=2^4MB(对应16MB(128Mbit)内存)。
(5)参考链接->http://www.crifan.com/summary_embedded_peripherals_sdram/


17.5.汇编初始化SDRAM
(1)汇编初始化SDRAM是通过sdram_asm_init汇编函数在sdram_init.S文件中实现的(汇编实现的函数在返回时需要明确使用返回指令mov-pc,lr);DDR初始化和SoC中的DDR控制器有关;也和开发板使用的DDR芯片有关;也和开发板设计时DDR的连接方式有关。
(2)S5PV210的DDR初始化步骤在SoC数据手册(1.2.1.3-DDR2章节)可知初始化DDR共需27个步骤;GEC210的内存连接方式->在DRAM0上连接256MB+在DRAM1上连接了256MB,则第1部分初始化DRAM0+第2部分初始化DRAM1;我们的代码来源=GEC210开发板官方的uboot源码+参考了GEC210裸机教程中对DDR的初始化+根据自己的理解修改某些参数。
(3)设置IO端口驱动强度->因为DDR芯片和S5PV210之间是通过很多总线连接的,总线的物理表现就是很多个引脚,也就是说DDR芯片和S5PV210芯片是通过一些引脚连接的,DDR芯片工作时需要一定的驱动信号,这个驱动信号需要一定的电平水平才能抗干扰,所以需要设置这些引脚的驱动能力,使DDR正常工作(S5PV210中的DRAM控制器对应的引脚设置为驱动强度2X,这些参数由DDR芯片厂商或者SoC厂商提供,我们一般是参考原厂给的代码)。
(4)DDR配置过程比较复杂,基本上是按照DDR控制器的时序要求来做的,其中很多参数要结合DDR芯片本身的参数来定,还有些参数是时序参数,要去详细计算,所以DDR配置非常繁琐+细致+专业,所以我们只需要学会这种思路和方法,结合文档和代码能看懂,会算一些常见的参数即可(见图1和图3)。


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值