FL2440的U-boot-2010.09移植六NAND Flash启动支持

 从NAND Flash启动的原理很简单,就是利用S3C2440内部4K大小的SRAM,存储在NAND Flash中的代码不能被执行,而S3C2440在从NAND Flash启动把NAND Flash的前4k代码复制到SRAM中运行,U-boot支持从NAND Flash启动的方法就是利用这前4K代码完成SDRAM的初始化(SDRAM有64M),然后还要完成从U-boot代码从NAND Flash中复制到SDRAM中,然后再跳转到SDRAM中去运行完整的U-boot。

      为了便于系统启动的方便,可以在start.S文件添加代码以识别系统是从NAND Flash启动还是从nor Flash启动,从S3C2440芯片手册中可以看到

到OM[1:0]都为0时,说明是从NAND Flash启动,01和10都是从nor Flash启动,OM[1:0]就是寄存器BWSCON的第2位~第1位(DW0)

一、添加nor Flash启动和NAND Flash启动的识别

修改arch/arm/cpu/arm920t/start.S,首先将217行附近修改为:

[cpp]  view plain copy
  1. #ifndef CONfig_SKIP_LOWLEVEL_INIT  
  2.     bl  cpu_init_crit  
  3. #endif  
  4.   
  5. #define BWSCON 0x48000000  
  6.         ldr     r0, =BWSCON  
  7.         ldr     r0, [r0]  
  8.         ands    r0, r0, #0x6  
  9.         tst     r0, #0x0  
  10.         bne     norflash_boot             /*OM[1:0] != 0, 跳转nor FLASH 启动处*/  
  11. /*判断uboot是从nand flash启动还是从 nor flash启动*/  

