加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

u-boot-2009.08在mini2440上的移植(三)---增加nand flash功能

发布时间:2020-12-15 18:08:31 所属栏目:百科 来源:网络整理
导读:u-boot-2009.08在mini2440上的移植(三)---增加nand flash功能 ?? 转载补充,谢谢分享:http://blog.163.com/liuqiang_mail@126/blog/static/109968875201176214200/ 移植环境 1,主机环境:VMare下CentOS 5.5 ,1G内存。 2,集成开发环境:Elipse IDE 3,

u-boot-2009.08在mini2440上的移植(三)---增加nand flash功能??

转载补充,谢谢分享:http://blog.163.com/liuqiang_mail@126/blog/static/109968875201176214200/

移植环境

1,主机环境:VMare下CentOS 5.5 ,1G内存。

2,集成开发环境:Elipse IDE

3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。

4,开发板:mini2440,2M nor flash,128M nand flash。

5,u-boot版本:u-boot-2009.08

6,参考文章:

http://blogold.chinaunix.net/u3/101649/showart.php?id=2105215

http://blog.chinaunix.net/space.php?uid=23787856&do=blog&id=115382

http://blogimg.chinaunix.net/blog/upfile2/100811115954.pdf

目前u-boot中还没有对2440上Nand Flash的支持,也就是说要想u-boot从Nand Flash上启动得自己去实现了。在做u-boot移植的时候,多数人使用的是Nand flash启动或Nar Flash启动。这样u-boot就只能在Nand flash或Nor flash。那么我们如何让我们的u-boot在Nand flash或Nor flash都能使用。

3.1,Nand flash或Nor flash双启动原理

首先,看一下我们熟悉的u-boot启动的时候执行的一段程序,这段程序一般存放在Nand flash中或Nor flash中。我们所说的Nand flash启动或Nor flash启动主要是涉及到一段搬移代码。这段搬移代码的功能是u-boot自己把自己搬移到内存中执行。如下是Nor flash启动中的这段搬移代码(这里以s3c2410为例)

  relocate:??????????????????????? /* relocate U-Boot to RAM */
  adr r0,_start??????? /* r0 <- current position of code */
  ldr r1,_TEXT_BASE??????? /* test if we run from flash or RAM */
  cmp r0,r1??????????????????????? /* don't reloc during debug */
  beq stack_setup
  ldr r2,_armboot_start
  ldr r3,_bss_start
  sub r2,r3,r2??????????????? /* r2 <- size of armboot */
  add r2,r0,r2??????????????? /* r2 <- source end address */
  copy_loop:
  ldmia r0!,{r3-r10}??????????????? /* copy from source address [r0] */
  stmia r1!,{r3-r10}??????????????? /* copy to target address [r1] */
  cmp r0,r2??????????????? /* until source end addreee [r2] */
  ble copy_loop
  #endif??????? /* CONFIG_SKIP_RELOCATE_UBOOT */
  #endif

上面这段代码就是把u-boot搬移到内存。而不同的启动方式区别也就在这段代码上,如果我们这里是Nand flash启动的话我们也需要写相同功能的代码,不同的是对于Nand的操作和Nor的操作是完全不同的,选择Nor flash启动是将Nor flash映射到片选0上也就是0x0地址而选择Nand flash启动则是将CPU的片内RAM(4K)映射到0地址,通过Nand flash控制器操作Nand flash。我们这里讨论如何实现Nand 和 Nor双启动。下面我们看看这两种启动的映射关系。


同时我们可以看到: 总线宽度和等待控制寄存器:
?


?
?在系统重启时会扫描BWSCON的状态,而BWSCON的其他位的初始状态都是0,只有DW0(BWSCON[2:1])的值由OM[1:0]来决定,通过上面的2个图我们可以发现,我们可以通过判断BWSCON的第2位、第3位?? {DW0(BWSCON[2:1])}的值,判断是Nor flash启动还是Nand Flash启动。可以启动代码之前添加如下代码,来判断是Nor flash启动还是Nand Flash启动。

