2010.06在unsp2440上的移植(2)

一、 步骤三:U-boot支持NAND启动

经过前两步我们的开发板已经支持了u-boot的NOR启动,在嵌入式开发中,由于nor FLASH的速度及容量上的原因,经常被NAND所替代,下面我们研究一下怎么从NAND上启动我们的u-boot

因为我们改过的代码需要在拷贝之前调用一段C程序,所以需要把对栈空间的初始化放在拷贝之前。

/* Set up the stack*/ 从后面移到前面,因为我们在后面的程序中需要调用C语言程序,所以在这里需要提前初始化栈空间

stack_setup:

。。。。。。。

bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate: /* relocate U-Boot to RAM */

adr r0, _start

ldr r1, _TEXT_BASE

cmp r0, r1

/*根据启动代码的实际地址与链接地址判断是从RAM启动或者FLASH启动*/

beq clear_bss /*从ram启动则继续执行下面的内容*/

ldr r2, _armboot_start

ldr r3, _bss_start

sub r2, r3, r2

#if 1

bl CopyCode2Ram /*调用C语言函数,从FLASH中拷贝镜像,此函数会自动识别是NOR启动还是NAND启动,此函数的实现为boot_init.c,需放在board/Samsung/unsp_2440/目录下*/

#else /*原U-BOOT:从NOR启动*/

add r2, r0, r2

copy_loop:

ldmia r0!, {r3-r10}

stmia r1!, {r3-r10}

cmp r0, r2

ble copy_loop

#endif

#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

 

boot_init.c文件是我们后来增加的文件,在u-boot启动的第一个阶段调用,第一阶段代码通过4k的SRAM运行,因此本函数必须链接到前4k的地址中,否则会调用不到此函数。

为此我们需做以下修改:

修改board/Samsung/unsp_2440/Makefile,在第28行左右的位置修改成以下形式

COBJS := unsp2440.o flash.o boot_init.o

这样就可以把我们编写的boot_init.c文件编译进去。

为了将boot_init.c链接到前4k代码中,我们还需修改以下文件:

arch/arm/cpu/arm920t/u-boot.lds u-boot的链接文件

.text :

{

     arch/arm/cpu/arm920t/start.o (.text)

     board/samsung/unsp2440/lowlevel_init.o(.text)

     board/samsung/unsp2440/boot_init.o(.text)

     *(.text)

}

 

将lowlevel_init.S跟boot_init.c文件均链接到前4K SRAM中。

我们可以重新编译并下载到开发板中,将开发板调到NAND启动,观察能否启动起来。

二、 步骤四:U-boot支持NAND操作

在上一节中我们说过,通常在嵌入式bootloader中,有两种方式来引导启动内核:从Nor Flash启动和从Nand Flash启动,但不管是从Nor启动或者从Nand启动,进入第二阶段以后,两者的执行流程是相同的。

当u-boot的start.S运行到“_start_armboot: .word start_armboot”时,就会调用lib_arm/board.c中的start_armboot函数,至此u-boot正式进入第二阶段。

此时注意:以前较早的u-boot版本进入第二阶段后,对Nand Flash的支持有新旧两套代码,新代码在drivers/nand目录下,旧代码在drivers/nand_legacy目录 下,CFG_NAND_LEGACY宏决定了使用哪套代码,如果定义了该宏就使用旧代码,否则使用新代码。

但是现在的u-boot-2010.6版本对 Nand的初始化、读写实现是基于最近的Linux内核的MTD架构,删除了以前传统的执行方法,使移植没有以前那样复杂了,实现Nand的操作和基本命令都直接在drivers/mtd/nand目录下。

下面我们结合代码来分析一下u-boot在第二阶段的执行流程。

1. lib_arm/board.c文件中的start_armboot函数调用了drivers/mtd/nand/nand.c文件中的nand_init函数,如下:

#if defined(CONFIG_CMD_NAND)

//可以看到CONFIG_CMD_NAND宏决定了Nand的初始化

puts ("NAND: " ) ;

nand_init();

#endif

2.nand_init调用了同文件下的nand_init_chip函数;

3.nand_init_chip函数调用drivers/mtd/nand/s3c2410_nand.c文件下的board_nand_init函数,然后再调用drivers/mtd/nand/nand_base.c函数中的nand_scan函数;

4.nand_scan函数调用了同文件下的nand_scan_ident函数等

 

因为2440和2410对nand控制器的操作有很大的不同,所以s3c2410_nand.c下对nand操作的函数就是我们做移植需要实现的部分了,他与具体的Nand Flash硬件密切相关。

为了区别与2410,这里我们就重新建立一个s3c2440_nand.c文件,在这里面来实现对nand的操作,代码参见S3c2440_nand.c:

s3c2440_nand.c

其次,在开发板配置文件include/configs/my2440.h文件中定义支持Nand操作的相关宏,如下:

/* Command line configuration. */

#define CONFIG_CMD_NAND

#define CONFIG_NAND_S3C2440 1

#define CONFIG_CMDLINE_EDITING

#ifdef CONFIG_CMDLINE_EDITING

    # undef CONFIG_AUTO_COMPLETE

#else

    #define CONFIG_AUTO_COMPLETE

#endif

/* NAND flash settings */

#if defined(CONFIG_CMD_NAND)

     #define CONFIG_SYS_NAND_BASE 0x4E000000 //Nand配置寄存器基地址

     #define CONFIG_SYS_MAX_NAND_DEVICE 1

    #define CONFIG_MTD_NAND_VERIFY_WRITE 1

     //#define NAND_SAMSUNG_LP_OPTIONS 1 //注意:我们这里是64M的Nand Flash,所以不用,如果是128M的大块Nand Flash,则需加上

#endif

 

然后,在drivers/mtd/nand/Makefile文件中添加s3c2440_nand.c的编译项,如下

# gedit drivers/mtd/nand/Makefile

COBJS- y + = s3c2440_nand.o

COBJS- $ ( CONFIG_NAND_S3C2440) + = s3c2440_nand. o

 

重新编译,将u-boot烧入NAND FLASH,并敲入help,可以看到有关NAND FLASH操作的命令已经可以使用。

在启动过程中,我们可以看到一个警告信息:“*** Warning - bad CRC or NAND, using default environment”,这是因为我们还没有将u-boot的环境变量保存nand中的缘故,那现在我们就用u-boot的saveenv命令将环境变量保存在NAND FLASH中,如下:

#ifdef CONFIG_CMD_NAND

      #define CONFIG_ENV_IS_IN_NAND 1

      #define CONFIG_ENV_OFFSET 0x30000 //将环境变量保存到nand中的0x30000位置

      //注意这个地址不要跟bootloader等其它分区冲突

       #define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */

#else

        #define CONFIG_ENV_IS_IN_FLASH 1 //将环境变量存入norflash中

        #define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */

#endif

 

重新编译下载上述警告���失,我们可以使用saveenv将环境变量的值存入NAND FLASH中。

为了测试NAND驱动移植是否成功,我们使用loady命令配合nand命令完成相关测试。

修改include/configs/unsp2440.h中

#define CONFIG_SYS_PROMPT "unsp2440 # " /* Monitor Command Prompt */

重新编译生成u-boot

#loady 0x33000000                                      //采用ymodem协议从串口下载u-boot镜像到0x33000000中

#nand erase 0x0 0x30000                            //擦除0x0到0x30000的FLASH地址

#nand write 0x33000000 0x0 0x30000   //将0x33000000中数据烧进NAND的0x0到0x30000中

 

重启开发板,观察提示符由smdk2410变为 unsp2440#,说明我们对NAND FLASH驱动的修改成功了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwyspw.html