Smart210启动流程、链接地址、复制代码等,解决串口控制台不好使问题
210串口控制台-问题描述 当210做到串口控制台发现按照视频及210故障分析之后却发现仍然不好使, 这个是因为视频中老师的代码中去除了一部分之前课程中与串口控制台无关部分的代码, 这边正常大家应该会发现,移植内核中printf函数还是会不好使,但是基本的串口打印是正常的, 首先我们先得分析一下这边主要的原因,如果细心的同学应该会发现, 当我们加入内核printf的代码之后,编译出来的档案会大于16K, 我们查找 S5PV210_iROM_ApplicationNote_Preliminary.pdf 这份文件, 可以发现手册中有这个部分的操作顺序,上电之后首先会运行在iROM中BL0里厂商固化好的代码, 并且把用户的BL1部分(只有16K)复制到了SRAM中(起始地址是0xD0020010,其中0xD0020000~0xD0020010是210加头的部份), 按照图中顺序用户应该要在BL1中将BL2(超过16K的部份),自己复制到SRAM中, 整个SRAM中有96K,如果整个Bootloader还超过就要在BL2中将剩馀代码复制到内存SDRAM中, 因此我们发现最大的问题应该就出在BL0只复制16K上,按手册要求,也为了之后的实验, 我们在这里需要把我们的裸机代码分成BL1跟BL2两个部分,这样才能解决不好使的问题 210串口控制台-BL0厂商固化代码 如果你看过答疑助手-许老师的BL1部分代码,你会发现许老师在BL1中根本没有做内存初始化, 直接就使用C语言,我们都知道C语言必须先要设置堆栈指针,而且堆栈指针会指向内存, 但是这个时候我们内存初始化都还没做呢,怎么可能会把指针指向内存, 其实答案就出在BL0厂商固化代码中,210跟2440、6410的启动流程最大不一样的地方, 就在这个BL0厂商固化代码中,首先从手册可以找到这个BL0干了什么 1.关闭看门狗计时器 2.初始化 iCache 3.初始化栈 4.初始化堆 5.初始化块设备复制函数 6.初始化锁相环并且设定系统时钟 7.复制用户代码BL1到SRAM中 8.检查BL1的校验值 9.检查是否为安全启动模式 10.跳转到用户的BL1继续执行 也就是说BL0中其实已经为我们初始化好堆栈了并且可以参考下面的内存地址分布来看一下 210串口控制台-BL1、BL2分别需要完成的代码 知道了BL0都干了什么之后,我们就知道其实BL1中最重要就是把BL2的代码复制到SRAM或者是内存 因为我们的uboot很容易就超过80K所以我们就乾脆不复制到SRAM而直接复制到内存了, 复制到内存之后当然还必须跳转到内存去执行,而BL2就是我们正常的uboot或者是裸机了, 而在BL1中的复制代码首先要考虑的就是从哪里复制、复制到哪里、怎么复制, 下面整理了BL1的这几个问题 1.从哪里复制:我们的代码是下载到nand中的所以当然是从nand复制这个肯定是没问题的, 当然使用nand之前当然得初始化nand 2.复制到哪:这个刚刚已经知道了我们直接复制到内存(SDRAM)中,这个也应该没问题 3.怎么复制: (a)首先按照课程自己初始化nand自己写的复制函数,当然没有问题,但是要注意的是nand的地址, 老师视频中的nand地址的写法是针对块来写的,建议大家可以参考yang的代码按手册按不同的nand, 写成标准的列+行地址的方式 (b)前面我们说到了BL0初始化了一个块设备复制函数,我们可不可以使用呢?当然是可以使用 手册提到了下面的说明 怎么使用呢可以先定义 #define NF8_ReadPage_Adv(a,b,c) (((int(*)(unsigned int, unsigned int, unsigned char*))(*((unsigned int *)0xD0037F90)))(a,b,c)) 然后复制的时候 需要注意的是这个函数的输入部分是数据所在的块跟所在的页,而不是页偏移,因为是块设备复制 (c)另外值得注意的是我们自己写的nand复制函数其实没有考虑过ecc,因为nand存储的数据很容易会出错, 所以nand有个ecc的校验机制,其实我们在看nand的手册仔细点就可以看出端倪, 也就是这个部分,多出的这些字节其实就是存放ecc校验码的,至于算法有兴趣的可以参考yang的代码 最后就是从nand的哪个地址开始复制,首先分为SLC跟MLC两种flash 正常大家应该使用的都是SLC的版本,下一节会提到BL1跟BL2的分割方式, 假设BL1加头之后填充到4K,并且把BL2附加在后面那么实际上就是从nand4K的位置开始复制, 如果BL1加头之后填充到16K,并且把BL2附加在后面那么实际上就是从nand16K的位置开始复制 另外提一下在210手册523页有一个OM脚的变量可以用来判断是怎么启动的 固化代码中还有从SD卡复制代码的函数有兴趣的可以参考yang的代码判断OM假设从SD卡启动, 就从SD卡复制剩下的代码BL2到内存。 210串口控制台-链接地址与BL1、BL2的分割方式 首先我们知道BL1是复制到SRAM中去执行的,在BL1中我们基本上只有在跳转BL2的时候使用绝对跳转, 剩下的地方都不会使用绝对跳转,所以BL1的链接地址实际上没有多大的作用, 而BL2的链接地址因为是跳转到内存中的,并且是我们主要的程序部分, 加上需要处理中段向量,因此这个链接地址就非常重要了, 如果我们的代码最终是复制到0x20008000这个地址并且跳转到这个地址的, 那我们的链接地址就必须是0x20008000,也就是说链接地址与代码实际的地址必须保持一致 至于怎么把代码分割成BL1跟BL2实际上的作法是做两个代码分别编译, 并且保证BL1小于16K,把BL1加头之后扩展到一定的大小,再把BL2附加在BL1后面 BL1的Makefile先把BL1编译之后加头 顶层的Makefile实际上就是把已经加完头的spl_210.bin 扩展成16K,然后再把编译完的BL2, 连接,实际上因为在210的头中有BL1的实际大小,因此如果你的BL1不到16K也就不需要一定得扩展到16K |