在OK6410平台的移植-----关于NAND启动

本文转载自:http://blog.chinaunix.net/uid-28382924-id-3412559.html

s3c6410 NAND flash启动原理网上有很多的资料讨论,这里不做详述,如果对其启动方式不了解的建议还是先阅读相关资料弄清楚。这里要讲的是针对2G MLC类型的NAND的移植方法。

1.修改配置2G MLC NAND相关信息。

   1.1修改/include/configs/smdk6410.h

         /* NAND chip page size */
        #define CONFIG_SYS_NAND_PAGE_SIZE 4096//2048
        /* NAND chip block size */
        #define CONFIG_SYS_NAND_BLOCK_SIZE (512 * 1024)//128
        /* NAND chip page per block count */
       #define CONFIG_SYS_NAND_PAGE_COUNT 128//64

  1.2修改/drivers/mtd/nand/nand_ids.c

找到这处:{"NAND 2GiB 3,3V 8-bit",    0xD5, 0, 2048, 0, LP_OPTIONS}改为:

                  {"NAND 2GiB 3,3V 8-bit",    0xD5, 4096, 2048, 512*1024, LP_OPTIONS}

   1.3修改/drivers/mtd/nand/nand_base.c

增加:static struct nand_ecclayout nand_oob_218 = {
.eccbytes = 104,
.eccpos = {
24,25,26,27,28,29,30,31,32,33,
34,35,36,37,38,39,40,41,42,43,
44,45,46,47,48,49,50,51,52,53,
54,55,56,57,58,59,60,61,62,63,
64,65,66,67,68,69,70,71,72,73,
74,75,76,77,78,79,80,81,82,83,
84,85,86,87,88,89,90,91,92,93,
94,95,96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,
114,115,116,117,118,119,120,121,122,123,
124,125,126,127},
.oobfree =
{
{.offset = 2,
.length = 22
}
}
};

还记得我们前面移植启动时有提示NAND:

No oob scheme defined for oobsize 218吗?

  在上面这个文件中找到nand_scan_tail()函数,增加:

case 218:
chip->ecc.layout = &nand_oob_218;
break;

经过修改后运行起来测试NAND 的读写看看是否正常:

Hit any key to stop autoboot: 0 

SMDK6410 # dnw 50008000

Insert a OTG cable into the connector!

OTG cable Connected!

Now, Waiting for DNW to transmit data

Download Done!! Download Address: 0x50008000, Download Filesize:0x401f0

Checksum is being calculated.

Checksum O.K.

SMDK6410 # md.b 50008000

50008000: 14 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................

50008010: 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................

50008020: 00 02 e0 57 60 02 e0 57 c0 02 e0 57 20 03 e0 57 ...W`..W...W ..W

50008030: 80 03 e0 57 e0 03 e0 57 40 04 e0 57 78 56 34 12 ...W...W@..WxV4.

SMDK6410 # nand erase 100000 40000


NAND erase: device 0 offset 0x100000, size 0x40000


Erasing at 0x100000 -- 100痮mplete.

OK

SMDK6410 # nand write 50008000 100000 40000


NAND write: device 0 offset 0x100000, size 0x40000

262144 bytes written: OK

SMDK6410 # nand read 58000000 100000 40000


NAND read: device 0 offset 0x100000, size 0x40000

262144 bytes read: OK

SMDK6410 # md.b 58000000

58000000: 14 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................

58000010: 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................

58000020: 00 02 e0 57 60 02 e0 57 c0 02 e0 57 20 03 e0 57 ...W`..W...W ..W

58000030: 80 03 e0 57 e0 03 e0 57 40 04 e0 57 78 56 34 12 ...W...W@..WxV4.

SMDK6410 #

上面先下载个程序到SDRAM 0x50008000中,然后查看该地址处的内容。再把这个地址开始的0x4000字节写入到NAND 0x100000这个地址处。再读NAND 0x100000的内容到SDRAM 0x58000000,这是第2片SDRAM的开始地址(我们有2片128M的SDRAM)。对比0x50008000和0x58000000的内容我们可以发现结果是相同的,这说明NAND的读写都没有问题。

