s5pv210——SD卡启动的细节思考
来源:互联网 发布:大数据时代 txt 久久 编辑:程序博客网 时间:2024/06/08 12:18
以下内容源于朱友鹏《物联网大讲坛》的学习,以及博客http://www.cnblogs.com/biaohc/p/6361662.html的学习整理,如有侵权,请告知删除。
1、首先,通过write2sd.sh将BL1,BL2烧录至SD卡。
(1)脚本内容
#!/bin/shsudo dd iflag=dsync oflag=dsync if=./BL1/BL1.bin of=/dev/sdb seek=1sudo dd iflag=dsync oflag=dsync if=./BL2/BL2.bin of=/dev/sdb seek=45(2)可知sd卡内容分布
2、其次,明确启动的一些细节。
由博客http://blog.csdn.net/oqqhutu12345678/article/details/70120598的地址映射可知:
(1)IROM是64KB的大小,范围为0x0000_0000~0x0000_FFFF,内部存储的是BL0的代码。
(2)IRAM是96KB的大小,范围为0xD000_2000~0xD000_3800,它细分不同用途的存储区。
- BL1存储区(开始地址为0xD002_0010,这地址是BL1的真正地址);
- BL1存储区之前有16字节用于BL1的校验头;
- 外部拷贝函数区(开始地址为0xD003_7F80);
- 中断向量表区(开始地址为0xD003_7400);
(3)SD启动的细节
- 当用SD卡启动时,由于三星开发板用sd卡启动的机制的限定,需要对原来的bin文件(原生的led.bin文件)进行加工(经过mkv210_image.c相关的添加16字节的校验头),得到210.bin文件(包含led.bin文件+16字节校验头);
- 再利用上述脚本进行烧录到SD卡中。
- BL0读取SD卡中的BL1(即210.bin文件,包含led.bin文件+16字节校验头)至ISRAM中以0xD002_000开始的区域;(此时led.bin还是处于0xD002_0010开始的区域)
- BL0根据led.bin文件计算出一个校验checksum,与16字节校验头中的cheksum对比,如果相同则执行BL1,否则不再执行。
- 当利用DWN工具下载时,摆脱了SD卡启动的限制,因此烧录的地址直接为0xD002_0010,烧录的文件是直接的文件bin文件。
(4)也就是说,SD卡启动时,BL0负责将SD卡中的BL1复制到ISRAM中以0xD002_0000开始的区域。
- 换言之,凡是以SD卡作为载体的,都需要对原来的,bin文件进行加工;
- 加工方法是mkv210_image.c相关的添加16字节的校验头操作。
- 执行裸机程序,类似于执行BL1,一般不用到执行BL2(如果BL1的大小超过了16KB,则应该分割成BL1,BL2)。
- 执行裸机程序的过程,和执行uboot的过程(源文档描述的BL1,BL2过程)不一样。
(5)问题
- 为什么将BL1,BL2分别烧录至SD卡的以第1,第45块为始的区域,其他的区域可以吗?(猜想,BL1必须烧录到第1块起始的区域,BL2可以适当位置)
- BL0代码怎样知道BL1代码,BL2代码在SD卡中存储的位置的?BL0怎么知道自己应该复制多少个字节?(猜想,BL1必须烧录到块1起始的区域,因此BL0很容易读取BL1,而由于BL1中有内容提示BL2烧录到了哪个块 ,BL1将到那个区域把BL2复制到内存中。一般我们会规定复制多少个字节?)
- BL0把复制的内容放置哪里?为什么复制到哪里?复制到别处可以吗?怎样体现复制到哪个地点的?(猜想,BL0把内容复制到ISRAM中以0xD002_0000开始的区域,因为BL1存储区里的会被自动执行,所以要复制到该区域,复制到别处就不能执行了。原生程序中BL1阶段的链接脚本地址为0xD002_0010,因此原生的bin会被链接到链接脚本指定的0xD002_0010)。
- 如何将一个大于16kb的裸机程序进行分割成BL1,BL2?(猜想,BL1需要把SRAM给初始化,然后BL1把BL2的内容复制到相应的位置(上面提到的外部拷贝函数区与此有关),然后跳转执行)
3、程序太大,分成BL1,BL2。详见博客http://www.cnblogs.com/biaohc/p/6361662.html
(1)BL0首先从SD卡的第一扇区中复制16KB(即BL1,包括16字节的校验头)到ISRAM中去执行。
- 第一扇区,16KB(默认BL1为16KB的大小);
(2)BL1程序所做的事情(BL1的链接地址为0xD002_0010,这样BL1的运行地址和链接地址是一致的,BL1不存在重定位的问题)
- 开关置锁
- 关看门狗
- 开icache
- 设置栈
- 初始化dram
- 初始化dram以后,再执行sd卡复制函数,把接下来要执行的代码复制到dram中;
- 跳转到内存中去执行接下来的代码即可;
/* * s5pv210裸机实验 * * * */ #define WTCON 0xE2700000#define PS_HOLD_CONTROL 0xE010E81C#define SVC_STACK 0xD0037D80 .global _start_start: //关看门狗 ldr r0, =WTCON ldr r1, =0 str r1, [r0] //PS_HOLD置锁 ldr r0, =0xE010E81C ldr r1, =0x301 ldr r2, [r0] orr r2, r2, r1 str r2, [r0] //开icache mrc p15, 0, r0, c1, c0, 0 //bic r0, r0, #(1<<12) //置0 关icache orr r0, r0, #(1<<12) //置1 开icache mcr p15, 0, r0, c1, c0, 0 //设置栈 ldr sp, =SVC_STACK bl sdram_asm_init//此函数见博文《s5pv210——SDARM的初始化》 bl cpysd_2_dram b .
/ * s5pv210裸机实验 * * sd卡中内容复制到内存中 * */#define CopySDMMCtoMem 0xD0037F98#define MEM_ADDRESS 0x23e00000#define bool intextern void led_blink(void);typedef bool (*CopyFunc_t)(int, unsigned int, unsigned short, unsigned int*, bool);void cpysd_2_dram(void) { //初始化函数指针p1,将0xD0037F98中的值强制类型转换为CopyFunc_t函数类型 CopyFunc_t p1 = (CopyFunc_t)(*(unsigned int*)CopySDMMCtoMem); //初始化函数指针p2, void (*p2)(void) = (void (*)(void))MEM_ADDRESS; // 通道号:0,或者2 // 开始扇区号:45 // 读取扇区个数:40 // 读取后放入内存地址:0x23E00000,注意BL2的链接地址是0x23E00000 // with_init:0 (*p1)(2, 45, 40, (unsigned int*)MEM_ADDRESS, 0); //跳转到0x23e00000内存地址处执行函数 (*p2)(); }
由上面可知,BL1从SD卡哪个块开始拷贝BL2,拷贝多少,都是在拷贝函数中指定的,这很好回答了上面2中的问题。另外,注意BL2的链接地址应该设置为0x23E00000,因为BL1将BL2内容拷贝到了该地址。
疑惑:“将0xD0037F98中的值强制类型转换为CopyFunc_t函数类型”,即0xD0037F98中的值表示的拷贝函数的入口地址。这个拷贝函数是怎样的?
(3)BL2:
/* * s5pv210裸机实验 * * * */ #define WTCON 0xE2700000#define PS_HOLD_CONTROL 0xE010E81C#define SVC_STACK 0xD0037D80 .global _start_start: bl led_blink b .
/* * s5pv210裸机实验 * * LED流水灯 * */ #define _REG_GPJ0CON *((unsigned int*)0xE0200240)#define _REG_GPJ0DAT *((unsigned int*)0xE0200244)#define _REG_GPD0CON *((unsigned int*)0xE02000A0)#define _REG_GPD0DAT *((unsigned int*)0xE02000A4)void delay(void);void led_blink(void){ //GPJ03、4、5设置为output模式 _REG_GPJ0CON = 0x11111111; //GPD0 1设置为输出模式 _REG_GPD0CON &= ~(0xF << 4); _REG_GPD0CON |= (0x1 << 4); while (1) { //led4 暗 _REG_GPD0DAT |= (1<<1); //暗 //GPJ03、4、5输出低电平为亮 //led1 亮 _REG_GPJ0DAT = ((0<<3) | (1<<4) | (1<<5)); //延时 delay(); //led2 亮 _REG_GPJ0DAT = ((1<<3) | (0<<4) | (1<<5)); //延时 delay(); //led3 亮 _REG_GPJ0DAT = ((1<<3) | (1<<4) | (0<<5)); //延时 delay(); //关 1 2 3 _REG_GPJ0DAT = ((1<<3) | (1<<4) | (1<<5)); //led4 亮 _REG_GPD0DAT &= ~(1<<1); //亮 //延时 delay(); } }void delay(void){ volatile unsigned int i = 900000; // volatile 让编译器不要优化,这样才能真正的减 while (i--); // 才能消耗时间,实现delay}
总结:
(1)BL1,BL2不同的链接地址(如d0020010 ,23e00000);
(2)BL1运行时,将sd卡中的BL2拷贝到内存23e00000。
- 这里涉及到内存的操作,因此BL1必须先初始化SDRAM;
- 拷贝动作是在BL1中进行的,拷贝完后由函数指针的解引用,实现跳转。这里涉及重定位?
- BL1有一系列初始化。如锁存、cache等。
- s5pv210——SD卡启动的细节思考
- S5PV210的SD卡启动详解1
- S5PV210的SD卡启动详解2
- s5pv210-SD卡启动详解
- S5PV210的SD卡启动实战1~2
- S5PV210 SD卡启动流程分析
- 【S5PV210学习笔记】外插SD卡启动程序失败的解决办法
- S5PV210系列 (裸机十二)之 SD 卡启动详解
- s5pv210-裸机之SD卡
- Beaglebone Black——制作自己的SD启动卡
- Beaglebone Black——制作自己的SD启动卡
- S5PV210的启动过程
- S5PV210的启动过程
- s5pv210的启动过程
- S5PV210的启动顺序
- s5pv210芯片wince6.0系统SD卡启动代码修改过程记录
- s5pv210芯片wince6.0系统SD卡启动代码修改过程记录
- s5pv210-dnw刷机并在uboot命令下破坏iNand使SD卡启动
- XCode5环境下利用crash log调试线上Crash的流程
- bootstrap搜索框button的样式问题
- 移动端如何让页面强制横屏
- 4-4 求自定类型元素的平均 (10分)
- 在R语言中进行局部多项式回归拟合(LOESS)
- s5pv210——SD卡启动的细节思考
- sass 学习笔记(一):嵌套,变量,operation。。。基本就是翻译了一遍官网
- arm64的prefetch/prefetchw/spin_lock_prefetch
- Java中File 类的使用
- 判断APP是否运行在前台
- MPAndroidChart详解
- SecureCRT中文显示乱码问题解决
- 市医院深入开展出院随访工作案例
- Redis实用指令(三)——List