S5PV210的启动过程

初步认识IROM和IRAM

S5PV210含有一个内64K的IROM和96K的IRAM,系统启动时主要依靠它们,IROM和IRAM所处的存储空间见下图:

image

S5PV210有IROM,且只能从IROM启动,不再支持原来的直接从外部介质启动方式。
IROM代码(BL0)运行完毕后,根据OM[5:0]确定外部启动介质(BL1和BL2)完成启动。S5PV210支持的外部启动介质包括:NAND Flash、OneNAND、SD/MMC、eMMC、eSSD、UART/USB。

完整的启动序列
系统刚启动时,会运行IROM中的固化代码,进行一些通用的初始化,具体步骤包括:
第一步 关闭看门狗;
第二步 初始化icache;
第三步 初始化堆栈;
第四步 设置时钟;
第五步 判断启动设备(nand/sd/onenand等),检查校验和,然后从启动设备中拷贝前16K的代码到IRAM的0xD0020000处;
第六步 若是安全模式启动,则进行完整性检查;
第七步 跳转到IRAM的0xD0020010地址上继续运行;

UART /USB启动模式
OM[5:4] = 0b10即可选择UART/USB启动模式此时IROM代码运行完毕后,会先尝试从UART 启动,若失败则会尝试从USB启动。若失败则会根据OM[3:0]选择相应的启动介质再次尝试启动。
UART启动时,必须在S5PV210上电前将串口连接好,上位机使用dnw工具来发送启动代码可执行文件。本教材中使用USB启动方式作为调试,因此不详细探讨UART启动方式。
1、USB启动方式必须借助dnw工具,教材中使用dnw v0.60c。
2、打开dnw软件,将dnw中USB下载地址设置为0xd0020010。
3、复位开发板。
4、若是初次使用则Windows会弹出发现新硬件图标,索引安装开发板dnw USB驱动即可。若已经安装驱动,则dnw会显示USB:OK,表示USB连接已经成功。
5、dnw菜单中USB Port->Transmit,选择编译好的bin文件即可。USB download完成后S5PV210会即刻跳转到0xd0020010处执行。

1、// 关闭看门狗
ldr    r0, =0xE2700000
mov    r1, #0
str    r1, [r0]

2、控制icache
// 打开icache可提高运行速度
#ifdef CONFIG_SYS_ICACHE_OFF
// clear bit 12 (I) I-cache 
    bic     r0, r0, #0x00001000
#else 
// set bit 12 (I) I-cache  
    orr     r0, r0, #0x00001000
#endif
    mcr     p15, 0, r0, c1, c0, 0

3、//设置栈
栈的整体作用
1) 保存现场;
2) 传递参数:汇编代码调用C函数时,需传递参数;
3) 保存临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量;

4、重定位代码到IRAM+0x4000
重定位:对于程序而言,我们需要理解两个概念,一是程序当前所处的地址,即程序在运行时,所处的当前地址;二是程序的链接地址,即程序运行时应该位于的运行地址。编译程序时,可以指定程序的链接地址。
对于S5PV210而言,启动时只会从NAND Flash/sd等启动设备中拷贝前16K的代码到IRAM中,那么当我们的程序超过16K怎么办?那就需要我们在前16K的代码中将整个程序完完整整地拷贝到DRAM等其他更大存储空间,然后再跳转到DRAM中继续运行我们的代码,这个拷贝然后跳转的过程就叫重定位。本章中我们主要学习如何重定位,但是并不会涉如何使用到DRAM,而是简单地将代码从IRAM的0xD0020010处拷贝到IRAM的0xD0024000处,然后跳转到0xD0024000处继续运行我们的代码。
链接脚本:链接脚本就是程序链接时的参考文件,其主要目的是描述如何把输入文件中的段(SECTION)映射到输出文件中,并控制输出文件的存储布局。链接脚本的基本命令式SECTIONS命令,一个SECTIONS命令内部包含一个或多个段,段(SECTION)是链接脚本的基本单元,它表示输入文件中的某个段是如何放置的。
链接脚本的标准格式如下:
SECTIONS
{
     sections-command
     sections-command
}
/*link.lds*/
SECTIONS
{
    . = 0xD0024000;
    .text : {
        start.o
        * (.text)
    }   
    .data : {
        * (.data)
    }
    bss_start = .;
    .bss : {
        * (.bss)
    }
    bss_end  = .;   
}
1) 在链接脚本中,单独的点号(.)代表了当前位置,. = 0xD0024000; 表示程序的链接地址是0xD0024000;
2) link.lds中的.text 、 .data 、 .bss分别是text段、data段、bss段的段名(这些段名并不是固定的,是可以随便起的)。.text段包含的内容是start.o和其余代码中所有的text段;.data段包含的内容是代码中所有的data段;.bss段包含的内容是代码中所有的bss段。
3) bss_start和bss_end保存的是bss段的起始地址和结束地址,在start.S中会被用到。

data、text、bss段:
1) data段:数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
2) text段:代码段通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
3) bss段:指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。当我们的程序有全局变量是,它是放在bss段的,由于全局变量默认初始值都是0,所有我们需要手动清bss段。
/*start.S*/
.global _start
_start: 
    // 关闭看门狗  
    ldr    r0, =0xE2700000              
    mov    r1, #0  
    str    r1, [r0]  
    // 设置栈,以便调用c函数  
    ldr    sp, =0xD0037D80   
    // 重定位                           
    // _start当前所位于的地址:0xd0022000  
    adr r0, _start            
    // _start的链接地址:0xd0024000 
    ldr r1, =_start      
    // bss段的起始地址 
    ldr r2, =bss_start  
    cmp r0, r1
    beq clean_bss
copy_loop:  
    ldr r3, [r0], #4    // 源  
    str r3, [r1], #4    // 目的  
    cmp r1, r2  
    bne copy_loop  
// 清bss段
clean_bss:   
    ldr r0, =bss_start                      
    ldr r1, =bss_end  
    cmp r0, r1  
    beq run_on_dram  
    mov r2, #0
    clear_loop:  
    str r2, [r0], #4  
    cmp r0, r1  
    bne clear_loop 
// 跳转
run_on_dram:               
    ldr pc, =main

/*main.c*/
#define     GPJ2CON     (*(volatile unsigned long *) 0xE0200280)
#define     GPJ2DAT        (*(volatile unsigned long *) 0xE0200284)
// 延时函数
void delay(unsigned long count)
{
    volatile unsigned long i = count;
    while (i--);       
}
void main()               
//LED 闪烁
{
    GPJ2CON = 0x00001111;
    // 配置引脚
    while(1)                   
    // 闪烁
    {
        GPJ2DAT = 0;
        // LED on
        delay(0x100000);
        GPJ2DAT = 0xf;
        // LED off
        delay(0x100000);
    }
}

5、重定位代码到DRAM
DRAM0对应的地址是0x2000_0000~0x3FFF_FFF共512M,DRAM1对应的地址是0x4000_000~0x7FFF_FFFF共1G。

代码下载链接:http://download.csdn.net/detail/klcf0220/5508253

喜欢开源,乐意分享的大神们,欢迎加入QQ群:176507146,你值的拥有哦!

作者:快乐出发0220 ;Android群:151319601 ; Linux群:96394158 ;转载请注明出处 http://klcf0220.cnblogs.com/ !!!
原文地址:https://www.cnblogs.com/klcf0220/p/3113695.html