一 在start.S程序中,为了支持nandflash启动,修改&添加了了以下程序
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq clear_bss
/*上面代码判断是否从ram中执行uboot',如果不是,则执行下面代码,判断是从nor启动还是nand启动*/
#define BWSCON 0x48000000
ldr r4, =BWSCON
ldr r4, [r4]
ands r4, r4, #6 //判断BWSCON[2:1]是否为00,如果是,Z=1即跳转到nand_boot
beq nand_boot
通过判断BWSCON来判断是否从nand启动是根据数据手册中的以下内容:
BWSCON的[2:1]位如下
其中的OM[1:0]的作用如下:
OM[2:1]可以通过跳线或者指拨开关来改变电平高低
如果判断不是nand启动,则将执行下面程序,从norflash启动
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
b clear_bss
#define NAND_SECTOR_SIZE_LP 2048
#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1)
nand_boot:
ldr r0, =0x33D00000/*传递给C代码的第一个参数:u-boot在RAM中的起始地址*/
mov r1, #0x0 /*传递给C代码的第二个参数:Nand Flash的起始地址*/
// mov r2, #0x30000 /*传递给C代码的第三个参数:u-boot的长度大小(192k)*/
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
ldr r4, =NAND_BLOCK_MASK_LP
add r2, r2, r4
bic r2, r2, r4//以上两句是将r2中保存的地址转换为以页大小为单位的整数
bl nand_read_ll //执行nand读程序,将nand中的uboot代码读取到ram中指定位置。
cmp r0, #0x0
beq ok_nand_read
bad_nand_read:
/*若nand_read_nll返回错误,则中间两个led点亮*/
loop2:
ldr r0,=GPBDAT
ldr r1,[r0]
bic r1,r1,#((1<<6)|(1<<7))
orr r1,r1,#((1<<5)|(1<<8))
str r1,[r0]
b loop2 //infinite loop
ok_nand_read:
mov r0, #0
ldr r1, =0x33D00000
mov r2, #0x400 //比较1KB数据
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq clear_bss
bne go_next
notmatch:
/*若拷贝到ram中的数据有误,则边上两个led点亮*/
loop3:
ldr r0,=GPBDAT
ldr r1,[r0]
bic r1,r1,#((1<<5)|(1<<8))
orr r1,r1,#((1<<7)|(1<<6))
str r1,[r0]
b loop3 //infinite loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:
str r2, [r0]/* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
/*如果nand拷贝到ram没有问题,则所有led点亮*/
ldr r0,=GPBDAT
ldr r1,[r0]
bic r1,r1,#((1<<6)|(1<<7)|(1<<5)|(1<<8))
/* orr r1,r1,#((1<<5)|(1<<8))*/
str r1,[r0]
二 start_armboot中nand_init函数研究
void nand_init(void)
{
int i;
unsigned int size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);
size += nand_info[i].size / 1024;//这个size是mtd数据的成员变量,调用nand_init_chip函数时,通过nand_info改变
if (nand_curr_device == -1)
nand_curr_device = i;
}
printf("%u MiB\n", size / 1024);//把KB转换为MB单位,将nand的总大小打印出来
}
以上函数中
CONFIG_SYS_MAX_NAND_DEVICE宏指nand设备的数量,移植nand支持时,应该在板子头文件中将其设置为1:
#define CONFIG_CMD_NAND
#define CONFIG_SYS_NAND_BASE 0x4e000000
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define CONFIG_SYS_NAND_MAX_CHIPS 1
(以上几个宏定义是为了添加nand支持在板子头文件中添加的)
nand_info是一个mtd_info类型的数组,数组大小就是上面的宏CONFIG_SYS_MAX_NAND_DEVICE指定。
下面解释一下mtd(百度中找到的)
MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的
memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有源代码在/drivers/