u-boot移植(九)---代码修改---NAND

2023-07-03  

一、NAND原理

  

  NAND 无地址空间,地址和数据的发送都依赖于LDATA[0:7]这一串数据总线。

  

   不看随机页编程,看到从高位到低位的页,总共分为64个页面,每个页的组成是2K + 64  个byte,一个块的大小是(128K + 4K)byte,64页组成一块。

1.1 NAND Flash的编址

  nand flash的的页的大小是(2048 + 64)byte,64这个数据是不参与编址的。

  访问 nand flash:


    • 发出命令:读、写、擦除

    • 发出地址

    • 传输数据

   命令设置如下:

  

1.2 nand flash的访问

  

  可以看看上面的模式选择,然后对应引脚进行操作,就可以进行读写操作。命令和数据就通过这些引脚来进行操作。但是不必直接操作这些引脚,可以通过寄存器来进行操作。

  查看S3C2440的手册,可以看到如下的信息:

  

  写命令寄存器就相当于NAND Flash寄存器命令周期,写地址寄存器就相当于NAND Flash寄存器的地址周期......

   我们的NAND Flash是X8的,即是8位NAND Flash,对应2440上面的一些控制寄存器:

  NAND Flash命令寄存器:

  

  地址寄存器:

  

  数据寄存器:

  

  状态寄存器:

  

  还有一些其他寄存器是与读写有关的。

  操作这些寄存器,2440会自动驱动PIN脚给出信号。

二、u-boot中设置nand启动

2.1 建立init.c

  这是NAND启动的初始化文件,里面包含了nand启动的初始化函数。代码添加到 borad/samdung/jz2440/ 目录下:

  1 /* NAND FLASH控制器 */

  2 #define NFCONF (*((volatile unsigned long *)0x4E000000))

  3 #define NFCONT (*((volatile unsigned long *)0x4E000004))

  4 #define NFCMMD (*((volatile unsigned char *)0x4E000008))

  5 #define NFADDR (*((volatile unsigned char *)0x4E00000C))

  6 #define NFDATA (*((volatile unsigned char *)0x4E000010))

  7 #define NFSTAT (*((volatile unsigned char *)0x4E000020))

  8 

  9 /* GPIO */

 10 #define GPHCON              (*(volatile unsigned long *)0x56000070)

 11 #define GPHUP               (*(volatile unsigned long *)0x56000078)

 12 

 13 /* UART registers*/

 14 #define ULCON0              (*(volatile unsigned long *)0x50000000)

 15 #define UCON0               (*(volatile unsigned long *)0x50000004)

 16 #define UFCON0              (*(volatile unsigned long *)0x50000008)

 17 #define UMCON0              (*(volatile unsigned long *)0x5000000c)

 18 #define UTRSTAT0            (*(volatile unsigned long *)0x50000010)

 19 #define UTXH0               (*(volatile unsigned char *)0x50000020)

 20 #define URXH0               (*(volatile unsigned char *)0x50000024)

 21 #define UBRDIV0             (*(volatile unsigned long *)0x50000028)

 22 

 23 #define TXD0READY   (1<<2)

 24 

 25 

 26 void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);

 27 

 28 /* 判定是否是nor启动 */

 29 static int isBootFromNorFlash(void)

 30 {

 31     volatile int *p = (volatile int *)0;

 32     int val;

 33 

 34     val = *p;

 35     *p = 0x12345678;

 36     if (*p == 0x12345678)

 37     {

 38         /* 写成功, 是nand启动 */

 39         *p = val;

 40         return 0;

 41     }

 42     else

 43     {

 44         /* NOR不能像内存一样写 */

 45         return 1;

 46     }

 47 }

 48 

 49 /* 拷贝代码到sdram */

 50 void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)

 51 {    

 52     int i = 0;

 53     

 54     /* 如果是NOR启动 */

 55     if (isBootFromNorFlash())

 56     {

 57         while (i < len)

 58         {

 59             dest[i] = src[i];

 60             i++;

 61         }

 62     }

 63     else

 64     {

 65         //nand_init();

 66         nand_read_ll((unsigned int)src, dest, len);

 67     }

 68 }

 69 

 70 /* 清除BSS */

 71 void clear_bss(void)

 72 {

 73     extern int __bss_start, __bss_end;

 74     int *p = &__bss_start;

 75     

 76     for (; p < &__bss_end; p++)

 77         *p = 0;

 78 }

 79 

 80 /* nand初始化 */

 81 void nand_init_ll(void)

 82 {

 83 #define TACLS   0

 84 #define TWRPH0  1

 85 #define TWRPH1  0

 86     /* 设置时序 */

 87     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

 88     /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */

 89     NFCONT = (1<<4)|(1<<1)|(1<<0);    

 90 }

 91 

 92 static void nand_select(void)

 93 {

 94     NFCONT &= ~(1<<1);    

 95 }

 96 

 97 static void nand_deselect(void)

 98 {

 99     NFCONT |= (1<<1);    

100 }

