U-Boot中SMDK2410的NAND Flash驅(qū)動(dòng)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
標(biāo)準(zhǔn)的SMDK2410板不支持NAND Flash,啟動(dòng)的時(shí)候是這樣的:
U-Boot 1.1.2 (May 28 2006 - 08:20:50)
U-Boot code: 33F80000 -> 33F99A14 BSS: -> 33F9DB0C
RAM Configuration:
Bank #0: 30000000 64 MB
Flash: 1 MB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
有NAND支持的多一行(NAND 64MB):
U-Boot 1.1.2 (May 28 2006 - 08:36:42)
U-Boot code: 33F80000 -> 33F99A14 BSS: -> 33F9DB0C
RAM Configuration:
Bank #0: 30000000 64 MB
Flash: 1 MB
NAND: 64 MB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
怎么實(shí)現(xiàn)這種支持呢?U-Boot真是功能強(qiáng)大的Bootloader,在/inclued/configs/smdk2410.h中有這么一段
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS
(CONFIG_CMD_DFL |
CFG_CMD_CACHE |
CFG_CMD_NAND |
/*CFG_CMD_EEPROM |*/
/*CFG_CMD_I2C |*/
/*CFG_CMD_USB |*/
CFG_CMD_REGINFO |
CFG_CMD_DATE |
CFG_CMD_ELF)
/* this must be included after the definition of CONFIG_COMMANDS (if any) */
需要說(shuō)明一下CONFIG_CMD_DFL,定義的是默認(rèn)指令,包括bdinfo、bootd、coninfo、saveenv、 flinfo、erase、protect、iminfo、imls、itest、loadb、loads、md、mm、nm、mw、cp、cmp、 crc、base、loop、loopw、mtest、sleep、bootp、tftpboot、rarpboot、run等常用指令,這些指令我以后會(huì)結(jié)合使用做適當(dāng)?shù)恼f(shuō)明。關(guān)于指令的宏定義說(shuō)明可以看看U-Boot的README里面的Monitor Functions。這就是對(duì)編譯成功后的U-Boot支持的命令的定義,SMDK2410默認(rèn)的smdk2401.h中,紅色字部分是注釋掉的。但是要支持NAND Flash遠(yuǎn)沒有去掉一個(gè)注釋這么簡(jiǎn)單。
我們可以試試單純把這個(gè)注釋去掉是什么結(jié)果,老步驟:
make distclean
make smdk2410_config
make
……一堆編譯信息飄過(guò)……
出錯(cuò)了,位置指向cmd_nand.c這個(gè)文件,好幾處錯(cuò)誤。原因是SMDK2410的配置里根本就沒有對(duì)NAND Flash支持的宏定義和函數(shù)。怎么辦?自己寫么?好在U-Boot里有另外一個(gè)可以讓我們借鑒的配置VCMA9。在Source Navigator里搜索一下vcma,看看vcma9.h和vcma9.c,可以從中摘取出一段宏定義和一些函數(shù)聲明。網(wǎng)上有人的做法是將其放在 smdk2410.h和smdk2410.c中,但是白癡的cross-2.95.3和cross-3.2都不能認(rèn)到cmd_nand.c中已經(jīng)在 smdk2410.h和smdk2410.c中定義的宏所指的函數(shù),就算是加上extern的也不行。也許你沒有看懂剛才這句話,解釋一下,例如 cmd_nand.c中有這樣一段
if(ale_wait)
NAND_WAIT_READY(nand); /* do the worst case 25us wait */
else
udelay(10);
其中NAND_WAIT_READY(nand),在smdk2410.h中定義為
#define NAND_WAIT_READY(nand) NF_WaitRB()
而NF_WaitRB()在smdk2410.c中定義為
static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
while (!(nand->NFSTAT & (1<<0)));
}
這個(gè)編譯器死活說(shuō)NF_WaitRB()未定義,就算是我在cmd_nand.c中加上這樣一句也不起作用
extern void NF_WaitRB(void)
也許是我C學(xué)的不好,搞不清楚多個(gè)文件共同編譯的時(shí)候static inline的引用關(guān)系,不管它,我把這些宏中定義的函數(shù)的申明放在了cmd_nand.c中,為了不太無(wú)恥,我在前面加上了針對(duì)SMDK2410的選擇性編譯。(請(qǐng)注意,下面這些代碼拷貝到cmd_nand.c中的適當(dāng)位置,cmd_nand.c中有許多選擇性編譯的宏,注意放的位置,不要被忽略掉了)
/*-----------------------------------------------------------------------
* NAND flash basic functions
* Added by Lu Xianzi 2006.5.27
* Copied from board/mpl/vcma9/vcma9.h & vcma9.c
*/
#if (CONFIG_SMDK2410)
#include
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;
static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;
case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}
static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
while (!(nand->NFSTAT & (1<<0)));
}
static inline void NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFDATA = data;
}
static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1<<12);
}
static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFECC);
}
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */
NF_Reset();
}
void nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX ", (ulong)nand);
#endif
printf ("%4lu MB ", nand_probe((ulong)nand) >> 20);
}
#endif /* (CONFIG_SMDK2410) */
然后把下面這些宏定義放在smdk2410.h中
/*-----------------------------------------------------------------------
* NAND flash settings
* Added by Lu Xianzi 2006.5.27
* Copied from include/conifgs/vcma9.h
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
#define NAND_WAIT_READY(nand) NF_WaitRB()
#define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH)
#define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW)
#define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d)
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
#define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d)
#define WRITE_NAND(d, adr) NF_Write(d)
#define READ_NAND(adr) NF_Read()
/* the following functions are NOP's because S3C24X0 handles this in hardware */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/* #define CONFIG_MTD_NAND_VERIFY_WRITE 1 */
/* This definition above is commented by Lu Xianzi. 2006.05.28
Because there's no definition of a macro called __mem_pci,
there will be a link error.
*/
#define CONFIG_MTD_NAND_ECC_JFFS2 1
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
注意這段宏定義中與vcma9.h中不同的是我標(biāo)記紅色的部分,網(wǎng)上的一些移植說(shuō)明沒有解決這個(gè)問(wèn)題,導(dǎo)致最后的鏈接無(wú)法通過(guò)。事實(shí)上,我這樣做取消了cmd_nand.c中對(duì)NAND Flash的寫校驗(yàn)和ECC校驗(yàn)。__mem_pci是一個(gè)什么東西我也不知道,在U-Boot目錄下搜索包含“__mem_pci”字串的文件也沒有找到,除了使用它的/include/asm/io.h。順便說(shuō)一下,這個(gè)麻煩是從cmd_nand.c中的nand_write_page函數(shù)中 readb(nand->IO_ADDR)這個(gè)宏開始的,你可以用Source Navigator查找一下引用,最后就指向沒有__mem_pci宏的這個(gè)問(wèn)題。希望有高手看到這篇文章,并給我指出解決的辦法,呵呵。U-Boot中SMDK2410的NAND Flash驅(qū)動(dòng) - xinli - xinli的Blog
做完這些修改,就再來(lái)一次老步驟
make distclean
make smdk2410_config
make
………………
生成了U-Boot.bin。NAND Flash的驅(qū)動(dòng)到此完成,好不好使呢?試試看。上次我們已經(jīng)在板子里燒寫進(jìn)了U-Boot,是一個(gè)可以支持串口傳輸?shù)腢-Boot,要是現(xiàn)在還用 sjf2410往里燒U-Boot.bin就太冤大頭了??梢岳么谶M(jìn)行傳輸,操作步驟如下:
使用超級(jí)終端,建立一個(gè)連接:文件〉新建連接;名稱隨便,圖表隨便,確定;連接時(shí)使用選擇你的開發(fā)板所接的COM口;端口設(shè)置中,每秒位數(shù)選115200,數(shù)據(jù)位選8,奇偶校驗(yàn)選無(wú),停止位選1,數(shù)據(jù)流控制選“無(wú)”。打開開發(fā)板的電源,出現(xiàn)以下提示:
U-Boot 1.1.2 (May 28 2006 - 08:20:50)
U-Boot code: 33F80000 -> 33F99A14 BSS: -> 33F9DB0C
RAM Configuration:
Bank #0: 30000000 64 MB
Flash: 1 MB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
LXZROB # loadb
## Ready for binary (kermit) download to 0x33000000 at 115200 bps...
loadb這個(gè)指令以kermit協(xié)議從串口下載二進(jìn)制文件到開發(fā)板的內(nèi)存中,默認(rèn)下載到0x33000000。當(dāng)然你可以改在別的地址,例如:loadb 30000000就是下載到0x30000000。這時(shí)候選擇超級(jí)終端菜單上:傳送〉發(fā)送文件,文件名選擇編譯好的U-Boot.bin,協(xié)議選擇 Kermit,點(diǎn)發(fā)送??梢钥吹桨l(fā)送進(jìn)度。
發(fā)送結(jié)束出現(xiàn)提示:
## Total Size = 0x00019a14 = 104980 Bytes
## Start Addr = 0x33000000
這時(shí)可以測(cè)試新的修改好不好使:
LXZROB # go 33000000
## Starting application at 0x33000000 ...
U-Boot 1.1.2 (May 28 2006 - 08:36:42)
U-Boot code: 33F80000 -> 33F99A14 BSS: -> 33F9DB0C
RAM Configuration:
Bank #0: 30000000 64 MB
Flash: 1 MB
NAND: 64 MB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
LXZROB #
go指令可以直接執(zhí)行內(nèi)存地址上的程序,例如剛才下載到0x33000000的新的支持NAND的U-Boot,可以看到出現(xiàn)了 “NAND: 64MB”這一項(xiàng)。輸入help,你會(huì)看到比剛才的U-Boot多了一組指令nand,輸入help nand,可以看到更加細(xì)節(jié)的指令:
LXZROB # help nand
nand info - show available NAND devices
nand device [dev] - show or set current device
nand read[.jffs2[s]] addr off size
nand write[.jffs2] addr off size - read/write `size' bytes starting
at offset `off' to/from memory address `addr'
nand erase [clean] [off size] - erase `size' bytes from
offset `off' (entire device if not specified)
nand bad - show bad blocks
nand read.oob addr off size - read out-of-band data
nand write.oob addr off size - read out-of-band data
輸入nand info,可以看到:
LXZROB # nand info
Device 0: Samsung unknown 64Mb at 0x4e000000 (64 MB, 16 kB sector)
說(shuō)明我們的驅(qū)動(dòng)成功了。也可以試試其他指令。
但是現(xiàn)在在NOR Flash中的U-boot還是不支持NAND的,需要重新燒寫。U-Boot支持自己燒寫自己。
先看看NOR Flash的情況:
LXZROB # flinfo
Bank # 1: AMD: 1x Amd29LV800BB (8Mbit)
Size: 1 MB in 19 Sectors
Sector Start Addresses:
00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO)
00020000 00030000 00040000 00050000 00060000
00070000 00080000 00090000 000A0000 000B0000
000C0000 000D0000 000E0000 000F0000 (RO)
一共有19個(gè)sector,其中前5個(gè)總計(jì)128kb的sector有U-Boot程序,是寫保護(hù)的。要燒寫首先要去掉寫保護(hù):
LXZROB # protect off 0 1ffff
Un-Protected 5 sectors
LXZROB # flinfo
Bank # 1: AMD: 1x Amd29LV800BB (8Mbit)
Size: 1 MB in 19 Sectors
Sector Start Addresses:
00000000 00004000 00006000 00008000 00010000
00020000 00030000 00040000 00050000 00060000
00070000 00080000 00090000 000A0000 000B0000
000C0000 000D0000 000E0000 000F0000 (RO)
可以看到寫保護(hù)已經(jīng)去掉,擦除:
LXZROB # erase 0 1ffff
Erasing sector 0 ... ok.
Erasing sector 1 ... ok.
Erasing sector 2 ... ok.
Erasing sector 3 ... ok.
Erasing sector 4 ... ok.
Erased 5 sectors
然后燒寫:
LXZROB # cp.b 33000000 0 19a14
Copy to Flash... done
cp.b是用來(lái)拷貝內(nèi)存信息的,其格式為cp [.b, .w, .l] source target count,輸入這樣的指令是因?yàn)閯偛虐殉绦蛳螺d到了0x33000000,NOR Flash的起始地址是0x0,下載的程序長(zhǎng)度為0x19a14。重啟開發(fā)板,U-Boot的燒寫就完成了。