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行附近修改为:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	bl	cpu_init_crit
#endif

#define BWSCON 0x48000000
        ldr     r0, =BWSCON
        ldr     r0, [r0]
        ands    r0, r0, #0x6
        tst     r0, #0x0
        bne     norflash_boot             /*OM[1:0] != 0, 跳转到NOR FLASH 启动处*/
/*判断uboot是从nand flash启动还是从 nor flash启动*/

在220行附近将:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:

修改为

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,[r1,#oNFCONF]
        
        ldr     r2,=((1<<4)|(1<<1)|(1<<0)) @Active low CE control
        str     r2,[r1,#oNFCONT]
        ldr     r2,[r1,#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 <hwang@mizi.com>
 * 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*****/

#if defined(CONFIG_CMD_NAND)

#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

#endif

 

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



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值