一、BootLoader的目标是启动内核
1)从Flash上把内核读入内存
a)能读取Flash
b)初始化内存/时钟/其他
2)启动
a)设置参数
b)跳转执行
二、最简单的BootLoader编写步骤
1)初始化硬件、关闭看门狗、设置时钟、设置SDRAM、初始化NAND FLASH。
2)如果BootLoader比较大,需要重定位到SDRAM
3)把内核从NAND FLASH读到SDRAM中
4)设置要传给内核的参数
5)跳转到内核
一>编写程序
1)初始化硬件、关闭看门狗、设置时钟、设置SDRAM、初始化NAND FLASH。——start.S
.text
.globl _start
_start:
/*第一步:关闭看门狗*/
ldr r0, =0x53000000
mov r1, #0
str r1, [r0] /* 看门狗控制器的最低位为0时,看门狗不输出复位信号 */
/*第二步:设置时钟*/
ldr r0, =0x4c000014
mov r1, #0x03 //tFCLK:tHCLK:tPCLK = 1:2:4
str r1, [r0]
//设置异步模式
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]
/*第三步:初始化SDRAM*/
ldr r0, =0x48000000
adr r1, sdram_config /* sdram_config的当前地址 */
add r3, r0, #(13*4)
1:
ldr r2, [r1], #4U-Boot第二阶段代码分析
str r2, [r0], #4
cmp r0, r3
bne 1b
/*第四步:重定位: 把bootloader本身的代码从flash复制到它的链接地址去*/
ldr sp, =0x34000000
bl nand_init
mov r0, #0
ldr r1, =_start
ldr r2, =__bss_start
sub r2, r2, r1
bl copy_code_to_sdram
bl clear_bss
/*第五步:执行main方法*/
ldr lr, =halt
ldr pc, =main
halt:
b halt
dram_config:
.long 0x22011110 //BWSCON
.long 0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
.long 0x00018005 //BANKCON6
.long 0x00018005 //BANKCON7
.long 0x008C04F4 // REFRESH
.long 0x000000B1 //BANKSIZE
.long 0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
j
2)如果BootLoader比较大,需要重定位到SDRAM——init.c
/* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020))
/* GPIO */
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define GPHUP (*(volatile unsigned long *)0x56000078)
/* UART registers*/
#define ULCON0 (*(volatile unsigned long *)0x50000000)
#define UCON0 (*(volatile unsigned long *)0x50000004)
#define UFCON0 (*(volatile unsigned long *)0x50000008)
#define UMCON0 (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028)
#define TXD0READY (1<<2)
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
int isBootFromNorFlash(void){
volatile int *p = (volatile int *)0;
int val;
val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/* 写成功, 是nand启动 */
*p = val;
return 0;
}
else
{
/* NOR不能像内存一样写 */
return 1;
}
}
int cpoy_code_to_sdram(){
int i = 0;
/* 如果是NOR启动 */
if (isBootFromNorFlash())
{
while (i < len)
{
dest[i] = src[i];
i++;
}
}
else
{
//nand_init();
nand_read((unsigned int)src, dest, len);
}
}