U-boot实现NOR FLASH启动
时间:2009-08-09 来源:lixuan216
起始工作就不多说了,本篇主要介绍U-boot的nor flash启动。
修改如下:
(include/configs/<yourneme>.h):
添加:
#define CONFIG_SST_39VF1601 1
#define CFG_MAX_FLASH_BANKS 1
#define PHYS_FLASH_SIZE 0x200000 /* 2MB */
#define CFG_MAX_FLASH_SIZE (512) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x40000) /* addr of environment */
并将关于AM29LV400和AM29LV800的信息全部注释掉。
NOR FLASH的操作函数在board/fs2410/flash.c中实现。它支持AM29LV400和AM29LV800.为了了解NORFLASH的操作,我们直接修改这个文件。首先我们的板子已经有了一个U-BOOT,但由于烧写的问题,我们这里启动一个调试方法,具体就是在配置文件include/configs/fs2410.h里定义:
#define CONFIG_SKIP_LOWLEVEL_INIT,这个宏用于cpu/arm920t/start.S里,主要是对CPU和存储控制器的初始化,所以调试阶段跳过初始化。然后修改board/fs2410/config.mk:
将TEXT_BASE = 0x33F80000暂时修改为:
TEXT_BASE = 0x33E00000。最后将u-boot.bin下载到这个地址,然后 从这个地址启动u-boot即可。
修改以上步骤以后,接下来我们修改board/fs2410/flash.c:
将:
#define MAIN_SECT_SIZE 0x10000 /* 64 KB */
修改为:
#define MAIN_SECT_SIZE 0x1000 /* 4 KB */(按sector操作)
将:
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
修改为:
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000005555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AAA << 1)))
这个参数参看SST39VF1601的手册可以得到。
在flash_init函数里仿照:
if defined(CONFIG_AMD_LV400)
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV400B & FLASH_TYPEMASK);
添加对SST39VF1601厂商ID和DEVICE ID的设置:
添加:
#if defined (CONFIG_SST_39VF1601)
(SST_MANUFACT & FLASH_VENDMASK)
(SST_ID_xF1601 & FLASH_TYPEMASK);
由于SST39VF1601每个SECTOR的大小都是一样的。所以修改:
将:
for (j = 0; j < flash_info[i].sector_count; j++) {
if (j <= 3) {
/* 1st one is 16 KB */
if (j == 0) {
flash_info[i].start[j] =
flashbase + 0;
}
........
........
修改为:
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] =flashbase + j*MAIN_SECT_SIZE;
}
当我们键入flinfo命令的时候,将我们的nor flash的信息答应,这里我们在flash_print_info添加相应的支持:
在:
case (AMD_MANUFACT & FLASH_VENDMASK):
printf ("AMD: ");
break;
后添加:
case (SST_MANUFACT & FLASH_VENDMASK):
printf ("SST: ");
break;
在:
case (AMD_ID_LV800B & FLASH_TYPEMASK):
printf ("1x Amd29LV800BB (8Mbit)\n");
break;
之后添加:
case (SST_ID_xF1601& FLASH_TYPEMASK):
printf ("1x SST39VF1610 (16Mbit)\n");
break;
接下来修改flash_erase函数,这里我们用SECTOR进行擦出操作。具体修改如下:
将:
if ((info->flash_id & FLASH_VENDMASK) !=
(AMD_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
修改为:if ((info->flash_id & FLASH_VENDMASK) !=
(SST_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
阅读弄SST39VF1601使用手册,我们对flash_erase()修改如下: .... if (info->protect[sect] == 0) { /* not protected */ vu_short *addr = (vu_short *) (info->start[sect]); MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; *addr = CMD_ERASE_CONFIRM; /* wait until flash is ready */ while(1){ unsigned short i; i = *((volatile unsigned short *)addr)&0x40; if(i!=*((volatile unsigned short *)addr)&0x40) continue; if(*((volatile unsigned short *)addr)&0x80) break; } printf ("ok.\n"); } else { /* it was protected */ printf ("protected!\n"); } } if (ctrlc ()) ........ 对flash_hword()修改如下: volatile static int write_hword (flash_info_t * info, ulong dest, ushort data) { vu_short *addr = (vu_short *) dest; ushort result; int rc = ERR_OK; int cflag, iflag; int chip; /* * Check if Flash is (sufficiently) erased */ result = *addr; if ((result & data) != data) return ERR_NOT_ERASED; /* * Disable interrupts which might cause a timeout here. Remember that our exception * vectors are at address 0 in the flash, and we don't want a (ticker) exception to happen * while the flash chip is in programming mode. */ cflag = icache_status (); icache_disable (); iflag = disable_interrupts (); MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; MEM_FLASH_ADDR1 = CMD_PROGRAM; *addr = data; /* arm simple, non interrupt dependent timer */ reset_timer_masked (); /* 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; } 到此为止,NOR FLASH支持基本修改完毕! 相关连接:http://blog.chinaunix.net/u2/63379/showart_1330720.html
添加:
#define CONFIG_SST_39VF1601 1
#define CFG_MAX_FLASH_BANKS 1
#define PHYS_FLASH_SIZE 0x200000 /* 2MB */
#define CFG_MAX_FLASH_SIZE (512) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x40000) /* addr of environment */
并将关于AM29LV400和AM29LV800的信息全部注释掉。
NOR FLASH的操作函数在board/fs2410/flash.c中实现。它支持AM29LV400和AM29LV800.为了了解NORFLASH的操作,我们直接修改这个文件。首先我们的板子已经有了一个U-BOOT,但由于烧写的问题,我们这里启动一个调试方法,具体就是在配置文件include/configs/fs2410.h里定义:
#define CONFIG_SKIP_LOWLEVEL_INIT,这个宏用于cpu/arm920t/start.S里,主要是对CPU和存储控制器的初始化,所以调试阶段跳过初始化。然后修改board/fs2410/config.mk:
将TEXT_BASE = 0x33F80000暂时修改为:
TEXT_BASE = 0x33E00000。最后将u-boot.bin下载到这个地址,然后 从这个地址启动u-boot即可。
修改以上步骤以后,接下来我们修改board/fs2410/flash.c:
将:
#define MAIN_SECT_SIZE 0x10000 /* 64 KB */
修改为:
#define MAIN_SECT_SIZE 0x1000 /* 4 KB */(按sector操作)
将:
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
修改为:
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000005555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AAA << 1)))
这个参数参看SST39VF1601的手册可以得到。
在flash_init函数里仿照:
if defined(CONFIG_AMD_LV400)
(AMD_MANUFACT & FLASH_VENDMASK) |
(AMD_ID_LV400B & FLASH_TYPEMASK);
添加对SST39VF1601厂商ID和DEVICE ID的设置:
添加:
#if defined (CONFIG_SST_39VF1601)
(SST_MANUFACT & FLASH_VENDMASK)
(SST_ID_xF1601 & FLASH_TYPEMASK);
由于SST39VF1601每个SECTOR的大小都是一样的。所以修改:
将:
for (j = 0; j < flash_info[i].sector_count; j++) {
if (j <= 3) {
/* 1st one is 16 KB */
if (j == 0) {
flash_info[i].start[j] =
flashbase + 0;
}
........
........
修改为:
for (j = 0; j < flash_info[i].sector_count; j++) {
flash_info[i].start[j] =flashbase + j*MAIN_SECT_SIZE;
}
当我们键入flinfo命令的时候,将我们的nor flash的信息答应,这里我们在flash_print_info添加相应的支持:
在:
case (AMD_MANUFACT & FLASH_VENDMASK):
printf ("AMD: ");
break;
后添加:
case (SST_MANUFACT & FLASH_VENDMASK):
printf ("SST: ");
break;
在:
case (AMD_ID_LV800B & FLASH_TYPEMASK):
printf ("1x Amd29LV800BB (8Mbit)\n");
break;
之后添加:
case (SST_ID_xF1601& FLASH_TYPEMASK):
printf ("1x SST39VF1610 (16Mbit)\n");
break;
接下来修改flash_erase函数,这里我们用SECTOR进行擦出操作。具体修改如下:
将:
if ((info->flash_id & FLASH_VENDMASK) !=
(AMD_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
修改为:if ((info->flash_id & FLASH_VENDMASK) !=
(SST_MANUFACT & FLASH_VENDMASK)) {
return ERR_UNKNOWN_FLASH_VENDOR;
阅读弄SST39VF1601使用手册,我们对flash_erase()修改如下: .... if (info->protect[sect] == 0) { /* not protected */ vu_short *addr = (vu_short *) (info->start[sect]); MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; *addr = CMD_ERASE_CONFIRM; /* wait until flash is ready */ while(1){ unsigned short i; i = *((volatile unsigned short *)addr)&0x40; if(i!=*((volatile unsigned short *)addr)&0x40) continue; if(*((volatile unsigned short *)addr)&0x80) break; } printf ("ok.\n"); } else { /* it was protected */ printf ("protected!\n"); } } if (ctrlc ()) ........ 对flash_hword()修改如下: volatile static int write_hword (flash_info_t * info, ulong dest, ushort data) { vu_short *addr = (vu_short *) dest; ushort result; int rc = ERR_OK; int cflag, iflag; int chip; /* * Check if Flash is (sufficiently) erased */ result = *addr; if ((result & data) != data) return ERR_NOT_ERASED; /* * Disable interrupts which might cause a timeout here. Remember that our exception * vectors are at address 0 in the flash, and we don't want a (ticker) exception to happen * while the flash chip is in programming mode. */ cflag = icache_status (); icache_disable (); iflag = disable_interrupts (); MEM_FLASH_ADDR1 = CMD_UNLOCK1; MEM_FLASH_ADDR2 = CMD_UNLOCK2; MEM_FLASH_ADDR1 = CMD_PROGRAM; *addr = data; /* arm simple, non interrupt dependent timer */ reset_timer_masked (); /* 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; } 到此为止,NOR FLASH支持基本修改完毕! 相关连接:http://blog.chinaunix.net/u2/63379/showart_1330720.html
相关阅读 更多 +