uboot之nandflash相关程序解释

本文详细解析了U-Boot在启动过程中针对NAND Flash的处理,包括如何判断启动介质、NAND Flash启动的条件、启动过程中的关键代码分析,以及NAND Flash相关函数的实现,如nand_init、nand_init_chip和nand_read_ll等。内容涵盖从硬件寄存器配置到软件功能实现,深入理解嵌入式系统中NAND Flash启动的流程和技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 在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/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值