Bootloader的启动流程(二)
上次我们的bootloader启动到了函数Main,回顾一下Main前面bootloader的做哪些操作。
首先从地址0x00开始设置arm中的7种异常向量表,系统复位属于复位异常,所以系统启动从复位异常向量0x00位置执行b Reset;
跳转到Reset处执行,关闭watch dog,禁止所有中断,设置系统时钟,等硬件初始化工作,要执行C程序之前要设置栈指针R14(SP),跳转到C程序Main函数。(head.S)
现在来分析下这C函数Main做了些什么事情?
void Main(void)
{
MMU_EnableICache();
MMU_EnableDCache();
Port_Init();
NandInit();
if (g_page_type == PAGE_UNKNOWN) {
Uart_SendString("/r/nunsupport NAND/r/n");
for(;;);
}
GetParameters();
Uart_SendString("load Image of Linux.../n/r");
ReadImageFromNand(); //loader.....
}
函数MMU_EnableICache,MMU_EnableDCache开启指令cache和数据cache。
开启指令cache是设置协处理器cp15的c1寄存器的第12位为1:
static inline void MMU_EnableICache(void)
{
asm (
"mrc p15,0,r0,c1,c0,0/n"
"orr r0,r0,#(1<<12)/n"
"mcr p15,0,r0,c1,c0,0/n"
);
}
开启数据cache是设置协处理器cp15的c1寄存器的第2位为1:
static inline void MMU_EnableDCache(void)
{
asm (
"mrc p15,0,r0,c1,c0,0/n"
"orr r0,r0,#(1<<2)/n"
"mcr p15,0,r0,c1,c0,0/n"
);
}
函数Port_Init(244x_lib.c),初始化GPIO:
void Port_Init(void)
{
GPACON = 0x7fffff;
GPBCON = 0x044555;
GPBUP = 0x7ff; // The pull up function is disabled GPB[10:0]
GPCCON = 0xaaaaaaaa;
GPCUP = 0xffff; // The pull up function is disabled GPC[15:0]
GPDCON = 0x00151544;
GPDDAT = 0x0430;
GPDUP = 0x877A;
GPECON = 0xaa2aaaaa;
GPEUP = 0xf7ff; // GPE11 is NC
GPFCON = 0x55aa;
GPFUP = 0xff; // The pull up function is disabled GPF[7:0]
GPGCON = 1<<8;
GPGDAT = 0;
GPHCON = 0x16faaa;
GPHUP = 0x7ff; // The pull up function is disabled GPH[10:0]
EXTINT0 = 0x22222222; // EINT[7:0]
EXTINT1 = 0x22222222; // EINT[15:8]
EXTINT2 = 0x22222222; // EINT[23:16]
}
设置GPIO寄存器的值,可以查看mini2440的datasheet。像GPACON寄存器宏是定义在s3c2440.h的头文件里,寄存器的地址。