11. 为了在uboot里显示你现在的nand的大小,修改include/linux/mtd/nand_ids.h的结构体nand_flash_ids /*这个结构体是为了在初始化nand时,用读到的id和这里面匹配,如果有就输出该nand的信息*/
注意:根据朋友小子 提醒,其实不用添加这一步的,而是在drivers/mtd/nand/nand_ids.h里已经有定义了,可以去看一下,这里也不删这段了,就当是告诉这结构体每一位的作用
static struct nand_flash_dev nand_flash_ids[] = {
....../*结构体nand_flash_dev 在doc2000.h中定义*/
/*厂家 型号,生产商编号,本模块的编号,总共容纳地址的位数,存储页字节数是否为256 ,地址需要多少字节数减一(行列地址总共) ,擦除1个block的大小,是否为16位总线*/
{"Samsung KM29N16000",NAND_MFR_SAMSUNG, 0x64, 21,1, 2, 0x1000, 0},
{"Samsung K9F2G08U0B", NAND_MFR_SAMSUNG, 0xDA, 28, 0, 4, 0x10000, 0},
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000, 0},
......
};
其中"SamsungK9F2G08U0B"是nand的名字,无关紧要
NAND_MFR_SAMSUNG是该nand的makercode 三星的是0xec
0xDA是本模块的编号,也就是device code,笔者的为0xda
28是你的芯片总共容纳的地址位数,也就是有效的地址位数,这个地方控制你显示的大小的。
0, 即是否为256字节一页,笔者的为2048一页,所以为0
0x10000为擦除1个block的大小,简单来说就是一个block的大小,本flash为1block= 64*1page = 64*2048 = 0x20000
1为是否16位总线,笔者的为8位
12. 修改lib_arm中的board.c添加几个debug信息,即点几个灯
#include<common.h>
#include <command.h>
#include <malloc.h>
#include <devices.h>
#include <version.h>
#include <net.h>
......
static intdisplay_banner (void)
{
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
gpio->GPFBDAT =0x7f8e;
//在串口初始化和console初始化完成,串口输出信息之前,LED1、LED2、LED3会亮起!
printf ("\n\n%s\n\n", version_string);
debug ("U-Boot code: %08lX -> %08lX BSS: ->%08lX\n",
_armboot_start,_bss_start, _bss_end);
printf("U-Boot code: %08lX -> %08lX BSS: ->%08lX\n",
_armboot_start, _bss_start, _bss_end);
#ifdef CONFIG_MODEM_SUPPORT
debug ("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif
return (0);
}
......
voidstart_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
#ifndefCFG_NO_FLASH
ulong size;
#endif
#ifdefined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
......
gpio->GPFDAT = 0x7f0e;
//在进入命令提示符之前,四个LED会同时亮起!
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
/* NOTREACHED - no way out of command loop except booting */
}
/*到这里,应该是可以编译通过的,否则就是编辑的时候出现了错误*/
15. 修改nor flash写入功能的代码,因为AMD与SST写时序有差别,所以要修改
在board/gt2440/flash.c里
//#define CMD_ERASE_CONFIRM 0x00000030
#define CMD_ERASE_CONFIRM 0x00000050
#if defined(CONFIG_SST_VF1601)
#define MEM_FLASH_ADDR1 (*(volatileu16 *)(CFG_FLASH_BASE + (0x00005555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatileu16 *)(CFG_FLASH_BASE + (0x00002AAA << 1)))
#else
#define MEM_FLASH_ADDR1 (*(volatileu16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatileu16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
#endif
#elif defined(CONFIG_AMD_LV800)
(AMD_MANUFACT& FLASH_VENDMASK) |
(AMD_ID_LV800B& FLASH_TYPEMASK);
#elif defined(CONFIG_SST_VF1601)
(SST_MANUFACT& FLASH_VENDMASK) |
(SST_ID_xF1601& FLASH_TYPEMASK);
#else
#error "Unknown flash configured"
#ifndef CONFIG_SST_VF1601
……
flash_info[i].start[j] =
flashbase+ (j - 3) * MAIN_SECT_SIZE;
}
#else
flash_info[i].start[j]=
flashbase+ (j) * MAIN_SECT_SIZE;
#endif
void flash_print_info (flash_info_t * info)
case (SST_MANUFACT & FLASH_VENDMASK):
printf("SST:");
break;
……
case (SST_ID_xF1601 & FLASH_TYPEMASK):
printf("1xSST39VF1601(2MB)\n");
break;
int flash_erase (flash_info_t * info, ints_first, int s_last)
……
#ifdef CONFIG_SST_VF1601
if((info->flash_id & FLASH_VENDMASK) !=
(SST_MANUFACT& FLASH_VENDMASK)) {
returnERR_UNKNOWN_FLASH_VENDOR;
}
#else
if ((info->flash_id & FLASH_VENDMASK)!=
(AMD_MANUFACT & FLASH_VENDMASK)) {
returnERR_UNKNOWN_FLASH_VENDOR;
}
#endif
int flash_erase (flash_info_t * info, ints_first, int s_last)
#if 0
/*wait until flash is ready */
chip= 0;
do{
result= *addr;
/*check timeout */
if(get_timer_masked () >
CFG_FLASH_ERASE_TOUT) {
MEM_FLASH_ADDR1= CMD_READ_ARRAY;
chip= TMO;
break;
}
if(!chip
&& (result & 0xFFFF) &BIT_ERASE_DONE)
chip= READY;
if(!chip
&& (result & 0xFFFF) &BIT_PROGRAM_ERROR)
chip= ERR;
}while (!chip);
MEM_FLASH_ADDR1= CMD_READ_ARRAY;
if(chip == ERR) {
rc= ERR_PROG_ERROR;
gotooutahere;
}
if(chip == TMO) {
rc= ERR_TIMOUT;
gotooutahere;
}
printf("ok.\n");
}else { /* it was protected */
printf("protected!\n");
}
}
#endif
/**********************************************/
/*wait until flash is ready*/
while(1){
unsignedshort i;
i= *((volatile unsigned short *)addr)& 0x40;
if(i!= (*((volatile unsigned short *)addr) & 0x40))
continue;
if((*((volatileunsigned short *)addr)) & 0x80)
break;
}
printf("ok.\n");
}else { /* it was protected */
printf ("protected!\n");
}
}
static int write_hword (flash_info_t * info, ulong dest,ushort data)
……
// MEM_FLASH_ADDR1= CMD_UNLOCK_BYPASS;
// *addr= CMD_PROGRAM;
MEM_FLASH_ADDR1 = CMD_PROGRAM;
#if 0
/* wait until flash is ready */
chip= 0;
do{
……
*addr= CMD_READ_ARRAY;
if(chip == ERR || *addr != data)
rc= ERR_PROG_ERROR;
#endif
/*waituntil flash is ready*/
while(1){
unsignedshort i = *(volatile unsigned short *)addr & 0x40;
if(i !=(*(volatile unsigned short *)addr & 0x40)) //D6 == D6
continue;
if((*(volatile unsigned short *)addr & 0x80) == (data & 0x80)){
rc = ERR_OK;
break; //D7 == D7
}
在include/configs/gt2440.h加上:
#define CONFIG_SST_VF1601 1
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000/* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number ofsectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE+ 0x070000) /* addr of environment */
#endif
#ifdef CONFIG_SST_VF1601
#define PHYS_FLASH_SIZE 0x00200000/* 2M */
#define CFG_MAX_FLASH_SECT (512) /* max number ofsectors on one chip */
#define CFG_ENV_ADDR (CFG_NAND_BASE + CFG_ENV_OFFSET) /* addrof environment */
#endif
13、支持yaffs根文件系统的烧写(可选)
因为在开发过程中,烧写yaffs根文件系统还是有需要的,但是1.3.4又不支持yaffs的烧写,所以就要手动移植。Yaffs根文件系统主要特点是烧写时第一块是不烧内容的,也就跳过第一块,所以在移植时会在相应的结构体里加入skipfirstblk这个成员。
1.首先在common/cmd_nand.c的496行附近加入
"nandread.yaffs - addr off|partitionsize\n"
"nandwrite.yaffs - addr off|partition size- read/write `size' bytes starting\n"
这两行主要是起提示作用的。
在349附近加入
#ifdefined(ENABLE_CMD_NAND_YAFFS)
} else if ( s != NULL&&
(!strcmp(s, ".yaffs") ||!strcmp(s, ".yaffs1"))){
if (read) {
/* read */
nand_read_options_t opts;
memset(&opts, 0, sizeof(opts));
opts.buffer= (u_char*) addr;
opts.length= size;
opts.offset= off;
opts.readoob= 1;
opts.quiet = quiet;
ret =nand_read_opts(nand, &opts);
} else {
/* write */
nand_write_options_topts;
memset(&opts, 0, sizeof(opts));
opts.buffer= (u_char*) addr;
opts.length= size;
opts.offset= off;
//opts.noecc = 1;
opts.pad =0;
opts.writeoob = 1;
opts.blockalign = 1;
opts.quiet = quiet;
opts.autoplace = 1;
if (s[6] =='1')
opts.forceyaffs = 1;
#ifdefined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
opts.skipfirstblk = 1;
#endif
ret =nand_write_opts(nand, &opts);
}
#endif
/*add to useyaffs*/
2.在include/command.h
加入
#defineENABLE_CMD_NAND_YAFFS 1
#define ENABLE_CMD_NAND_YAFFS_SKIPFB 1
#defineCFG_NAND_YAFFS1_NEW_OOB_LAYOUT 0
3.在include/nand.h里的nand_write_options结构体加入
u_char *buffer; /*memory block containing image to write */
ulong length; /*number of bytes to write */
ulong offset; /*start address in NAND */
int quiet; /*don't display progress messages */
int autoplace; /*if true use auto oob layout */
int forcejffs2; /*force jffs2 oob layout */
int forceyaffs; /*force yaffs oob layout */
int noecc; /*write without ecc */
int writeoob; /*image contains oob data */
int pad; /* pad topage size */
int blockalign; /*1|2|4 set multiple of eraseblocks
*to align to */
int skipfirstblk;//add to use yaffs
};
14、yaffs2根文件系统制作
在说制作时,先要说说制作的工具,首先,内核要支持yaffs根文件系统,就要去打补丁,先到yaffs官网上下载
其中的mkyaffs2image这个工具是有点不正常的,不支持2K的nand,要上网去搜补丁,主要是制作根文件映像时,oob区域不一样导致。