S5pv210——SD卡重入
1:s5pv210启动原理:s5pv210启动的时候首先查看OMpin设置的启动方式,如果设置为SDMMC启动的话,首先从SD的通道1启动,但是通道1连接的是iNand,如果iNand中启动不了,
则从SD卡的通道2启动,sd卡通道2连接外置的sd卡,BL0首先从sd卡的第一扇区中复制16kb到sram中去执行(包括16字节的校验头),
所以BL1所做的事情:
(1) 开关置锁
(2) 关看门狗
(3) 开icache
(4) 设置栈
(5) 初始化dram
(6) 初始化dram以后,在执行sd卡复制函数,把接下来要执行的代码复制到dram中;
(7) 跳转到内存中去执行接下来的代码即可;
代码实战:
BL1:
(1) 开关置锁
(2) 关看门狗
(3) 开icache
(4) 设置栈
(5) 初始化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
    
    
    bl cpysd_2_dram
    
    b .
(6) 初始化dram以后,在执行sd卡复制函数,把接下来要执行的代码复制到dram中;
(7) 跳转到内存中去执行接下来的代码即可;
/* * s5pv210裸机实验 * * sd卡中内容复制到内存中 * */ #define CopySDMMCtoMem 0xD0037F98 #define MEM_ADDRESS 0x23e00000 #define bool int extern 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; //将sd扇区45中的内容复制到内存0x23e00000内存位置中 (*p1)(2, 45, 40, (unsigned int*)MEM_ADDRESS, 0); //跳转到0x23e00000内存地址处执行函数 (*p2)(); }
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
}
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号