在220行附近将:

  • #ifndef CONfig_SKIP_RELOCATE_UBOOT  
  • relocate:  
  • 修改

    [html] 
  • norflash_boot:  
  • #ifndef CONfig_SKIP_RELOCATE_UBOOT  
  • relocate:  
  • 二、添加NAND Flash的U-boot代码从NAND FLash到SDRAM搬移的代码
    在前面修改的 bne norflash_boot ,227行后添加

  • /*****************************nand boot**************************/  
  • nandflash_boot:  
  • #define LENGTH_UBOOT 0x40000  
  • #define NAND_CTL_BASE 0x4e000000  
  • #define oNFCONF 0x00  
  • #define oNFCONT 0x04  
  • #define oNFCMD  0x08  
  • #define oNFSTAT 0x20  
  •   
  •         @reset NAND  
  •         mov     r1,#NAND_CTL_BASE  
  •         ldr     r2,=((7<<12)|(7<<8)|(7<<4))  
  •         str     r2,[r1,#oNFCONF]  
  •         ldr     r2,#oNFCONF]  
  •           
  •         ldr     r2,=((1<<4)|(1<<1)|(1<<0)) @Active low CE control  
  •         str     r2,#oNFCONT]  
  •         ldr     r2,#oNFCONT]  
  •           
  •         @ get read to call C functions  
  •         ldr     sp,DW_STACK_START   @setup stack point  
  •         mov     fp,#0               @no prevIoUs frame, so fp = 0  
  •           
  •         @copy Uboot to ram  
  •         ldr     r0, =TEXT_BASE  
  •         mov     r1,#0x0  
  •         mov     r2,#LENGTH_UBOOT  
  •         bl      nand_read_ll  
  •         tst     r0,#0x0  
  •         beq     ok_nand_read  
  •   
  • bad_nand_read:  
  • loop2:  
  •         b       loop2     @infinite loop  
  •   
  • ok_nand_read:  
  •         @verify  
  •         mov     r0,#0  
  •         ldr     r1,=TEXT_BASE  
  •         mov     r2,#0x400     @ compare 4k code from sram to sdram  
  •   
  • go_next:  
  •         ldr     r3, [r0], #4  
  •         ldr     r4, [r1], #4  
  •         teq     r3, r4  
  •         bne     notmatch  
  •         subs    r2,r2,#4  
  •         tst     r2,#0x0   @do not forget the instruction if have not this command the uboot can't break the loop  
  •         beq     stack_setup  
  •         bne     go_next  
  •   
  • notmatch:  
  • loop3:  
  •         b       loop3 @infinite loop  
  • /*****************************nand boot**************************/  
  • 上面这部分代码首先初始化了NAND Flash寄存器,然后进行了一个函数调用(这个函数中完成了代码搬移)后面则是对复制出来的数据进行一个简单的校验。在327行附近添加为:

  • _start_armboot: .word start_armboot  
  • #define  STACK_BASE 0x33f00000  
  • #define  STACK_SIZE 0x10000  
  •         .align 2  
  • DW_STACK_START: .word STACK_BASE+STACK_SIZE-4  
  • 添加函数的栈调用空间

    三、添加C语言从NAND Flash搬移代码部分

    首先在board/fl2440目录下新建一个名为nand_read.c的文件,其内容如下:

    /*  
  •  * vivi/s3c2410/nand_read.c: Simple NAND read functions for booting from NAND 
  •  * 
  •  * copyright (C) 2002 MIZI Research, Inc. 
  •  * Author: Hwang, Chideok <[email protected]> 
  •  * Date  : $Date: 2002/08/14 10:26:47 $ 
  •  * 
  •  * $Revision: 1.6 $ 
  •  * $Id: param.c,v 1.9 2002/07/11 06:17:20 nandy Exp  
  •  */  
  •   
  • #include <config.h>  
  •   
  • #define __REGb(x)   (*(volatile unsigned char *)(x))  
  • #define __REGi(x)   (*(volatile unsigned int *)(x))  
  • #define NF_BASE     0x4e000000  
  •   
  • /*S3C2440与S3C2440 nandflash控制寄存器地址不同需要进行修改*/  
  • #define NFCONF      __REGi(NF_BASE + 0x0)  
  • #define NFCONT          __REGi(NF_BASE + 0x4)  
  • #define NFCMD       __REGb(NF_BASE + 0x8)  
  • #define NFADDR      __REGb(NF_BASE + 0xc)  
  • #define NFDATA      __REGb(NF_BASE + 0x10)  
  • #define NFSTAT      __REGb(NF_BASE + 0x20)  
  •   
  • #define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))  
  • #define NAND_CHIP_disABLE (NFCONT |= (1<<1))  
  • #define NAND_CLEAR_RB (NFSTAT |= (1<<2))  
  • #define NAND_DETECT_RB {while(! (NFSTAT&(1<<2)));}  
  • #define NAND_ECC_CLEAR (NFCONT |= 0x10)  
  • /*see data sheet P193*/  
  •   
  • #define BUSY 1  
  • static inline void wait_idle(void) {  
  •     int i;  
  •     while(!(NFSTAT & BUSY))  
  •       for(i=0; i<10; i++);  
  • }  
  •   
  • /*根据fl2440的nand flash 作相应修改*/  
  • #define NAND_SECTOR_SIZE    2048  
  • #define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)  
  •   
  • /* low level nand read function */  
  •  int  
  • nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)  
  • {  
  •     int i, j;  
  •     int pagenum;  
  •   
  •     if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {  
  •         return -1;  /* invalid alignment */  
  •     }  
  •   
  •     /* chip Enable */  
  •     NAND_CHIP_ENABLE;  
  •       
  •     for(i = start_addr; i < (start_addr + size);) {  
  •       /* READ0 */  
  •   
  •       NAND_CLEAR_RB;  
  •       for(j = 0; j < 10; j++);  
  •         
  •       pagenum = i >> 11;  
  •       /* Write Address  
  •         该步骤详见nand flash(k9f2g08u0a)手册p17 
  •         参考fl2440开发板nand_lowlevel.c文件中ReadPage函数 
  •       */  
  •       NFCMD = 0x0;  
  •         
  •       NFADDR = 0;  
  •       NFADDR = 0;  
  •       NFADDR = pagenum & 0xff;  
  •       NFADDR = (pagenum >> 8) & 0xff;  
  •       NFADDR = (pagenum >> 16) & 0xff;  
  •       /*如果不理解见数据手册nand flashP9*/  
  •   
  •       NFCMD = 0x30;  
  •       wait_idle();  
  •   
  •       for(j=0; j < NAND_SECTOR_SIZE; j++) {  
  •           *buf = (NFDATA & 0xff);  
  •            buf++;  
  •       }  
  •        
  •      i += NAND_SECTOR_SIZE;  
  •    
  •     }  
  •   
  •     NAND_CHIP_disABLE;  
  •      
  •     /* chip disable */  
  •       
  •     return 0;  
  • }  
  •     开发板的NAND Flash型号为k9f2g08u0a,它的容量是256MByte,NAND Flash的最小读取单位是以页为单位的,即2KByte(12位)每页,共128K页(17位),而地址线是8位的,因此当需要读取一页时,需分周期发送页地址,这款芯片规定前两个地址周期发送页内地址,后面的三周期发送页编号,它的流程如表1:

    1 NAND Flash地址

     

    I/O 0

    I/O 1

    I/O 2

    I/O 3

    I/O 4

    I/O 5

    I/O 6

    I/O 7

    第一周期

    A0

    A1

    A2

    A3

    A4

    A5

    A6

    A7

    第二周期

    A8

    A9

    A10

    A11

    0

    0

    0

    0

    第三周期

    A12

    A13

    A14

    A15

    A16

    A17

    A18

    A19

    第四周期

    A20

    A21

    A22

    A23

    A24

    A25

    A26

    A27

    第五周期

    A28

    0

    0

    0

    0

    0

    0

    0

    我们在读取uboot.bin时,直接按页读取,所以前两周期地址我们设成了全0,后面的3周期实际就是也编号。

    修改board/fl2440/Makefile文件,使得nand_read.c能被编译到u-boot.bin中,修改28行为:

  • COBJS   := fl2440.o nand_read.o flash.o  
  • 我们还知道由于我们需要在前4K代码中完成代码的搬移,而搬移的代码集中在start.S和nand_read.c中,而U-boot的编译过程并不能保证nand_read.c能在前4K代码中,所以需要我们手动设置,修改文件arch/arm/cpu/arm920t/u-boot.lds文件40行为:

  • .text :  
  • {  
  •     arch/arm/cpu/arm920t/start.o    (.text)  
  •                board/fl2440/lowlevel_init.o (.text)  
  •                board/fl2440/nand_read.o (.text)  
  •     *(.text)  
  • }  

  • 这样,编译器在编译时能保证start.S和nand_read.c编译出的二进制代码在前4K。

    修改include/configs/fl2440.h中,添加相关的宏定义以支持NAND Flash的串口操作命令:

  • #define CONfig_CMD_NAND   /*****add by yanghao*****/  
  • <p>#if defined(CONfig_CMD_NAND)</p><p>#define CONfig_NAND_S3C2410  
  • #define CONfig_SYS_MAX_NAND_DEVICE   1     /* Max number of NAND devices        */  
  • #define NAND_MAX_CHIPS   1  
  • #define CONfig_SYS_NAND_BASE 0x4E000000</p>#endif  
  •  

    然后将开发板设置成为从NAND Flash启动,将编译出来的u-boot.bin烧写入NAND Flash,上电这样就完成了从NAND Flash的启动。

    相关文章

      译序:JWMediaPlayer是开源的网页使用的Flash播放器。本...
        Flash编程原理都是只能将1写为0,而不能将0写成1.所...
     上传setenvgatewayip192.168.1.1;setenvserverip192.168.1...
    Error:FlashDownloadFailed-"Cortex-M3"出现一般有...
    jPlayer是一个用于控制和播放mp3文件的jQuery插件。它在后台...
    #ifndef__FONTUPD_H__#define__FONTUPD_H__#include"sy...