?# define BWSCON?? 0x48000000?
??????? ldr r0,=BWSCON
??????? ldr r0,[r0]
??????? and r0,#6
??????? cmp? r0,#0??
??????? bne? relocate

?///////////////////////////////////////////////////
???? //nand_boot
? //Nand 搬移代码
////////////////////////////////////////////////////
??relocate:
?????? //nor_boot
????? //Nor 搬移代码
////////////////////////////////////////////////////
有了上面这段代码,就可以实现双启动了,只要再适当的添加对应的功能我们的uboot就完成了

?3.2,为u-boot增加对nand flash支持实际操作

【1】修改代码重定向部分,增加Nor flash 和Nand flash 双启动

修改cpu/arm920t/start.S文件,为使u-boot从Nand Flash启动,需要将下面注释掉的CPU和DRAM初始化部分还原。

用gedit打开cpu/arm920t/start.S,定位到199行附近,找到如下代码

//#ifndef CONFIG_SKIP_LOWLEVEL_INIT
?//bl cpu_init_crit
//#endif

将注释掉的这段代码恢复,修改如下:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
?bl cpu_init_crit
#endif

Tekkaman Ninja从2009.08 开始就在启动时增加了启动时检测自身是否已经在SDRAM中(通过OpenJTAG载入),以及芯片是Norboot还是Nandboot的机制,来决定代码重定向的方式,使得编译出的bin文件可以同时烧入Nand Flash和Nor flash,以及被OpenJTAG载入进行调试。至于这部分的原理,在Tekkaman Ninja的博客文章《在U-boot下实现自动识别启动Flash的原理(针对S3C24x0)》中有详细叙述。这部分代码修改后结果如下:

(1)判断当前代码位置,如果在内存,直接跳到stack_setup

//#ifndef CONFIG_SKIP_RELOCATE_UBOOT
//relocate: /* relocate U-Boot to RAM */
/***************** Check the code position begain*******************************/
?adr r0,_start? /* r0 <- current position of code?? */
?ldr r1,_TEXT_BASE? /* test if we run from flash or RAM */
?cmp???? r0,r1????????? /* don't reloc during debug? */
?beq???? stack_setup
/****************** Check the code position end ********************************/

(2)如果不是在代码当前位置不再内存中,就判断启动的Flash:Nand 或者Nor
/***************** Check the boot flash begain **********************************/
# define BWSCON? 0x48000000?
??????? ldr r0,[r0]
??????? ands r0,#0??
??????? bne? relocate


?/* recovery? */
?ldr r0,=(0xdeadbeef)
?ldr r1,=( (4<<28)|(3<<4)|(3<<2) )
?str r0,[r1]
/***************** check the boot flash end ************************************/

(3)如果判断是在Nand Flash中启动的话,那么nand? Flash搬移代码如下:
定义u-boot在nand flash中存放的长度为#define LENGTH_UBOOT 0x60000,可以方便修改u-boot因为裁剪和增添大小的改变而占的长度。

// copy U-Boot to RAM? form?? Nand Flash

/***************** NAND BOOT start *************************************************/

#define LENGTH_UBOOT 0x60000
#define NAND_CTL_BASE 0x4E000000