开始时显示NAND的oob size=218,可能是还没有正确配置NAND的PAGE和BLOCK size,配置后变成128了,如下:

Hit any key to stop autoboot: 0 

SMDK6410 # nand info

Device 0: nand0, sector size 512 KiB

Page size 4096 b

OOB size 128 b

Erase size 524288 b

SMDK6410 #

2.添加NAND拷贝程序到SDRAM运行功能。

   我们知道,NAND启动时芯片会读NAND 开始的4K字节到iRAM运行,这4K字节里面放的程序主要功能是拷贝存放在NAND中的程序到SDRAM运行,这也是u-boot里面nand_spl这个文件夹里面相关程序的作用。

nand_spl根据u-boot的配置(CONFIG_NAND_SPL=y)生成一个u-boot-spl-16k.bin,这个程序就是放在NAND的第一个page(开始的4K字节)的。而u-boot-2012.10主目录下的u-boot.bin则是用于在SDRAM中运行的。u-boot把u-boot-spl-16k.bin和u-boot.bin拼起来合成一个u-boot-nand.bin这就是通常我们烧到NAND中的程序。但经过实验发现,通过u-boot的NAND write写到NAND的程序却运行不起来?这里要注意两个问题:第一,可能写的不对;第二,可能读得不对。但在上面第一步骤里面我们试过NAND的读写都是正确的。或者还有其他原因?

原来(不知道为什么),在把u-boot-nand.bin写入NAND要这样做才行:

假设通过DNW把文件放在0X50008000这个位置上。

nand erase 0 100000

第一:把50008000写入NAND的0地址上,每次写入大小都是一个page(4K)。

nand write 50008000 0 1000

第二:把50008800写入NAND的1000地址上。

nand write 50008800 1000 1000

第三:把50009000写入NAND的2000地址上。

nand write 50009000 2000 1000

第四:把50009800写入NAND的3000地址上。

nand write 50009800 3000 1000

最后,把剩余的写完:

nand write 5000a000 4000 fe000

这样写入,当然读的时候也不能再是简单的每个page这样读了。

第一:读NAND第3个page放到SDRAM指定要运行的地址,比如0x57e00000

为什么第一第二个page不读?因为第一page放的是u-boot-spl-16k.bin,我们不需要它,我们需要的是u-boot.bin。第二个page由于上面写的方法的原因也没有用了。

第二:读第4个page放在SDRAM的0x57e00800,也就覆盖掉前面2K(这个好像可以没有)。

第三:读剩余的放在0x57e01000开始处。

参考下图:



本来u-boot带有一个nand_boot文件正是实现拷贝到SDRAM功能,所以我们必须修改/nand_spl/nand_boot.c内容如下:

#include <common.h>
#include <nand.h>
#include <asm/io.h>

#include <asm/arch/s3c6410.h>
/*
* address format
* 17 16 9 8 0
* --------------------------------------------
* | block(12bit) | page(5bit) | offset(9bit) |
* --------------------------------------------
*/
#define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
#define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
#define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)

static void nandll_read_page (uchar *buf, ulong addr, int large_block)
{
int i;
int page_size = 512;

if (large_block==1)
page_size = 2048;
if (large_block==2)
page_size = 4096;
if(large_block==3)
page_size = 8192;

NAND_ENABLE_CE();

NFCMD_REG = NAND_CMD_READ0;

/* Write Address */
NFADDR_REG = 0;

if (large_block)
NFADDR_REG = 0;

NFADDR_REG = (addr) & 0xff;
NFADDR_REG = (addr >> 8) & 0xff;
NFADDR_REG = (addr >> 16) & 0xff;

if (large_block)
NFCMD_REG = NAND_CMD_READSTART;

NF_TRANSRnB();

/* for compatibility(2460). u32 cannot be used. by scsuh */
for(i=0; i < page_size; i ) {
*buf = NFDATA8_REG;
}

NAND_DISABLE_CE();
//return 0;
}

