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行附近将:

[cpp]  view plain copy
  1. #ifndef CONFIG_SKIP_RELOCATE_UBOOT  
  2. relocate:  

修改为

[html]  view plain copy
  1. norflash_boot:  
  2. #ifndef CONFIG_SKIP_RELOCATE_UBOOT  
  3. relocate:  

二、添加NAND Flash的U-boot代码从NAND FLash到SDRAM搬移的代码
在前面修改的 bne norflash_boot ,227行后添加

[cpp]  view plain copy
  1. /*****************************nand boot**************************/  
  2. nandflash_boot:  
  3. #define LENGTH_UBOOT 0x40000  
  4. #define NAND_CTL_BASE 0x4e000000  
  5. #define oNFCONF 0x00  
  6. #define oNFCONT 0x04  
  7. #define oNFCMD  0x08  
  8. #define oNFSTAT 0x20  
  9.   
  10.         @reset NAND  
  11.         mov     r1,#NAND_CTL_BASE  
  12.         ldr     r2,=((7<<12)|(7<<8)|(7<<4))  
  13.         str     r2,[r1,#oNFCONF]  
  14.         ldr     r2,[r1,#oNFCONF]  
  15.           
  16.         ldr     r2,=((1<<4)|(1<<1)|(1<<0)) @Active low CE control  
  17.         str     r2,[r1,#oNFCONT]  
  18.         ldr     r2,[r1,#oNFCONT]  
  19.           
  20.         @ get read to call C functions  
  21.         ldr     sp,DW_STACK_START   @setup stack point  
  22.         mov     fp,#0               @no previous frame, so fp = 0  
  23.           
  24.         @copy Uboot to ram  
  25.         ldr     r0, =TEXT_BASE  
  26.         mov     r1,#0x0  
  27.         mov     r2,#LENGTH_UBOOT  
  28.         bl      nand_read_ll  
  29.         tst     r0,#0x0  
  30.         beq     ok_nand_read  
  31.   
  32. bad_nand_read:  
  33. loop2:  
  34.         b       loop2     @infinite loop  
  35.   
  36. ok_nand_read:  
  37.         @verify  
  38.         mov     r0,#0  
  39.         ldr     r1,=TEXT_BASE  
  40.         mov     r2,#0x400     @ compare 4k code from sram to sdram  
  41.   
  42. go_next:  
  43.         ldr     r3, [r0], #4  
  44.         ldr     r4, [r1], #4  
  45.         teq     r3, r4  
  46.         bne     notmatch  
  47.         subs    r2,r2,#4  
  48.         tst     r2,#0x0   @do not forget the instruction if have not this command the uboot can't break the loop  
  49.         beq     stack_setup  
  50.         bne     go_next  
  51.   
  52. notmatch:  
  53. loop3:  
  54.         b       loop3 @infinite loop  
  55. /*****************************nand boot**************************/  

上面这部分代码首先初始化了NAND Flash寄存器,然后进行了一个函数调用(这个函数中完成了代码搬移)后面则是对复制出来的数据进行一个简单的校验。在327行附近添加为:

[cpp]  view plain copy
  1. _start_armboot: .word start_armboot  
  2. #define  STACK_BASE 0x33f00000  
  3. #define  STACK_SIZE 0x10000  
  4.         .align 2  
  5. DW_STACK_START: .word STACK_BASE+STACK_SIZE-4  

添加函数的栈调用空间

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

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

[cpp]  view plain copy
  1. /*  
  2.  * vivi/s3c2410/nand_read.c: Simple NAND read functions for booting from NAND 
  3.  * 
  4.  * Copyright (C) 2002 MIZI Research, Inc. 
  5.  * 
  6.  * Author: Hwang, Chideok <hwang@mizi.com> 
  7.  * Date  : $Date: 2002/08/14 10:26:47 $ 
  8.  * 
  9.  * $Revision: 1.6 $ 
  10.  * $Id: param.c,v 1.9 2002/07/11 06:17:20 nandy Exp  
  11.  * 
  12.  */  
  13.   
  14. #include <config.h>  
  15.   
  16. #define __REGb(x)   (*(volatile unsigned char *)(x))  
  17. #define __REGi(x)   (*(volatile unsigned int *)(x))  
  18. #define NF_BASE     0x4e000000  
  19.   
  20. /*S3C2440与S3C2440 nandflash控制寄存器地址不同需要进行修改*/  
  21. #define NFCONF      __REGi(NF_BASE + 0x0)  
  22. #define NFCONT          __REGi(NF_BASE + 0x4)  
  23. #define NFCMD       __REGb(NF_BASE + 0x8)  
  24. #define NFADDR      __REGb(NF_BASE + 0xc)  
  25. #define NFDATA      __REGb(NF_BASE + 0x10)  
  26. #define NFSTAT      __REGb(NF_BASE + 0x20)  
  27.   
  28. #define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))  
  29. #define NAND_CHIP_DISABLE (NFCONT |= (1<<1))  
  30. #define NAND_CLEAR_RB (NFSTAT |= (1<<2))  
  31. #define NAND_DETECT_RB {while(! (NFSTAT&(1<<2)));}  
  32. #define NAND_ECC_CLEAR (NFCONT |= 0x10)  
  33. /*see data sheet P193*/  
  34.   
  35. #define BUSY 1  
  36. static inline void wait_idle(void) {  
  37.     int i;  
  38.     while(!(NFSTAT & BUSY))  
  39.       for(i=0; i<10; i++);  
  40. }  
  41.   
  42. /*根据fl2440的nand flash 作相应修改*/  
  43. #define NAND_SECTOR_SIZE    2048  
  44. #define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)  
  45.   
  46. /* low level nand read function */  
  47.  int  
  48. nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)  
  49. {  
  50.     int i, j;  
  51.     int pagenum;  
  52.   
  53.     if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {  
  54.         return -1;  /* invalid alignment */  
  55.     }  
  56.   
  57.     /* chip Enable */  
  58.     NAND_CHIP_ENABLE;  
  59.       
  60.     for(i = start_addr; i < (start_addr + size);) {  
  61.       /* READ0 */  
  62.   
  63.       NAND_CLEAR_RB;  
  64.       for(j = 0; j < 10; j++);  
  65.         
  66.       pagenum = i >> 11;  
  67.       /* Write Address  
  68.         该步骤详见nand flash(k9f2g08u0a)手册p17 
  69.         参考fl2440开发板nand_lowlevel.c文件中ReadPage函数 
  70.       */  
  71.       NFCMD = 0x0;  
  72.         
  73.       NFADDR = 0;  
  74.       NFADDR = 0;  
  75.       NFADDR = pagenum & 0xff;  
  76.       NFADDR = (pagenum >> 8) & 0xff;  
  77.       NFADDR = (pagenum >> 16) & 0xff;  
  78.       /*如果不理解见数据手册nand flashP9*/  
  79.   
  80.       NFCMD = 0x30;  
  81.       wait_idle();  
  82.   
  83.       for(j=0; j < NAND_SECTOR_SIZE; j++) {  
  84.           *buf = (NFDATA & 0xff);  
  85.            buf++;  
  86.       }  
  87.        
  88.      i += NAND_SECTOR_SIZE;  
  89.    
  90.     }  
  91.   
  92.     NAND_CHIP_DISABLE;  
  93.      
  94.     /* chip Disable */  
  95.       
  96.     return 0;  
  97. }  

    开发板的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行为:

[cpp]  view plain copy
  1. 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行为:

[cpp]  view plain copy
  1. .text :  
  2. {  
  3.     arch/arm/cpu/arm920t/start.o    (.text)  
  4.                board/fl2440/lowlevel_init.o (.text)  
  5.                board/fl2440/nand_read.o (.text)  
  6.     *(.text)  
  7. }  


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

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

[cpp]  view plain copy
  1. #define CONFIG_CMD_NAND   /*****add by yanghao*****/  
  2. <p>#if defined(CONFIG_CMD_NAND)</p><p>#define CONFIG_NAND_S3C2410  
  3. #define CONFIG_SYS_MAX_NAND_DEVICE   1     /* Max number of NAND devices        */  
  4. #define NAND_MAX_CHIPS   1  
  5. #define CONFIG_SYS_NAND_BASE 0x4E000000</p>#endif  

 

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

目录
相关文章
|
7月前
|
存储 内存技术
MTK flash配置方法(转)
MTK flash配置方法(转)
89 1
|
7月前
NUC980修改内核支持spi-nand
NUC980修改内核支持spi-nand
82 2
|
Ubuntu
野火IMX6ULL PRO移植最新buidroot根文件系统(2022.02.04)
野火IMX6ULL PRO移植最新buidroot根文件系统(2022.02.04)
287 0
|
开发工具 内存技术 Perl
如何固化ZYNQ PL端程序到FLASH
ZYNQ7000板子上,PL端逻辑烧写到FLASH里面。怎么办?
|
存储 Linux 芯片
如何编写linux下nand flash驱动-3
【读(read)操作过程详解】 以最简单的read操作为例,解释如何理解时序图,以及将时序图 中的要求,转化为代码。   解释时序图之前,让我们先要搞清楚,我们要做的事情:那就是,要从nand flash的某个页里面,读取我们要的数据。
1060 0
|
存储 Linux 芯片
如何编写linux下nand flash驱动-1
1.       硬件特性: 【Flash的硬件实现机制】 Flash全名叫做Flash Memory,属于非易失性存储设备(Non-volatile Memory Device),与此相对应的是易失性存储设备(Volatile Memory Device)。
964 0
|
存储 算法 Linux
如何编写linux下nand flash驱动-4
2.       软件方面 如果想要在Linux下编写Nand Flash驱动,那么就先要搞清楚Linux下,关于此部分的整个框架。弄明白,系统是如何管理你的nand flash的,以及,系统都帮你做了那些准备工作,而剩下的,驱动底层实现部分,你要去实现哪些功能,才能使得硬件正常工作起来。
946 0