启动
汇编文件:
#define S3C2440_MPLL_200MHZ ((0x5c<12)|(0x01<4)|(0x02))
#define S3C2440_MPLL_400MHZ ((0x5c<12)|(0x01<4)|(0x01))
#define MEM_CTL_BASE 0x48000000
.text
.global _start
_start:
// 1、关看门狗 //
ldr r0, =0x53000000
mov r1, #0
str r1, [r0]
// 2、设置系统时钟 //
ldr r0, =0x4c000014
//mov r1, #0x03 // FCLK:HCLK:PCLK=1:2:4, HdivN=1,PdivN=1
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0]
// 如果HdivN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” //
mrc p15, 0, r1, c1, c0, 0 // 读出控制寄存器 //
orr r1, r1, #0xc0000000 // 设置为“asynchronous bus mode” //
mcr p15, 0, r1, c1, c0, 0 // 写入控制寄存器 //
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0]
// 启动ICACHE //
mrc p15, 0, r0, c1, c0, 0 @ read control reg
orr r0, r0, #(1<12)
mcr p15, 0, r0, c1, c0, 0 @ write it back
// 3、初始化SDARM //
ldr r0, =MEM_CTL_BASE
adr r1, sdarm_config
add r3, r0,#(13*4)
1:
ldr r2, [r1],#4
str r2, [r0],#4
cmp r0, r3
bne 1b
// 4. 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 //
ldr sp, =0x34000000 //让SP指向最高的内存,栈是往下增长的
bl nand_init //即使是nor启动也要初始化nand flash,因为内核是存在nandflash上面的,还 //要去nandflash上面把内核读出来。
mov r0, #0
ldr r1, =_start //链接地址在链接脚本中注明,即程序运行时应该在的地方,0x33f80000
ldr r2, =__bss_start
sub r2, r2, r1
bl copy_code_to_sdram
bl clear_bss
// 5、执行main函数 //
ldr lr, =halt
ldr pc, =main //跳到main函数中运行,不用bl指令是因为该指令会跳到sdarm中执行
halt:
halt
sdarm_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 00x008C04F4 //REFRESH
.long 00x000000B1 //BANKSIZE
.long 00x00000030 //MRSRB6
.long 00x00000030 //MRSRB7
==============================================================
nand flash初始化文件:
// 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))
void nand_init(void)
{
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
// 设置时序 //
NFCONF = (TACLS<12)|(TWRPH0<8)|(TWRPH1<4);
// 使能NAND Flash控制器, 初始化ECC, 禁止片选 //
NFCONT = (1<4)|(1<1)|(1<0);
}
void nand_select(void)
{
NFCONT &= ~(1<1);
}
void del_select(void)
{
NFCONT |= (1<1);
}
void nand_cmd(unsigned char cmd)
{
volatile int i=0;
NFCMMD = cmd;
for(i=0; i<10; i++);
}
void nand_wait_ready(void)
{
while (!(NFSTAT & 1));
}
unsigned char nand_data(void)
{
return NFDATA;
}
void nand_addr(unsigned int addr)
{
unsigned int col = addr % 2048;
unsigned int page = addr / 2048;
unsigned int i=0;
NFADDR = col & 0xff;
for(i=0; i<10; i++);
NFADDR = (col>>8) & 0xff;
for(i=0; i<10; i++);
NFADDR = page & 0xff;
for(i=0; i<10; i++);
NFADDR = (page>>8) & 0xff;
for(i=0; i<10; i++);
NFADDR = (page>>16) & 0xff;
for(i=0; i<10; i++);
}
//addr--->0,下面的nand_read函数从nand flash的0地址读数据放在buf地方
//buf---->_start 即链接地址在链接脚本中注明,程序运行时应该在的地方,0x33f80000,把程序拷贝过去
//len----->__bss_start-_start
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr 48;
int i = 0;
// 选中片选 //
nand_select();
while(i
{
// 发读命令 //
nand_cmd(0x00);
// 发地址 //
nand_addr(addr);
// 发读命令 //
nand_cmd(0x30);