桂林电子科技大学毕业设计(论文)报告用纸 第 21 页 共 56 页
3.4 U-Boot Nor flash驱动的移植
Nor flash在uboot中的配置信息:
/*----------------------------------------------------------------------- * FLASH and environment organization */
#define CFG_MAX_FLASH_BANKS2/* max number of memory banks*/ #define CFG_MAX_FLASH_SECT35/* max number of sectors on one chip*/
/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT(2*CFG_HZ) /* Timeout for Flash Erase */ #define CFG_FLASH_WRITE_TOUT(2*CFG_HZ) /* Timeout for Flash Write */
原来代码中是SST39VF3201,现在板子用的是AM29LV160DB。板子上有两个flash一个是内部flash大小为500KB基址是0x00000000另一个是外部flash大小为1MB基址是0x80000000,我们把编译好后的uboot烧写到内部flash中。
它们的操作函数在u-boot-1.1.6/LPC2468OEM_Board/flash.c中实现。我们对flash.c做相应的修改即可。修改相应的flash初始化的信息,主要是扇区大小分布和一些相关信息。如下所示: ulong flash_init (void) { int j, k; ulong size = 0; ulong flashbase = 0;
flash_info[0].flash_id = (PHILIPS_LPC2468 & FLASH_VENDMASK); flash_info[0].size = 0x007D000;/* 512 - 12 KB */内部flash flash_info[0].sector_count = 27; memset (flash_info[0].protect, 0, 27); flashbase = 0x00000000; for (j = 0, k = 0; j < 8; j++, k++) { flash_info[0].start[k] = flashbase; flashbase += 0x00001000;
21
桂林电子科技大学毕业设计(论文)报告用纸 第 22 页 共 56 页
}
for (j = 0; j < 14; j++, k++) { flash_info[0].start[k] = flashbase; flashbase += 0x00008000; }
for (j = 0; j < 5; j++, k++) { flash_info[0].start[k] = flashbase; flashbase += 0x00001000; }
size += flash_info[0].size;
// Note the bank offsets are defined as follow:
// - 1st Bank: 0x00000000 (images at 0x00100000, 0x00800000, 0x00900000) // - 2nd Bank: 0x00400000 (images at 0x00500000, 0x00C00000, 0x00D00000) // - 3rd Bank: 0x00200000 (images at 0x00300000, 0x00A00000, 0x00B00000) // - 4th Bank: 0x00600000 (images at 0x00700000, 0x00E00000, 0x00F00000) flash_info[1].flash_id = (AMD_MANUFACT & FLASH_VENDMASK); flash_info[1].size = 0x00200000; /* 1st 2 MB */ 外部flash flash_info[1].sector_count = 35; memset (flash_info[1].protect, 0, 35); flashbase = AMD_BASEADDR; for (j=0; j<1; j++) {
flash_info[1].start[j] = flashbase; flashbase += 0x2000;/* 8 Kw sectors */ }
for (j=1; j<3; j++) {
flash_info[1].start[j] = flashbase; flashbase += 0x1000;/* 4 Kw 2 sectors */ }
for (j=3; j<4; j++) {
flash_info[1].start[j] = flashbase; flashbase += 0x4000;/* 16 Kw 1 sectors */ }
22
桂林电子科技大学毕业设计(论文)报告用纸 第 23 页 共 56 页
for (j=4; j<35; j++) {
flash_info[1].start[j] = flashbase; flashbase += 0x8000;/* 32 Kw sectors */ }
size += flash_info[1].size;
/* Protect monitor and environment sectors */ flash_protect (FLAG_PROTECT_SET, 0x0,
0x0 + monitor_flash_len - 1, &flash_info[0]);
#ifdef CFG_ENV_IS_IN_FLASH flash_protect (FLAG_PROTECT_SET, CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); #endif
return size; }
到此uboot的nor flash驱动可以跑起来了。
3.5 NAND Flash 驱动移植
NAND Flash 驱动是从linux2.6内核移植过来的,因此它是按照linux MTD 系统层次结构来编写的(关于MTD的介绍将在移植linux驱动的时候做介绍)。它在MTD层下实现了通用的NAND驱动(主要是drivers/nand/nand_base.c文件实现的),因此它的芯片级的nand驱动比较容易。
Nand驱动在include/configs/LPC2468OEM_Board.h文件中的配置
#define CONFIG_COMMANDS(CONFIG_CMD_DFL | CFG_CMD_FAT | CFG_CMD_NET | CFG_CMD_MMC | CFG_CMD_NAND | CFG_CMD_DHCP | CFG_CMD_PING | CFG_CMD_I2C)
23
桂林电子科技大学毕业设计(论文)报告用纸 第 24 页 共 56 页
/*
* NAND Flash */
#define CFG_MAX_NAND_DEVICE1 #define NAND_MAX_CHIPS1
#define CFG_NAND_BASE0x81000000 //基地址
需要在board/LPC2468OEM_Board /nand.c中实现三个函数:
static void hwcontrol(struct mtd_info *mtd, int cmd)完成硬件控制,
static void nand_select_chip(struct mtd_info * mtd , int chip)完成芯片选择;void board_nand_init(struct nand_chip *nand)完成nand的初始化工作,具体代码见源代码。
#include
#include /*
* CLE at A21 * ALE at A22 CE P[0] 25 */
#define MASK_CLE (1<<21) #define MASK_ALE (1<<22)
static void hwcontrol(struct mtd_info *mtd, int cmd) {
struct nand_chip *this = mtd->priv; ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
IO_ADDR_W &= ~(MASK_ALE|MASK_CLE);
switch (cmd) {
case NAND_CTL_CLRNCE: IOCLR0 |=(1<<25); break;
case NAND_CTL_SETNCE: IOSET0 |=(1<<25);
24
桂林电子科技大学毕业设计(论文)报告用纸 第 25 页 共 56 页
break; case NAND_CTL_SETCLE: IO_ADDR_W |= MASK_CLE; break;
case NAND_CTL_SETALE: IO_ADDR_W |= MASK_ALE; break; }
this->IO_ADDR_W = (void *) IO_ADDR_W; }
static void nand_select_chip(struct mtd_info * mtd , int chip) {
struct nand_chip *this = mtd->priv; switch(chip) { case -1:
this->hwcontrol(mtd, NAND_CTL_SETNCE); break; case 0:
this->hwcontrol(mtd, NAND_CTL_CLRNCE); break; } }
void board_nand_init(struct nand_chip *nand) {
/* IO_ADDR_R and IO_ADDR_W set by nand-driver using CFG_NAND_BASE */ nand->hwcontrol = hwcontrol; /* nand->dev_ready = ; */
nand->eccmode = NAND_ECC_SOFT; //采用软件方式 nand->chip_delay = 25;/* us */
nand->options = NAND_SAMSUNG_LP_OPTIONS; //nand->cmdfunc = nand_command; nand->select_chip = nand_select_chip;
25