文章引自:http://piaoxiang.cublog.cn
现在基本熟悉了
GNU as、ld、objdump、objcopy。可以进行后续的基本实验了。今天把s<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />3c2410的memory controller看了,结合《s3c2410完全开发》实验五,实现了一个sdram的简单实验。源代码如下,下面重点分析s3c2410复位后的内存映射,及其应用。
一、基本配置
EDUKIT-III采用核心子板加扩展板的设计方式,我学习ARM9,所以采用s3c2410的核心子板。核心子板资源如下:
MCU : S3C2410A
SDRAM : 两片HY57V561620CT-H
NOR FLASH: AM29LV160DB-90EC
扩展板资源:
NAND FLASH: K9F5608UOC
二、nand flash boot分析
S3C2410支持从nor/nand flash、eeprom等rom类型的介质启动。现在我想做的是从外部nand flash启动,首先看datasheet第一部分:
NAND Flash Boot Loader | |||||||||||||||
可以明确,首先,s3c2410支持从nand flash存储介质启动,其次,在硬件上,s3c2410除了提供相应的逻辑外,还提供了一个4K的sram作为buffer用于nand启动。最后,s3c2410支持从nand flash启动之后的内存分配形式(也就是说,从nand flash启动之后和从nor flash启动之后的内存分配形式是不同的。s3c2410支持这两种形式,可以说是相对于其他的MCU不同的地方。)
然后看datasheet的第六部分:nand flash controller。overview中首先讲述了用nand flash代替nor flash作为启动介质的原因(成本低)。
可以很明显的看出,s3c2410x启动代码从外部nand flash启动的流程:上电复位后,s3c2410自动读取nand flash的前4KBytes的数据到内部sram buffer中,这个硬件的sram buffer被称为“Steppingstone”。然后执行下载到steppingstone的代码,这部分代码完成将nand flash的内容复制到sdram中,在复制时,利用硬件的ECC验证数据有效性。完成复制后,主程序就开始从sdram执行。
过程应该是很清晰。但是首先怀疑的是,s3c2410如何实现自动读取nand flash的前4KBytes数据到内部sram buffer当中。网上为什么没人就这点产生疑问,并深入分析呢?我分析可能有两种方法:一是像at91rm9200一样,内部集成一个小的rom,固化代码,这部分代码的作用就是完成自动读取功能;二是完全用硬件实现。仔细看了框图,发现s3c2410只有internal sram buffer,并没有rom,所以最大可能就是硬件实现。看一下硬件框图figure6-1,可以发现hardware ECC编解码器,可以看到internal buffer(4KB),另外注意的一个地方是,存在着control state machine和buffer control,而且之间有粗体线链接。也就是说明了用一个控制状态机实现了自动读取4KB数据的过程,完全的硬件实现。如下图所示:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 明确了这个问题之后,对从硬件上电到nand flash启动就比较清晰了。而且,也就理解为什么vivi的stage1的head.S必须要小于4KB,因为internal sram buffer只有4KB。如果要完成一个比较复杂的bootloader,那也应该尽量简化stage1,完成基本的初始化之后,把剩余的工作量都放到将nand flash的代码搬移到sdram之后进行。
三 memory controller分析
看datasheet第五部分。s3c2410比较特殊,支持1G的内存空间,分为8个bank,每个bank128MBytes,128MB×8=1GB。但是在这8个bank中,又有所不同,并且nand flash不对应任何bank,它是通过一组寄存器来访问的,可看上面框图的register bank。
可以推断出,sdram应该在bank6,起始地址固定为128M*6=0x30000000,在此之后,就要根据sdram的大小和位宽来决定了,而且有个注意的地方是,bank7必须和bank6一样大小。参考figure5-1和table 5-1就非常清晰了。现在EDUKIT-III上用了两片SDRAM,型号是HY57V561620CT-H,查看datasheet,它是4banks×4M×16bit=256Mbits=32Mbytes,那么两片组合起来就是64MBytes,位宽是32bit,所以bank6的地址范围是[0x30000000-0x33ffffff],bank7的地址范围是[0x34000000-0x37ffffff]。查看s3c2410 table 5-2,可以知道bank选择地址线为A[25:24]--->BA[1:0]。
关于sdram,还应该知道刷新频率和列宽度。HY57V561620CT-H datasheet中,有:
所以刷新频率为64ms/8192=7.8125us。
查看PIN DESCRIPTION,可以看出A0-A12为地址,其中ROW Address为RA[0:12],Column Address为CA[0-8],显然CAS的位数为9bits。
四、实验内容分析
实验内容很简单,就是完成基本的初始化之后,把steppingstone的4K数据搬移到sdram中。然后在sdram中执行灯循环点亮程序。结合这个实验,也可以很清晰的明白,前面几个基本实验,从nand flash启动后,所有代码只是搬移到了steppingstone中,也就是实际执行时是在steppingstone中,也就是boot internal sram(4KB)中执行的,所以运行时域和加载时域都是0x00000000,设置的堆栈可以是1024,也可以是4096,但是注意一是最大为4096,二是保证不与可执行代码发生冲突。在这个程序中,运行时域和加载时域是不相同的。加载时域是0x00000000,但是运行时域是0x30000000。《s3c2410完全开发》对这个地方讲解不是太详细。经过实验,和王老师的帮助,弄清楚了到底怎么回事。现在关于运行时域和加载时域的具体分析如下:
根据nand flash的特点,初始代码的加载时域为0x00000000,也就是当前PC的值为0x00000000,两种跳转指令b(l)等只能相对寻址,最大范围是+/-32MBytes,所以如果不改变PC的话,不可能能利用b或者bl跳转到sdram的空间中。跳转指令ldr则不受此寻址空间的限制,可以进行绝对寻址。需要了解的一个细节就是,链接后所有的标号都是基于运行地址的,比如运行地址为0x30000000,那么第一个标号_start地址就是0x30000000,所以可以利用ldr的绝对寻址来完成到sdram的跳转。下面根据编写的sdram的反汇编来进行分析:
首先看在不去除符号信息的前提下:
这里是反汇编的结果:
可以很明显的看出,_start为0x30000000,stop为0x30000020。也就是说,经过链接之后,symbol table中的存放位置都是基于运行起始地址0x30000000的。但是需要注意的是,开始运行是PC的值为0x00000000,虽然bl 30000040 <memsetup>是30000040,但是要注意,此处指令为bl,所以只能相对寻址,而不能够绝对寻址,也就是说,它只能跳转到距离0x30000000为0x40的位置,这点查看bl的汇编指令说明就比较清晰了。
利用上面的技巧,就可以把PC的值装载到sdram的空间,因为之前代码搬移已经完成了,所以,后续的工作都已经工作在sdram的空间中了。
如果在利用objcopy去除了符号信息之后,反汇编之后的结果只能是以0开始的相对地址,也就看不出上面的东西了,所以,要理解还应该是采用上面的分析方法。这点在《s3c2410完全开发》上是没有详细说明的。写到这里,自己已经比较清晰了。关于其他的分析,《s3c2410完全开发》已经比较详细了,可以参考。
程序源代码如下:
|
文章评论(0条评论)
登录后参与讨论