/*
* Read data from NAND.
*/
static void nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
{
uchar *buf = (uchar *)dst_addr;
int i;
uint page_shift = 9;

if (large_block==1)
page_shift = 11;

if(large_block==2)
page_shift = 12;

if(large_block==3)
page_shift =13;

if(large_block == 2)
{
/* Read pages */
for (i = 2; i < 4; i , buf =(1<<(page_shift-1))) {
nandll_read_page(buf, i, large_block);
}


/* Read pages */
for (i = 4; i < (size>>page_shift); i , buf =(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}

}else if(large_block == 3) //K9GAG08U0E
{
/* Read pages */
for (i = 0; i < 4; i , buf =(1<<(page_shift-2))) {
nandll_read_page(buf, i, large_block);
}


/* Read pages */
for (i = 4; i < (0x40000>>page_shift); i , buf =(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
else
{
for (i = 0; i < (0x3c000>>page_shift); i , buf =(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
//return 0;
}

void nand_boot(void)
{
int large_block = 0;
int i;
vu_char id;
__attribute__((noreturn)) void (*uboot)(void);

NAND_ENABLE_CE();
NFCMD_REG=NAND_CMD_RESET;
NF_TRANSRnB();


NFCMD_REG = NAND_CMD_READID;
NFADDR_REG = 0x00;

NF_TRANSRnB();

/* wait for a while */
for (i=0; i<200; i );

int factory = NFDATA8_REG;
id = NFDATA8_REG;

int cellinfo=NFDATA8_REG;
int tmp= NFDATA8_REG;

//int childType=tmp & 0x03; //Page size
int childType=cellinfo; //Page size

if (id > 0x80)
{
large_block = 1;
}

if(id == 0xd5 && childType==0x94 )//K9GAG08U0D
{
large_block = 2;

}
if(id == 0xd5 && childType==0x14 )//K9GAG08U0M
{
large_block = 2;

}
if(id == 0xd5 && childType==0x84 )//K9GAG08U0E
{
large_block = 3;

}
if(id==0xd7)//K9LBG08U0D
{
large_block = 2;
}
if(factory==0x2c && id == 0x48) //MT29F16G08ABACAWP
{
large_block = 2;

}if(factory==0x2c && id == 0x38) //MT29F8G08ABABAWP
{
large_block = 2;

}


/* read NAND Block.
* 128KB ->240KB because of U-Boot size increase. by scsuh
* So, read 0x3c000 bytes not 0x20000(128KB).
*/
nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x80000, large_block);
uboot = (void *)CONFIG_SYS_PHY_UBOOT_BASE;
(*uboot)();
}

注意nandll_read_blocks()函数里有这段:

if(large_block == 2)
{
/* Read pages */
for (i = 2; i < 4; i , buf =(1<<(page_shift-1))) {
nandll_read_page(buf, i, large_block);
}

i的值一开始等于2的意思是跳过NAND开始第一个page放的u-boot-spl-16k.bin。

3.制作用于烧录到NAND的u-boot-nand.bin文件。

如果我们编译的u-boot-spl-16k小于4k,那么我们需要自己把它补充到4K再放到u-boot.bin的开头,合成一个u-boot-nand.bin。嫌hex手工修改麻烦的话,也可以在建立一个文件,内容如下:

#!/bin/sh
rm -f u-boot-hand.bin
cat nand_spl/u-boot-spl-16k.bin >> temp
cat zero-16k.bin >> temp
split -b 4k temp 

mv xaa u-boot-4k.bin
cat u-boot-4k.bin >> u-boot-hand.bin
cat u-boot.bin >> u-boot-hand.bin

rm -f temp 
rm -f u-boot-4k.bin
rm -f xa*

rm -f /mnt/hgfs/share/u-boot.bin
rm -f /mnt/hgfs/share/u-boot-nand.bin
cp u-boot.bin /mnt/hgfs/share/u-boot.bin
cp u-boot-hand.bin /mnt/hgfs/share/u-boot-nand.bin

root@ubuntu:/home/my/u-boot-2012.10# ./rc

这时在当前目录下就有一个可以烧录的u-boot-hand.bin.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值