移植NAND花了我一下午的時間才把他弄明白,解決錯誤的途中,我也學到了更多的東西,希望大家自己要嘗試親手移植,不要老是用別人的補丁文件,自己你懂手做了才真正是你的東西。
分析了一下Uboot中Nandflash的驅動,u-boot-2009.08使用的是和Linux內核一樣的MTD(內存技術設備)架構。在Uboot下對Nand的支持體現在命令行下實現對nand flash的操作,為:nand info,nand device,nand read,nand write,nand erease,nand bad。用到的主要數據結構有:struct nand_flash_dev,struct nand_chip。前者包括主要的芯片型號,存儲容量,設備ID,I/O總線寬度等信息;后者是具體對nand flash進行操作時用到的信息。?
u-boot啟動到第二個階段后,在/cpu/arm920t/board.c這個文件中start_armboot函數里,有下面的代碼:?
~~~
#if defined(CONFIG_CMD_NAND)
?? ?puts ("NAND:? ");
?? ?nand_init();?? ??? ?/* go init the NAND */
#endif
~~~
?所以,我們只要定義了CONFIG_CMD_NAND這個宏,就會開始nand初始化。通過用Source Insight來做代碼分析來一步步地查看函數執行過程,得出下面的nand執行流程:
1./cpu/arm920t/board.c文件中的start_armboot函數調用/drivers/mtd/nand/nand.c文件中的nand_init函數;
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.s3c2410_nand.c就是我們做移植需要實現的文件,是與具體的硬件密切相關的。
5.nand_scan函數會調用同文件下的nand_scan_ident等函數。
從這里我們得知,我們要把nand移植到2440上,就要修改s3c2410_nand.c這個文件!因為對nand flash的操作,實際上就是對nand控制器的操作,而2440的nand控制器和2410相比,有很大的不同!我們的修改工作量主要也是在這里。在這里我就在源文件上修改了。
首先在include/configs/fl2440.h中相應位置增加必要的宏定義:
~~~
#define CONFIG_CMD_NAND
/* NAND flash settings */
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4E000000
#define CONFIG_SYS_MAX_NAND_DEVICE ? ? 1
#define CONFIG_MTD_NAND_VERIFY_WRITE ?1
#define NAND_SAMSUNG_LP_OPTIONS ? ? ? 1 ???/*注意,這個定義很重要,因為我們用的是大塊nand!! */
#undef ?CONFIG_ENV_IS_IN_FLASH ? ? ? ? ? ? ??
#define CONFIG_ENV_IS_IN_NAND ? ? 1 ? ????/* 環境變量的保存位置 */
#endif
~~~
修改/drivers/mtd/nand/Makefile,在其中添加:
COBJS-y += s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2410_nand.o?
下面的工作主要是修改drivers/mtd/nand/s3c2410_nand.c文件,首先修改27行如下
~~~
#if ?0
#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 NFECC0 ? ? ? ? ?__REGb(NF_BASE + 0x14)
#define NFECC1 ? ? ? ? ?__REGb(NF_BASE + 0x15)
#define NFECC2 ? ? ? ? ?__REGb(NF_BASE + 0x16)
#endif?
#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 ? ? NFMECCD0 ? ?__REGi(NF_BASE + 0x14)
#define ? ? NFMECCD1 ? ?__REGi(NF_BASE + 0x18)
#define ? ? NFSECCD ? ? ? __REGi(NF_BASE + 0x1C)
#define ? ?NFSTAT ? ? ? ? ? __REGb(NF_BASE + 0x20)
#define ? ?NFSTAT0 ? ? ? ? __REGi(NF_BASE + 0x24)
#define ? ?NFSTAT1 ? ? ? ? __REGi(NF_BASE + 0x28)
#define ? ?NFMECC0 ? ? ? ?__REGi(NF_BASE + 0x2C)
#define ? ?NFMECC1 ? ? ? ?__REGi(NF_BASE + 0x30)
#define ? ?NFSECC ? ? ? ? ? __REGi(NF_BASE + 0x34)
#define ? ?NFSBLK ? ? ? ? ? __REGi(NF_BASE + 0x38)
#define ? ?NFEBLK ? ? ? ? ? __REGi(NF_BASE + 0x3c)
~~~
修改下面的宏:
~~~
#define S3C2410_NFCONF_EN ? ? ? ? ?(1<<15)
#define S3C2410_NFCONF_512BYTE ? ? (1<<14)
#define S3C2410_NFCONF_4STEP ? ? ? (1<<13)
#define S3C2410_NFCONF_INITECC ? ? (1<<12)
#define S3C2410_NFCONF_nFCE ? ? ? ?(1<<11)
#define S3C2410_NFCONF_TACLS(x) ? ?((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x) ? ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x) ? ((x)<<0)
#define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8
~~~
uboot代碼中的NAND Flash的讀寫驅動中存在一些錯誤,需要進行修改后才能完成,主要修改drivers/mtd/nand/s3c2410_nand.c文件,首先修改27行如下:
修改s3c2410_hwcontrol函數 ?,這個函數用來控制發送命令還是地址。board_nand_init函數。
首先聲明一個全局變量?ulong?IO_ADDR_W?=?NF_BASE;?
~~~
#ifdef CONFIG_S3C2410_NAND_HWECC ?//這個宏沒有定義,所以我們不用關心ECC之類的。
~~~
~~~
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%02x\n", cmd, ctrl);
? ? ? ? ?if (ctrl & NAND_CTRL_CHANGE) {
? ? ??ulong IO_ADDR_W = NF_BASE;? ? ? ? ??
? ? ? ? ? ?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_S3C2440) ?
? ? ? ? if (ctrl & NAND_NCE) ?
? ? ? ? ? ? NFCONT&= ~S3C2410_NFCONT_nFCE; ?//源碼中是NFCONF,S3C2410_NFCONF_nFCE
? ? ? ? ? ? ? ??
? ? ? ? else ?
? ? ? ? ? ?NFCONT|=S3C2410_NFCONT_nFCE; ?//源碼中是NFCONF,S3C2410_NFCONF_nFCE
? ? ? ? ? #endif ?
? ? ? }
? ? ?if (cmd != NAND_CMD_NONE)
? ? ? ? ?// ? ? writeb(cmd, chip->IO_ADDR_W);
? ? ? ? ?writeb(cmd, (void *)IO_ADDR_W);
}
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 */
? ? ? ? twrph0 = 0; twrph1 = 4; tacls = 2;
? ? ? ? ?cfg = 0;
? ? ? ? cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
? ? ? ? cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
? ? ? ? cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
? ? ? ?NFCONF = cfg;
? ? ?cfg = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);
? ? ?NFCONT = cfg; ? ? ??
? ?* initialize nand_chip data structure */
? ? ? ? nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010; ?//NFSTAT 的地址是0x4e000010
? ? ?/* read_buf and write_buf are default */
? ? ? ? /* read_byte and write_byte are default */
? ? ? ? /* hwcontrol always must be implemented */
? ? ? ? nand->cmd_ctrl = s3c2410_hwcontrol;
? ? ? nand->dev_ready = s3c2410_dev_ready;
/*以下是校驗碼的設置,可以不用設置*/
#ifdef CONFIG_S3C2410_NAND_HWECC
? ? ? ? nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
? ? ? ? nand->ecc.calculate = s3c2410_nand_calculate_ecc;
? ? ? ? nand->ecc.correct = s3c2410_nand_correct_data;
? ? ? ? nand->ecc.mode = NAND_ECC_HW3_512;
#else
? ? ? ? nand->ecc.mode = NAND_ECC_SOFT;
#endif
ifdef CONFIG_S3C2410_NAND_BBT
? ? ? ? nand->options = NAND_USE_FLASH_BBT;
#else
? ? ? ? nand->options = 0;
#endif
?DEBUGN("end of nand_init\n");
?return 0;
}
~~~
突然發現我自己都愛上了自己的執著精神,哈哈,回去吃完飯了。
參考地址:http://blog.csdn.net/yanghao23/article/details/7700699
- 前言
- FL2440的u-boot-2010.09移植(一)
- FL2440的u-boot-2010.09移植(二)
- FL2440的U-boot-2009.08移植(三)支持Nor FLASH
- FL2440的U-boot-2009.08移植(四) 支持DM900網卡
- FL2440的U-boot-2009.08移植(五)uboot架構中NAND Flash驅動修改
- FL2440如何利用JLINK燒寫U-boot到NAND Flash中
- uboot中的快捷菜單的制作說明
- env_relocate 函數深入分析
- U-boot mkimage指定Linux內核地址時的兩種方式
- 實現u-boot對yaffs/yaffs2文件系統下載的支持