#ifdef CONFIG_S3C2440
/* Offset */
#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)|(0<<0) )
?str r2,[r1,#oNFCONF]
?ldr r2,#oNFCONF]

?ldr r2,=( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
?str r2,#oNFCONT]
?ldr r2,#oNFCONT]

?mov r2,#0xff @ RESET command
?strb r2,#oNFCMD]

?mov r3,#0 @ wait
nand1:
?add r3,#0x1
?cmp r3,#0xa
?blt nand1

nand2:
?ldr r2,#oNFSTAT] @ wait ready
?tst r2,#0x4
?beq nand2


?ldr r2,#oNFCONT]
?orr r2,r2,#0x2 @ Flash Memory Chip Disable
?str r2,u5b8bu4f53; margin-top:0px; margin-bottom:10px; padding-top:0px; padding-bottom:0px"> ?@ get read to call C functions (for nand_read())
?ldr sp,DW_STACK_START @ setup stack pointer
?mov fp,#0 @ no previous frame,so fp=0

?@ copy U-Boot 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 @ 4 bytes * 1024 = 4K-bytes
go_next:
?ldr r3,[r0],#4
?ldr r4,[r1],#4
?teq r3,r4
?bne notmatch
?subs r2,#4
?beq stack_setup
?bne go_next

notmatch:
loop3:
?b loop3 @ infinite loop
#endif

#ifdef CONFIG_S3C2410

/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFSTAT 0x10


?mov r3,#0x1
?beq nand2

bad_nand_read:
loop2:
?b loop2 @ infinite loop


ok_nand_read:
?@ verify
?mov r0,u5b8bu4f53; margin-top:0px; margin-bottom:10px; padding-top:0px; padding-bottom:0px"> notmatch:
loop3:
?b loop3 @ infinite loop

#endif
/***************** NAND BOOT end *************************************************/


(4)如果判断是在Nor? Flash中启动的话,那么nor? Flash搬移代码如下:

// copy U-Boot to RAM? form?? Nor? Flash

/***************** NOR BOOT start *************************************************/
relocate:??? /* relocate U-Boot to RAM???? */
????? /*********** CHECK_FOR_MAGIC_NUMBER***************/
?ldr r1,=(0xdeadbeef)
?cmp r0,r1
?bne loop3
????? /*********** CHECK_FOR_MAGIC_NUMBER***************/
?adr r0,_TEXT_BASE? /* test if we run from flash or RAM */
?ldr r2,_armboot_start
?ldr r3,_bss_start
?sub r2,r2? /* r2 <- size of armboot??????????? */
?add r2,r2? /* r2 <- source end address???????? */

copy_loop:
?ldmia r0!,{r3-r10}? /* copy from source address [r0]??? */
?stmia r1!,{r3-r10}? /* copy to?? target address [r1]??? */
?cmp r0,r2?? /* until source end addreee [r2]??? */
?ble copy_loop
//#endif /* CONFIG_SKIP_RELOCATE_UBOOT */?
/***************** NOR BOOT end********************************************/


?/* Set up the stack????????? */
stack_setup:
?ldr r0,_TEXT_BASE? /* upper 128 KiB: relocated uboot?? */
?sub r0,#CONFIG_SYS_MALLOC_LEN /* malloc area???????????? */
?sub r0,#CONFIG_SYS_GBL_DATA_SIZE /* bdinfo?

... ...

【2】在上面添加的代码中有一个跳转:bl nand_read_ll ,它跳入是新增的C 语言文件board/samsung/mini2440/nand_read.c中的函数,这个文件原本是用vivi 的代码,后来经过openmoko 的修改,并支持不同的Nand Flash 芯片,我又这里多加了几个个芯片ID以支持所有mini2440 的Nand Flash。代码如下:

/*
?* nand_read.c: Simple NAND read functions for booting from NAND
?*
?* This is used by cpu/arm920/start.S assembler code,
?* and the board-specific linker script must make sure this
?* file is linked within the first 4kB of NAND flash.
?*
?* Taken from GPLv2 licensed vivi bootloader,
?* Copyright (C) 2002 MIZI Research,Inc.
?*
?* Author: Hwang,Chideok <hwang@mizi.com>
?* Date? : $Date: 2004/02/04 10:37:37 $
?*
?* u-boot integration and bad-block skipping (C) 2006 by OpenMoko,Inc.
?* Author: Harald Welte <laforge@openmoko.org>
?*/

#include <common.h>
#include <linux/mtd/nand.h>


#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGw(x) (*(volatile unsigned short *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE? 0x4e000000
#if defined(CONFIG_S3C2410)
#define NFCONF? __REGi(NF_BASE + 0x0)
#define NFCMD? __REGb(NF_BASE + 0x4)
#define NFADDR? __REGb(NF_BASE + 0x8)
#define NFDATA? __REGb(NF_BASE + 0xc)
#define NFSTAT? __REGb(NF_BASE + 0x10)
#define NFSTAT_BUSY 1
#define nand_select() (NFCONF &= ~0x800)
#define nand_deselect() (NFCONF |= 0x800)
#define nand_clear_RnB() do {} while (0)
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
#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 NFDATA16 __REGw(NF_BASE + 0x10)
#define NFSTAT? __REGb(NF_BASE + 0x20)
#define NFSTAT_BUSY 1
#define nand_select() (NFCONT &= ~(1 << 1))
#define nand_deselect() (NFCONT |= (1 << 1))
#define nand_clear_RnB() (NFSTAT |= (1 << 2))
#endif

static inline void nand_wait(void)
{
?int i;

?while (!(NFSTAT & NFSTAT_BUSY))
? for (i=0; i<10; i++);
}

struct boot_nand_t {
?int page_size;
?int block_size;
?int bad_block_offset;
// unsigned long size;
};

#if 0
#if defined(CONFIG_S3C2410) || defined(CONFIG_MINI2440)
/* configuration for 2410 with 512byte sized flash */
#define NAND_PAGE_SIZE? 512
#define BAD_BLOCK_OFFSET 5
#define NAND_BLOCK_MASK? (NAND_PAGE_SIZE - 1)
#define NAND_BLOCK_SIZE? 0x4000
#else
/* configuration for 2440 with 2048byte sized flash */
#define NAND_5_ADDR_CYCLE
#define NAND_PAGE_SIZE? 2048
#define BAD_BLOCK_OFFSET NAND_PAGE_SIZE
#define NAND_BLOCK_MASK? (NAND_PAGE_SIZE - 1)
#define NAND_BLOCK_SIZE? (NAND_PAGE_SIZE * 64)
#endif

/* compile time failure in case of an invalid configuration */
#if defined(CONFIG_S3C2410) && (NAND_PAGE_SIZE != 512)
#error "S3C2410 does not support nand page size != 512"
#endif
#endif

static int is_bad_block(struct boot_nand_t * nand,unsigned long i)
{
?unsigned char data;
?unsigned long page_num;

?nand_clear_RnB();
?if (nand->page_size == 512) {
? NFCMD = NAND_CMD_READOOB; /* 0x50 */
? NFADDR = nand->bad_block_offset & 0xf;
? NFADDR = (i >> 9) & 0xff;
? NFADDR = (i >> 17) & 0xff;
? NFADDR = (i >> 25) & 0xff;
?} else if (nand->page_size == 2048) {
? page_num = i >> 11; /* addr / 2048 */
? NFCMD = NAND_CMD_READ0;
? NFADDR = nand->bad_block_offset & 0xff;
? NFADDR = (nand->bad_block_offset >> 8) & 0xff;
? NFADDR = page_num & 0xff;
? NFADDR = (page_num >> 8) & 0xff;
? NFADDR = (page_num >> 16) & 0xff;
? NFCMD = NAND_CMD_READSTART;
?} else {
? return -1;
?}
?nand_wait();
?data = (NFDATA & 0xff);
?if (data != 0xff)
? return 1;

?return 0;
}

static int nand_read_page_ll(struct boot_nand_t * nand,unsigned char *buf,unsigned long addr)
{
?unsigned short *ptr16 = (unsigned short *)buf;
?unsigned int i,page_num;

?nand_clear_RnB();

?NFCMD = NAND_CMD_READ0;

?if (nand->page_size == 512) {
? /* Write Address */
? NFADDR = addr & 0xff;
? NFADDR = (addr >> 9) & 0xff;
? NFADDR = (addr >> 17) & 0xff;
? NFADDR = (addr >> 25) & 0xff;
?} else if (nand->page_size == 2048) {
? page_num = addr >> 11; /* addr / 2048 */
? /* Write Address */
? NFADDR = 0;
? NFADDR = 0;
? NFADDR = page_num & 0xff;
? NFADDR = (page_num >> 8) & 0xff;
? NFADDR = (page_num >> 16) & 0xff;
? NFCMD = NAND_CMD_READSTART;
?} else {
? return -1;
?}
?nand_wait();

#if defined(CONFIG_S3C2410)
?for (i = 0; i < nand->page_size; i++) {
? *buf = (NFDATA & 0xff);
? buf++;
?}
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
?for (i = 0; i < (nand->page_size>>1); i++) {
? *ptr16 = NFDATA16;
? ptr16++;
?}
#endif

?return nand->page_size;
}

static unsigned short nand_read_id(void)
{
?unsigned short res = 0;
?NFCMD = NAND_CMD_READID;
?NFADDR = 0;
?res = NFDATA;
?res = (res << 8) | NFDATA;
?return res;
}

extern unsigned int dynpart_size[];

/* low level nand read function */
int nand_read_ll(unsigned char *buf,unsigned long start_addr,int size)
{
?int i,j;
?unsigned short nand_id;
?struct boot_nand_t nand;

?/* chip Enable */
?nand_select();
?nand_clear_RnB();
?
?for (i = 0; i < 10; i++)
? ;
?nand_id = nand_read_id();
?if (0) { /* dirty little hack to detect if nand id is misread */
? unsigned short * nid = (unsigned short *)0x31fffff0;
? *nid = nand_id;
?}

?????? if (nand_id == 0xec76?? /* Samsung K91208 */
???????????||nand_id == 0xad76 ) { /*Hynix HY27US08121A*/
? nand.page_size = 512;
? nand.block_size = 16 * 1024;
? nand.bad_block_offset = 5;
?// nand.size = 0x4000000;
?} else if (nand_id == 0xecf1? /* Samsung K9F1G08U0B */
?????||nand_id == 0xecda? /* Samsung K9F2G08U0B */
???? ||nand_id == 0xecd3 ) { /* Samsung K9K8G08 */
? nand.page_size = 2048;
? nand.block_size = 128 * 1024;
? nand.bad_block_offset = nand.page_size;
?// nand.size = 0x8000000;
?} else {
? return -1; // hang
?}
?if ((start_addr & (nand.block_size-1)) || (size & ((nand.block_size-1))))
? return -1; /* invalid alignment */

?for (i=start_addr; i < (start_addr + size);) {
#ifdef CONFIG_S3C2410_NAND_SKIP_BAD
?//if (i & (nand.block_size-1)== 0) {//warning: suggest parentheses around comparison in operand of '&'
?if ((i & (nand.block_size-1))== 0) {?
??

? if (is_bad_block(&nand,i) ||
?????? is_bad_block(&nand,i + nand.page_size)) {
??? /* Bad block */
??? i += nand.block_size;
??? size += nand.block_size;
??? continue;
?? }
? }
#endif
? j = nand_read_page_ll(&nand,buf,i);
? i += j;
? buf += j;
?}

?/* chip Disable */
?nand_deselect();

然后保存为nand_read.c,还要记得路径是在board/samsung/mini2440/目录下。

注意:上面这段代码中对Nand进行寻址的部分,这跟具体的Nand Flash的寻址方式有关。根据我们开发板上的Nand Flash(K9F1G08U0C)数据手册得知,片内寻址是采用27位地址形式。从第0位开始分四次通过I/O0-I/O7进行传送,并进行片内寻址。具体含义和结构图如下(相关概念参考Nand数据手册):

0-11位:Y-Buffers偏移地址

12-27位:X-Buffers偏移地址


【3】在board/samsung/mini2440/Makefile中添加nand_read.c的编译选项,使他编译到u-boot中,修改后代码如下:
?
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).a
COBJS :=??nand_read.o?mini2440.o flash.o
SOBJS := lowlevel_init.o
【4】在mini2440.h头文件中加入Nand要用到的宏和寄存器的定义。
用gedit打开include/configs/mini2440.h头文件,定位到文件末尾处加入下列代码:
/*-----------------------------------------------------------------------
?* NAND flash settings
?*/

#define CONFIG_S3C2410_NAND_SKIP_BAD 1

【5】在cpu/arm920t/u-boot.lds中添加下面两行代码,主要目的是防止编译器把我们自己添加的用于nandboot的子函数放到4K之后,否则是无法启动的,修改后代码如下:
?.text :
?{
???? cpu/arm920t/start.o (.text)
???? board/samsung/mini2440/lowlevel_init.o (.text)
???? board/samsung/mini2440/nand_read.o (.text)
???? *(.text)
?}
?

3.3,重新编译
?这里发生一个错误,错误原因是有一个变量没有定义,这个错误发生在【1】修改代码重定向部分,增加Nor flash 和Nand flash 双启动,错误提示信息如下:

Error: Internal_relocation (type 182) not fixed up (OFFSET_IMM)
编译 start.S 文件时出错。错误位置

340 @ get read to call C functions (for nand_read())
341 ldr sp,DW_STACK_START @ setup stack pointer
342 mov fp,so fp=0
反复排查问题,原来宏DW_STACK_START 原作者在文章中没有贴出定义,加上以下代码在cpu/arm920t/start.S的459行附件

ldrpc,_start_armboot
_start_armboot: .word start_armboot
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START: .wordSTACK_BASE+STACK_SIZE-4?

重新编译,成功,编译成功后生成u-boot.bin文件。下载时先将mini2440开发板调到Nor启动档,利用supervivi的a命令将u-boot.bin下载到开发板的Nand Flash中,再把开发板调到Nand启动档,打开电源就从Nand Flash启动了,启动结果如下:
... ...
Enter your selection: ?
U-Boot 2009.08 ( 5鏈?06 2011 - 14:17:44)
DRAM:? 64 MB
Flash:? 2 MB
*** Warning - bad CRC,using default environment
In:??? serial
Out:?? serial
Err:?? serial
[u-boot@MINI2440]#nand info
Unknown command nand' - try 'help'
[u-boot@MINI2440]#

从上面的运行结果看,显然现在的Nand还不能做任何事情,而且也没有显示有关Nand的任何信息,所以只能说明上面的这些步骤只是完成了Nand移植的Stage1部分。下面我们来添加我们开发板上的Nand Flash(K9F1G08U0B)的Stage2部分的有关操作支持。
3.4,在U-boot 启动的第一阶段,初始化了Nand Flash 控制器。但到第二阶段start_armboot函数还是会再次初始化Nand Flash 控制器。因为第二阶段和第一阶段的代码基本是独立的,第一阶段的代码基本只起到代码重定位的作用,到了第二阶段才是真正U-boot 的开始,以前的初始化过程还会重做一遍,比如始化Nand Flash 控制器、CPU 频率等。因为 S3C2440 和S3C2410 之间的很大差别就是:S3C2410 的Nand Flash 控制器只支持512B+16B 的Nand Flash,而S3C2440 还支持2KB+64B 的大容量Nand Flash。所以在Nand Flash 控制器上寄存器和控制流程上的差别很明显,底层驱动代码的修改也是必须的。具体的差别还是需要对比芯片数据手册的,下面我们结合代码来分析一下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函数等。

【1】Nand Flash 相关代码的修改
打开/drivers/mtd/nand/s3c2410_nand.c,定位到37行,修改如下:
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE? 0x4e000000
#if defined(CONFIG_S3C2410)
#define NFCONF? __REGi(NF_BASE + 0x0)
#define NFCMD? __REGb(NF_BASE + 0x4)
... ...
#define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8
#endif
#if defined(CONFIG_S3C2440)
#define S3C2410_ADDR_NALE 0x08
#define S3C2410_ADDR_NCLE 0x0c
#define NFCONF? __REGi(NF_BASE + 0x0)
#define NFCONT??? __REGb(NF_BASE + 0x4)???
#define NFCMD? __REGb(NF_BASE + 0x8)
#define NFADDR? __REGb(NF_BASE + 0xc)
#define NFDATA? __REGb(NF_BASE + 0x10)
#define NFMECCD0?? __REGb(NF_BASE + 0x14)
#define NFMECCD1?? __REGb(NF_BASE + 0x18)
#define NFSECCD?? __REGb(NF_BASE + 0x1c)
#define NFSTAT? __REGb(NF_BASE + 0x20)
#define NFESTAT0 __REGb(NF_BASE + 0x24)
#define NFESTAT1 __REGb(NF_BASE + 0x28)
#define NFMECC0? __REGb(NF_BASE + 0x2c)
#define NFMECC1? __REGb(NF_BASE + 0x30)
#define NFSECC? __REGb(NF_BASE + 0x34)
#define NFSBLK? __REGb(NF_BASE + 0x38)
#define NFEBLK? __REGb(NF_BASE + 0x3c)
#define NFECC0? __REGb(NF_BASE + 0x2c)
#define NFECC1? __REGb(NF_BASE + 0x2d)
#define NFECC2? __REGb(NF_BASE + 0x2e)
#define S3C2410_NFCONT_EN????????? (1<<0)
#define S3C2410_NFCONT_INITECC???? (1<<4)
#define S3C2410_NFCONT_nFCE??????? (1<<1)
#define S3C2410_NFCONT_MAINECCLOCK (1<<5)
#define S3C2410_NFCONF_TACLS(x)??? ((x)<<12)
#define S3C2410_NFCONF_TWRPH0(x)?? ((x)<<8)
#define S3C2410_NFCONF_TWRPH1(x)?? ((x)<<4)
#endif
ulong IO_ADDR_W = NF_BASE;??
static void s3c2410_hwcontrol(struct mtd_info *mtd,int cmd,unsigned int ctrl)
{
?//struct nand_chip *chip = mtd->priv;
?DEBUGN("hwcontrol(): 0x%02x 0x%02xn",cmd,ctrl);
?if (ctrl & NAND_CTRL_CHANGE) {
??//ulong IO_ADDR_W = NF_BASE;//应注释掉这个局部变量否则找不到ID "No NAND device found!!!"?
?? IO_ADDR_W = NF_BASE;?
?if (!(ctrl & NAND_CLE))
?? IO_ADDR_W |= S3C2410_ADDR_NCLE;
? if (!(ctrl & NAND_ALE))
???IO_ADDR_W |= S3C2410_ADDR_NALE;
? //chip->IO_ADDR_W = (void *)IO_ADDR_W;
#if defined(CONFIG_S3C2410)
? if (ctrl & NAND_NCE)
?? NFCONF &= ~S3C2410_NFCONF_nFCE;
? else
?? NFCONF |= S3C2410_NFCONF_nFCE;
#endif
#if defined(CONFIG_S3C2440)
? if (ctrl & NAND_NCE)
?? NFCONT &= ~S3C2410_NFCONT_nFCE;
? else
?? NFCONT |= S3C2410_NFCONT_nFCE;
#endif
?}
?if (cmd != NAND_CMD_NONE)
? //writeb(cmd,chip->IO_ADDR_W);
? writeb(cmd,(void *)IO_ADDR_W);
}
... ...
#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd,int mode)
{
?DEBUGN("s3c2410_nand_enable_hwecc(%p,%d)n",mtd,mode);
#if defined(CONFIG_S3C2410)
?NFCONF |= S3C2410_NFCONF_INITECC;
#endif
#if defined(CONFIG_S3C2440)
?NFCONT |= S3C2410_NFCONT_INITECC;
#endif
}
... ...
#endif
int board_nand_init(struct nand_chip *nand)
{
?u_int32_t cfg;
?u_int8_t tacls,twrph0,twrph1;
?S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
?DEBUGN("board_nand_init()n");
?clk_power->CLKCON |= (1 << 4);
?/* initialize hardware */
#if defined(CONFIG_S3C2410)
? twrph0 = 3; twrph1 = 0; tacls = 0;
? cfg = S3C2410_NFCONF_EN;
? cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
? cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
? cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
? NFCONF = cfg;
?/* initialize nand_chip data structure */
?nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;
#endif
#if defined(CONFIG_S3C2440)
? twrph0 = 4; twrph1 = 2; tacls = 0;
? cfg = 0;
? cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
? cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
? cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
? NFCONF = cfg;
? NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);
? /* initialize nand_chip data structure */
? nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
#endif
?/* read_buf and write_buf are default */
?/* read_byte and write_byte are default */


【2】在mini2440.h里添加nand_flash相关宏定义
打开include/configs/mini2440.h,定位到98行附近,加入下列代码:
/*
?* Command line configuration.
?*/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_JFFS2? /* JFFS2 Support*/
... ...
在文件末尾处加入下列代码:
/*-----------------------------------------------------------------------
?* NAND flash settings
?*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_NAND_BASE 0x4E000000?
#define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND devices? */
#define SECTORSIZE 512
#define SECTORSIZE_2K 2048
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_SECTOR_SIZE_2K SECTORSIZE_2K
#define NAND_BLOCK_MASK 511
#define NAND_BLOCK_MASK_2K 2047
#define NAND_MAX_CHIPS 1
#define CONFIG_MTD_NAND_VERIFY_WRITE?
#define CONFIG_SYS_64BIT_VSPRINTF? /* needed for nand_util.c */
#endif /* CONFIG_CMD_NAND */
#define CONFIG_S3C2410_NAND_SKIP_BAD 1
?
3.5,重新编译,按上面3.3中方法下载,运行结果如下:
?
Enter your selection: ?
U-Boot 2009.08 ( 5鏈?06 2011 - 19:52:47)
DRAM:? 64 MB
Flash:? 2 MB
NAND:? 128 MiB
*** Warning - bad CRC,using default environment
In:??? serial
Out:?? serial
Err:?? serial
[u-boot@MINI2440]# nand info
Device 0: NAND 128MiB 3,3V 8-bit,sector size 128 KiB
[u-boot@MINI2440]# saveenv
Saving Environment to Flash...
Un-Protected 16 sectors
Erasing Flash...Erasing sector 64 ...
从上面输出信息可以看到保存环境变量并没有成功,而且它是将把环境变量保存到Flash即Nor flash中,显然这不正确,我们是要保存到Nand中。原来,u-boot在默认的情况下把环境变量都是保存到Nor Flash中的,所以我们要修改代码,让它保存到Nand中,如下:
打开include/configs/mini2440.h,定位到193行附近,注释掉下列代码:

/* timeout values are in ticks */
#define CONFIG_SYS_FLASH_ERASE_TOUT?(5*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
#define CONFIG_SYS_FLASH_WRITE_TOUT?(5*CONFIG_SYS_HZ) /* Timeout for Flash Write */

//#define?CONFIG_ENV_IS_IN_FLASH?1
//#define CONFIG_ENV_SIZE??0x20000?/* Total Size of Environment Sector */

然后加入下列代码:

/*-----------------------------------------------------------------------
?* NAND flash settings
?*/
#define CONFIG_ENV_IS_IN_NAND? 1
#define CONFIG_ENV_OFFSET????? 0x40000 //将环境变量保存到nand中的0x40000位置必,须在块的起始位置
#define CONFIG_ENV_SIZE??????? 0x20000 /*必须为块大小的整数倍 , 否则会提示下面的信息,将擦除整个块*/
#if defined(CONFIG_CMD_NAND)
?
Warning: Erase size 0x00010000 smaller than one erase block 0x00020000
???????? Erasing 0x00020000 instead
NAND 128MiB 3,3V 8-bit: MTD Erase failure: -22
Writing to Nand... FAILED!
?
然后保存,重新编译、拨到nor 档下载,在拨到nand 档上电运行:
Enter your selection: ?
U-Boot 2009.08 ( 5鏈?06 2011 - 22:30:25)
DRAM:? 64 MB
Flash:? 2 MB
NAND:? 128 MiB
*** Warning - bad CRC or NAND,using default environment
In:??? serial
Out:?? serial
Err:?? serial
[u-boot@MINI2440]# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 --?? 0% complete.
Writing to Nand... done
[u-boot@MINI2440]#
可以看到环境变量保存成功,将开发板重新上电后不会再有bad CRC告警,nand flash 移植成功。

接下来将进入u-boot的第四阶段,为u-boot-2009.08增加网卡DM9000驱动支持。

有时间要研究代码呀,一定要,待续。。。。。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读