移植环境:
主芯片:SAMSUNG s3c2440A
开发板:GT2440
uboot版本:u-boot1.1.6
NOR Flash型号:EN29LV160AB。
硬件连接原理图如下图所示:
EN29LV160支持半字、单字节访问方式。如上图Pin47BYTE#为high时,采用Word Mode。Flash芯片的地址线A0-A19与s3c2440地址线的ADDR1-ADDR20连接。因为Flash是half word访问模式,s3c2440是按照单字节方式访问。故地址线错位连接。这点在s3c2440的datasheet中有描述。例如当s3c2440读取地址0处的数据时,发送的地址为0000 0000 0000 0000 0000b,地址线错位连接后,Flash芯片接收的地址为0。当s3c2440读取地址1处的数据时,发送的地址为0000 0000 0000 0000 0001,地址线错位连接后,Flash芯片接收的地址依然为0。这样为的是解决存储单元不匹配的问题。
EN29LV160AB的扇区分配,datasheet描述如下:
Flexible sector architecture(复杂的扇区结构)
One 16-KByte、two 8-KByte、one 32-KByte and third-one 64-KByte sectors(byte mode)
One 8-KWord、two 4-KWord、One 16-KWord and third-one 32-KWord sectors(Word mode)
软件修改
在/include/configs/2440.h中,
//注释原程序采用的两块nor Flash的配置
#if 0
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CONFIG_SYS_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CONFIG_SYS_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000) /* addr of environment */
#endif
//第175行添加如下内容
#define CONFIG_EON_29LV160AB 1 //添加芯片
#define PHYS_FLASH_SIZE 0x200000 //Flash芯片的总容量
#define CONFIG_SYS_MAX_FLASH_SECT (35) //根据EN29LV160AB的芯片手册描述,共35个扇区
#define CFG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x060000) //暂设置环境变量的首地址为0x060000(即:384Kb)
在/include/flash.c中,添加Flash的ID和厂商代码,添加代码:
#define EON_ID_LV160AB 0x22492249
#define EON_MANUFACT 0x001c001c
在/board/2440/flash.c中修改nor FLASH的驱动,该文件中包括对FLASH的初始化、扇区的擦除和写入。主要是对flash_init、flash_erase、write_hword三个函数的修改。
#define MAIN_SECT_SIZE 0x8000 // 根据EON29LV160AB的datasheet描述,主扇区大小为32K,以word mode方式访问
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1)))
由于我们是把norflash连接到了s3c2440的bank0上,因此norflash中的地址相对于s3c2440来说基址为0x00000000,即CONFIG_SYS_FLASH_BASE = 0。
EN29LV160AB手册要求将解锁码写到指定的地址0x555和0x2AA上,所以s3c2440发送的地址应该向左移动一位,保证nor FLASH的正确接收地址信息。
由数据手册可知EN29LV160AB第0扇区大小为8K,第1、2为4K,第3为16K,后面31扇区为32K。所以需要按照描述修改程序中的前面4个扇区的大小// 增加的代码
#elif defined(CONFIG_EON_29LV160AB) // 参考原FLASH描述进行修改,改与EN29LV160AB相关
(EON_MANUFACT & FLASH_VENDMASK) |
(EON_ID_LV160AB & FLASH_TYPEMASK);
#else
#error "Unknow flash configured"
#endif
for (j = 0; j < flash_info[i].sector_count; j++)
{
if (j <= 3)
{
/* 1st one is 8 KB */
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;
}
}
else
{
flash_info[i].start[j] = flashbase + (j - 3) * MAIN_SECT_SIZE;
}
}
size += flash_info[i].size;
修改flash_print_info,添加EN29LV160AB相关信息如下:
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 & FLASH_TYPEMASK):
printf ("1x EN29LV160AB (16Mbit)\n");
break;
default:
printf ("Unknown Chip Type\n");
goto Done;
break;
}
修改int flash_erase (flash_info_t * info, int s_first, int s_last)
if ((info->flash_id & FLASH_VENDMASK) != // 由于我们使用的是EN29LV160AB的FLASH芯片,所以其他型号为未知型号
(EON_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;4. 至此,uboot关于Norflash已经移植好.
http://blog.csdn.net/quannii/article/details/8861572