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
}