注意:红色标记为修改的地方
4.3修改NorFlash写入功能的代码
(1)针对EN29LV160AB芯片
具体参考:
gongping11的《u-boot-2010.06移植到TQ2440过程2-nor Flash的移植》文章,网址:http://home.eeworld.com.cn/my/space-uid-67414-blogid-55044.html
IT_114的csdn博客《u-boot-2011.03在TQ2440上的移植(3)--支持norflash启动》网址:http://blog.csdn.net/it_114/article/details/6264897
为flash添加ID号,这个ID 号是一个固定的值,由于是采用了bottom boot block ,从低地址到高地址增长的形式。可知ID 号是2249。添加ID号的函数为:
打开include/flash.h文件194行增加下面两个宏定义
/*添加两种不同扇区方式的ID标号,标号在手册中可以找到*/
#define EON_ID_LV160AB_T 0x22C422C4 /*LV160AB ID (16 M, top boot sector) */
#define EON_ID_LV160AB_B 0x22492249 /*LV160AB ID (16 M, bottom boot sect) */
top boot sect 是第一个分区在最高位,bottom boot sect 是第一个分区在最低位
修改board/sunzl/sunzl2440/flash.c这个文件
//#defineMAIN_SECT_SIZE 0x10000 /* 64 KB */
#defineMAIN_SECT_SIZE 0x8000 /* 32 K Word */
………………
ulong flash_init(void)
{
………………….
#elifdefined(CONFIG_AMD_LV800)
(AMD_MANUFACT &FLASH_VENDMASK) |
(AMD_ID_LV800B &FLASH_TYPEMASK);
#elifdefined(CONFIG_EON_29LV160AB)
(EON_MANUFACT &FLASH_VENDMASK) |/*添加厂商*/
(EON_ID_LV160AB_B& FLASH_TYPEMASK);/*添加芯片的ID号*/
#else
#error "Unknownflash configured"
………………….
if (j <= 3) {
/* 1st one is 8 KB,第一分区的大小是8K字*/
if (j == 0){
flash_info[i].start[j]=
flashbase+ 0;
}
/* 2nd and 3rd are both 4 KB */
if ((j ==1) || (j == 2)) {
flash_info[i].start[j]=
flashbase+ 0x2000 + (j -
1) *
0x1000;
}
/* 4th 16 KB */
if (j == 3){
flash_info[i].start[j]=
flashbase + 0x4000;
}
……………….
void flash_print_info(flash_info_t * info)
{
int i;
switch (info->flash_id &FLASH_VENDMASK) {
case (AMD_MANUFACT &FLASH_VENDMASK):
printf ("AMD: ");
break;
case(EON_MANUFACT & FLASH_VENDMASK):
printf("EON: ") ;
break;
default:
printf ("Unknown Vendor");
break;
}
switch (info->flash_id &FLASH_TYPEMASK) {
case (AMD_ID_LV400B &FLASH_TYPEMASK):
printf ("1x Amd29LV400BB(4Mbit)\n");
break;
case (AMD_ID_LV800B &FLASH_TYPEMASK):
printf ("1x Amd29LV800BB(8Mbit)\n");
break;
case(EON_ID_LV160AB_B & FLASH_TYPEMASK):
printf ("1xEON_29LV160AB (16Mbit)\n");
break;
default:
printf ("Unknown ChipType\n");
……………..
int flash_erase(flash_info_t * info, int s_first, int s_last)
{
……………………..
if ((s_first < 0)|| (s_first > s_last)) {
return ERR_INVAL;
}
if ((info->flash_id &FLASH_VENDMASK) !=
/*(AMD_MANUFACT & FLASH_VENDMASK)) {*/
(EON_MANUFACT & FLASH_VENDMASK)) {
returnERR_UNKNOWN_FLASH_VENDOR;
}
prot = 0;
(2)针对SST39VF1601芯片(芯片型号不同,移植有区别,请对应好自己板子上的芯片做相应的移植)
在虽然S3C2440 和S3C2410 对于Nor Flash 的链接都是一样的,但是SBC2410 使用的AMD 的Nor Flash 芯片,而mini2440 使用的SST 的Nor Flash。这两款芯片在写入时所使用的块大小、时序和指令代码有差别,所以必须根据芯片的数据手册进行修改。主要的差别请看数据手册的对比:
SST39VF1601:
Am29LV160:
除了上面的不同以外,SST39VF1601 每个SECTOR 的大小都是一样的,而
Am29LV160 的头几块比较小。需要做的修改集中在board/sunzl/sunzl2440/flash.c这个文件上,修改如下:
#define CMD_READ_ARRAY 0x000000F0
#define CMD_UNLOCK1 0x000000AA
#define CMD_UNLOCK2 0x00000055
#define CMD_ERASE_SETUP 0x00000080
//#define CMD_ERASE_CONFIRM 0x00000030
#define CMD_ERASE_CONFIRM 0x00000050
#define CMD_PROGRAM 0x000000A0
#define CMD_UNLOCK_BYPASS 0x00000020
#ifdef CONFIG_SST_VF1601
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE +(0x000005555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE +(0x000002AAA << 1)))
#else
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 <<1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA <<1)))
#endif
…………..
ulong flash_init (void)
{
…………..
#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"
…………
panic ("configured too many flashbanks!\n");
for (j =0; j < flash_info[i].sector_count; j++) {
#ifndef CONFIG_SST_VF1601
if (j<= 3) {
/*1st one is 16 KB */
if(j == 0) {
flash_info[i].start[j]=
flashbase+ 0;
}
/*2nd and 3rd are both 8 KB */
if((j == 1) || (j == 2)) {
flash_info[i].start[j]=
flashbase+ 0x4000 + (j -1) *0x2000;
}
/*4th 32 KB */
if(j == 3) {
flash_info[i].start[j]=
flashbase+ 0x8000;
}
}else {
flash_info[i].start[j]=
flashbase+ (j - 3) * MAIN_SECT_SIZE;
}
#else
flash_info[i].start[j]=
flashbase+ (j) * MAIN_SECT_SIZE;
#endif
}
size +=flash_info[i].size;
}
…………
void flash_print_info (flash_info_t * info)
{
……………
case (AMD_MANUFACT & FLASH_VENDMASK):
printf("AMD: ");
break;
case (SST_MANUFACT & FLASH_VENDMASK):
printf("SST: ");
break;
default:
printf("Unknown Vendor ");
break;
}
…………
case (AMD_ID_LV800B & FLASH_TYPEMASK):
printf("1x Amd29LV800BB (8Mbit)\n");
break;
case (SST_ID_xF1601 & FLASH_TYPEMASK):
printf("1x SST39VF1601 (2MB)\n");
break;
default:
printf("Unknown Chip Type\n");
gotoDone;
……………
int flash_erase (flash_info_t * info, int s_first, ints_last)
{
// ushortresult;
int iflag,cflag, prot, sect;
int rc =ERR_OK;
// intchip;
……………
if ((s_first < 0) || (s_first > s_last)) {
returnERR_INVAL;
}
#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
prot = 0;
……………….
MEM_FLASH_ADDR1= CMD_UNLOCK1;
MEM_FLASH_ADDR2= CMD_UNLOCK2;
*addr= CMD_ERASE_CONFIRM;
#if 0
/*wait until flash is ready */
chip= 0;
……………
printf("protected!\n");
}
}
#endif
/* waituntil flash is ready */
while(1){
unsigned short i;
i = *((volatileunsigned 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");
}
}
if (ctrlc ())
printf("User Interrupt!\n");
// outahere:
……………….
static int write_hword (flash_info_t * info, ulongdest, ushort data)
{
……………
int cflag,iflag;
// intchip;
………..
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2= CMD_UNLOCK2;
// MEM_FLASH_ADDR1= CMD_UNLOCK_BYPASS;
// *addr= CMD_PROGRAM;
MEM_FLASH_ADDR1= CMD_PROGRAM;
*addr = data;
/* armsimple, non interrupt dependent timer */
reset_timer_masked();
#if 0
/* wait untilflash is ready */
chip = 0;
………….
if (chip == ERR || *addr != data)
rc =ERR_PROG_ERROR;
#endif
/* wait until flash is ready */
while(1){
unsigned short 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
}
}
if (iflag)
enable_interrupts();
if (cflag)
icache_enable();
return rc;
}
(3)针对S29AL016芯片
具体参考yuesichiu的csdn博客《S3C2440U-Boot移植--Norflash驱动支持- S29AL016》,网址http://blog.csdn.net/yuesichiu/article/details/8267015
AM29LV160B与S29AL016J的厂商id和芯片id相同,那我们就可以直接根据AM29LV160B来移植。
修改board/sunzl/sunzl2440/flash.c这个文件
一:flash_init(void) 函数中
#if defined(CONFIG_AMD_LV400)
(AMD_MANUFACT &FLASH_VENDMASK) |
(AMD_ID_LV400B &FLASH_TYPEMASK);
#elif defined(CONFIG_AMD_LV1800)
(AMD_MANUFACT &FLASH_VENDMASK) |
(AMD_ID_LV800B &FLASH_TYPEMASK);
之后 加入
#elif defined(CONFIG_AMD_LV160)
(AMD_MANUFACT &FLASH_VENDMASK) |
(AMD_ID_LV160B &FLASH_TYPEMASK);
二:flash_print_info(flash_info_t *info)函数中
case (AMD_ID_LV400B&FLASH_TYPEMASK):
printf ("1xAmd29LV400BB (4Mbit)\n");
break;
case (AMD_ID_LV800B & FLASH_TYPEMASK):
printf ("1xAmd29LV800BB (8Mbit)\n");
break;
之后加入
case(AMD_ID_LV160B &FLASH_TYPEMASK):
printf ("1x S29AL016J(16Mbit ) \n");
break;
三种芯片剩下的修改都在最后include/configs/sunzl2440.h配置文件中修改 具体参考
u-boot-2009.11移植(适用于TQ2440和MINI2440)第五篇:修改配置文件