从零开始写bootloader(1)
下面是具体的代码实现:
#define S3C2440_MPLL_200MHZ ((0x5C<<12)|(0x01<<4)|(0x02))
#define MEM_CTL_BASE 0x48000000
.text
.global _start:
_start: /* 关闭看门狗 * /
ldr r0, =0x53000000
mov r1,#0
str r1,[0]
.global _start:
_start: /* 关闭看门狗 * /
ldr r0, =0x53000000
mov r1,#0
str r1,[0]
/* 设置时钟 */
ldr r0,=0x4c000014
mov r1,#0x03; //FCLK:HCLk:PCLK=1:2:4,HDIVN=1,PDIVN=1
str r1,[r0]
/*如果HDIVN非0,CPU的总线模式应该从“fast bus mode ”变为 asynchronous,这是根据数据手册来的,数据手册要求这样做(条件:如果FCLK不等于HCLK的话)*/
mrc p15,0,r1,cl,c0,0 /*读出控制寄存器*/
orr r1,r1,#0xc0000000 /*设置为"asynchronous bus mode"*/
mcr p15,0,r1,c1,c0,0 /*写入控制寄存器*/
/*设置MPLLCON= S3C2440_MPLL_200MHZ*/
ldr r0,= 0x4c000004
ldr r1,= s3c2440_MPLL_200MHZ /*伪汇编指的是在编译时,如果这个值比较复杂的话,那就会将这个值拆分放在内存的某个地方,然后再读那个内存地址*/
str r1,[r0]
/* 初始化SDRAM */
ldr r0,=MEM_CTL_BASE
adr r1,sdram_config /*得到当前地址*/
add r3,r0,#(13*4)
1b:
ldr r2,[r1],#4
str r2,[r0],#4
cmp r0,r3
bne 1b
sdram_config:
.long 0x22011110 //BWSCOON
.long 0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
.long 0x00018005 //BANKCON6
.long 0x008c04F4
.long 0x000000B1 //BANKSIZE
.long 0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
adr r1,sdram_config /*得到当前地址*/
add r3,r0,#(13*4)
1b:
ldr r2,[r1],#4
str r2,[r0],#4
cmp r0,r3
bne 1b
sdram_config:
.long 0x22011110 //BWSCOON
.long 0x00000700 //BANKCON0
.long 0x00000700 //BANKCON1
.long 0x00000700 //BANKCON2
.long 0x00000700 //BANKCON3
.long 0x00000700 //BANKCON4
.long 0x00000700 //BANKCON5
.long 0x00018005 //BANKCON6
.long 0x008c04F4
.long 0x000000B1 //BANKSIZE
.long 0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7
/* 重定位bootloader ,把本身的代码从flash复制到它的链接地址去*/
ldr sp,= 0x34000000
ldr sp,= 0x34000000
bl nand_init /*初始化nandflash*/
mov r0,#0
ldr r1, =_start /*计算需要拷贝的文件的大小*/
ldr r2, =__bss_start
sub r2,r3,r1
mov r0,#0
ldr r1, =_start /*计算需要拷贝的文件的大小*/
ldr r2, =__bss_start
sub r2,r3,r1
bl copy_code_to_sdram /*将代码拷贝到sdram中*/
bl clear_bss /*bss段中的变量都赋值为0,至于为甚麽,我认为是语法的问题*/
/* 执行main */
ldr lr,=halt
ldr pc,=main
halt:
b halt /*假设main函数有返回值的话,一直停在这里,避免单板跑飞。*/
ldr lr,=halt
ldr pc,=main
halt:
b halt /*假设main函数有返回值的话,一直停在这里,避免单板跑飞。*/
void clear_bss(void) /*清除bss段,将这段都赋值为0*/
{
extern int __bss_start,__bss_end;
int *p = &__bss_start;
{
extern int __bss_start,__bss_end;
int *p = &__bss_start;
for(;p < &__bss_end;p++)
*p = 0;
}
*p = 0;
}
void nand_init(void)
{ #define TACLS 0
#define TWTPH0 3
#define TERPH1 0
#define TWTPH0 3
#define TERPH1 0
/*设置时序*/
S3C2440nand->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
/*使能nand flash控制器,初始化ECC,禁止片选*/
s3c2440nand->NFCONT = (1<<4) | (1<<1)| (1<<0);
S3C2440nand->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
/*使能nand flash控制器,初始化ECC,禁止片选*/
s3c2440nand->NFCONT = (1<<4) | (1<<1)| (1<<0);
}
/*nand发出命令函数*/
void nand_cmd(unsigned char cmd)
{
int i;
NFCMMMD cmd;
for (i = 0;i < 10;i++); /*必须等待一会,否则程序会出错*/
}
/*nand发出命令函数*/
void nand_cmd(unsigned char cmd)
{
int i;
NFCMMMD cmd;
for (i = 0;i < 10;i++); /*必须等待一会,否则程序会出错*/
}
/*nand的地址函数*/
void nand_addr(unsigned int addr)
{
unsigned int col = addr /2048;
unsigned int page = addr % 2048;
volatile int i;
void nand_addr(unsigned int addr)
{
unsigned int col = addr /2048;
unsigned int page = addr % 2048;
volatile int i;
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++)
}
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++)
}
/*nand的等待函数*/
void nand_wait_ready()
{
while(!(NFSTAT & 1));
}
/*nand的数据*/
void unsigned char nand_data(void)
{
return NFDATA;
}
/*nand片选函数*/
void nand_select(void)
{
NFCONT &= ~(1<<1);
}
/*取消片选函数*/
void nand_deselect(void)
{
NFCONT |= (1<<1);
}
/*nand的读函数*/
void nand_read(unsigned int addr,unsigned char *buf.unsigned int len)
{
int col = addr /2048; /*col指的是读的是第一页的某个地址,并不是从0开始读的*/
int i = 0;
/*选中*/
nand_select();
while(1)
{/*发出读命令00h*/
nand_cmd(0x00);
/*发出地址(分5步发出)*/
nand_addr(addr);
/*发出读命令*/
nand_cmd(0x30);
/*判断状态*/
nand_wait_ready();
/*读数据*/
for(;col< 2048;&&(i<len);col++)
{
buf[i] = nand_data();
i++;
addr++;
}
col =0;
}
void nand_read(unsigned int addr,unsigned char *buf.unsigned int len)
{
int col = addr /2048; /*col指的是读的是第一页的某个地址,并不是从0开始读的*/
int i = 0;
/*选中*/
nand_select();
while(1)
{/*发出读命令00h*/
nand_cmd(0x00);
/*发出地址(分5步发出)*/
nand_addr(addr);
/*发出读命令*/
nand_cmd(0x30);
/*判断状态*/
nand_wait_ready();
/*读数据*/
for(;col< 2048;&&(i<len);col++)
{
buf[i] = nand_data();
i++;
addr++;
}
col =0;
}
/*取消选中,禁止nandflash发出片选信号*/
nand_deselect();
nand_deselect();
}
posted on 2018-10-10 10:13 xiegangqingnian 阅读(666) 评论(0) 编辑 收藏 举报