UBOOT-2012-10在OK6410平臺的移植(七)關於NAND啓動

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 [email protected].

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 [email protected].

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開始處。

參考下圖:

28382924_1353258959s8O8.png


本來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.




<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
閱讀(4) | 評論(0) | 轉發(0) |
給主人留下些什麼吧!~~
評論熱議
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章