101 

102 static void nand_cmd(unsigned char cmd)

103 {

104     volatile int i;

105     NFCMMD = cmd;

106     for (i = 0; i < 10; i++);

107 }

108 

109 static void nand_addr(unsigned int addr)

110 {

111     unsigned int col  = addr % 2048;

112     unsigned int page = addr / 2048;

113     volatile int i;

114 

115     NFADDR = col & 0xff;

116     for (i = 0; i < 10; i++);

117     NFADDR = (col >> 8) & 0xff;

118     for (i = 0; i < 10; i++);

119     

120     NFADDR  = page & 0xff;

121     for (i = 0; i < 10; i++);

122     NFADDR  = (page >> 8) & 0xff;

123     for (i = 0; i < 10; i++);

124     NFADDR  = (page >> 16) & 0xff;

125     for (i = 0; i < 10; i++);    

126 }

127 

128 static void nand_wait_ready(void)

129 {

130     while (!(NFSTAT & 1));

131 }

132 

133 static unsigned char nand_data(void)

134 {

135     return NFDATA;

136 }

137 

138 void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)

139 {

140     int col = addr % 2048;

141     int i = 0;

142         

143     /* 1. 选中 */

144     nand_select();

145 

146     while (i < len)

147     {

148         /* 2. 发出读命令00h */

149         nand_cmd(0x00);

150 

151         /* 3. 发出地址(分5步发出) */

152         nand_addr(addr);

153 

154         /* 4. 发出读命令30h */

155         nand_cmd(0x30);

156 

157         /* 5. 判断状态 */

158         nand_wait_ready();

159 

160         /* 6. 读数据 */

161         for (; (col < 2048) && (i < len); col++)

162         {

163             buf[i] = nand_data();

164             i++;

165             addr++;

166         }

167         

168         col = 0;

169     }

170 

171     /* 7. 取消选中 */        

172     nand_deselect();

173 }

  修改 borad/samdung/jz2440/ 目录下的 makefile:

  

2.2 去掉代码重定位

  去掉 -pie 选项:

  

  注释掉第82行:

  

2.3 修改代码链接地址

  Jz2440.h (includeconfigs) 

  

2.4 修改链接脚本文件

  U-boot.lds (archarmcpu) 链接脚本的修改,本版本u-boot将一个文件夹下面的c文件都链接成一个.o文件,名字为built-in.o,所以我们直接写上built-in.o即可。

  

  

  将这两个built-in.o放入链接脚本当中:

  

2.5 修改 board_init_f

  在crt0.S中设置nand 启动的代码:

  

  这一段代码就是 nand 重定位代码了。CONFIG_SYS_TEXT_BASE 是自己设置的,可以自行设置大小。

  接下来的代码就是跳转到 board_init_f_mem 和 board_init_f 中执行初始化。

   init_sequence_f 链表中要注释掉下面两行,并更改:

  

2.6 修改重定位代码

  首先在board_init_f(Board_f.c (common) )添加返回函数:

  

 1 unsigned int board_init_f(ulong boot_flags)

 2 {

 3 

 4     gd->flags = boot_flags;

 5     gd->have_console = 0;

 6 

 7     if (initcall_run_list(init_sequence_f))

 8         hang();

 9 #if 0

10 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) &&

11         !defined(CONFIG_EFI_APP)

12     /* NOTREACHED - jump_to_copy() does not return */

13     hang();

14 #endif

15 #endif

16     return (unsigned int)(gd->new_gd);  //添加的返回值,返回id供 board_init_r调用

17 }


  board_init_f 函数原型记得在 include/common中也修改。


  修改crt0.S 代码如下:


ENTRY(_main)


/*

 * Set up initial C runtime environment and call board_init_f(0).

 * 初始化C运行环境并且调用 board_init_f(0) 函数

 */


 /*

  * 初始化栈地址

  */

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)

    ldr    sp, =(CONFIG_SPL_STACK)

#else

    /* Generic-asm-offsets.h (includegenerated)

     * #define GENERATED_GBL_DATA_SIZE 192

     * JZ2440.h(includeconfig)

     * #define PHYS_SDRAM_1        0x30000000

     * #define CONFIG_SYS_SDRAM_BASE    PHYS_SDRAM_1

     * #define CONFIG_SYS_INIT_SP_ADDR    (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)

     * 

     * CONFIG_SYS_INIT_SP_ADDR = 0x30000000 + 0x1000 - 192(0xc0) = 0x30000f40

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。