您的位置:首页 > 编程语言

U-boot之flash初始化完全代码分析

2009-07-02 22:59 591 查看
一 代码分析

1Board->dave->flash.c
#include <common.h>
#include <asm/hardware.h>
#include "../common/flash.c"
#包含必须的头文件
static ulong flash_get_size (vu_long * addr, flash_info_t * info);
static void flash_get_offsets (ulong base, flash_info_t * info);
#声明两个静态函数
FLASH初始化
unsigned long flash_init (void)
{
#ifdef __DEBUG_START_FROM_SRAM__
return CFG_DUMMY_FLASH_SIZE;
#如果定义了__DEBUG_START_FROM_SRAM__也就是从ram启动,则返回CFG_DUMMY_FLASH_SIZE
#else
unsigned long size_b0;
int i;
/* Init: no FLASHes known */
for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
flash_info[i].flash_id = FLASH_UNKNOWN;
}
#初始标识Flash的bank为FLASH_UNKNOWN
/* Static FLASH Bank configuration here - FIXME XXX */
size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
#调用flash_get_size函数,获取flash的大小,存入size_b0
if (flash_info[0].flash_id == FLASH_UNKNOWN) {
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB/n",
size_b0, size_b0<<20);
}
#判断Flash是否是列表中所有的,如果没有,打印信息。具体列表在flash_get_size函数中
/* Setup offsets */
flash_get_offsets (0, &flash_info[0]);
#设置起始偏移地址。“0”表示基地址,“&flash_info[0]”bank0的基地址
/* Monitor protection ON by default */
(void)flash_protect(FLAG_PROTECT_SET,
-CFG_MONITOR_LEN,
0xffffffff,
&flash_info[0]);
#flash保护,见flash_protect函数
flash_info[0].size = size_b0;
#将size_b0存入flash_info[0]
return (size_b0);
#endif
}
2Board->dave->command->flash.c
#include <common.h>
#include <asm/processor.h>
#包含必要的头文件
flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
#定义数组flash_info为flash_info_t类型,该类型的定义见3
static int write_word (flash_info_t *info, ulong dest, ulong data);
#声明静态函数
获取FLASH偏移地址
static void flash_get_offsets (ulong base, flash_info_t *info)
{
int i;
short n;
/* set up sector start address table */
#设置起始地址表。判断Flash类型,厂商和片名,如果都不符合,则执行else的内容
if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U)) {
for (i = 0; i < info->sector_count; i++)
info->start[i] = base + (i * 0x00010000);
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
/* set sector offsets for bottom boot block type */
for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
info->start[i] = base;
base += 8 << 10;
}
while (i < info->sector_count) { /* 64k regular sectors */
info->start[i] = base;
base += 64 << 10;
++i;
}
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
/* set sector offsets for top boot block type */
base += info->size;
i = info->sector_count;
for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
base -= 8 << 10;
--i;
info->start[i] = base;
}
while (i > 0) { /* 64k regular sectors */
base -= 64 << 10;
--i;
info->start[i] = base;
}
} else {
if (info->flash_id & FLASH_BTYPE) {
/* set sector offsets for bottom boot block type */
info->start[0] = base + 0x00000000;
info->start[1] = base + 0x00004000;
info->start[2] = base + 0x00006000;
info->start[3] = base + 0x00008000;
for (i = 4; i < info->sector_count; i++) {
info->start[i] = base + (i * 0x00010000) - 0x00030000;
}
} else {
/* set sector offsets for top boot block type */
#如果都不是以上的类型,设置物理片段的起始地址
i = info->sector_count - 1;
info->start[i--] = base + info->size - 0x00004000;
info->start[i--] = base + info->size - 0x00006000;
info->start[i--] = base + info->size - 0x00008000;
for (; i >= 0; i--) {
info->start[i] = base + i * 0x00010000;
}
}
}
}
FLASH信息打印输出
void flash_print_info (flash_info_t *info)
{
int i;
int k;
int size;
int erased;
volatile unsigned long *flash;

if (info->flash_id == FLASH_UNKNOWN) {
printf ("missing or unknown FLASH type/n");
return;
}
switch (info->flash_id & FLASH_VENDMASK) {
case FLASH_MAN_AMD: printf ("AMD "); break;
case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
case FLASH_MAN_SST: printf ("SST "); break;
case FLASH_MAN_STM: printf ("ST "); break;
default: printf ("Unknown Vendor "); break;
}
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)/n");
break;
case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)/n");
break;
case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)/n");
break;
case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)/n");
break;
case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)/n");
break;
case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)/n");
break;
case FLASH_AM320T: printf ("AM29LV320T (32 M, top sector)/n");
break;
case FLASH_AM320B: printf ("AM29LV320B (32 M, bottom sector)/n");
break;
case FLASH_AMDL322T: printf ("AM29DL322T (32 M, top sector)/n");
break;
case FLASH_AMDL322B: printf ("AM29DL322B (32 M, bottom sector)/n");
break;
case FLASH_AMDL323T: printf ("AM29DL323T (32 M, top sector)/n");
break;
case FLASH_AMDL323B: printf ("AM29DL323B (32 M, bottom sector)/n");
break;
case FLASH_AM640U: printf ("AM29LV640D (64 M, uniform sector)/n");
break;
case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)/n");
break;
case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)/n");
break;
case FLASH_STMW320DT: printf ("M29W320DT (32 M, top sector)/n");
break;
default: printf ("Unknown Chip Type/n");
break;
}
printf (" Size: %ld MB in %d Sectors/n",
info->size >> 20, info->sector_count);
printf (" Sector Start Addresses:");
for (i=0; i<info->sector_count; ++i) {
#ifdef CFG_FLASH_EMPTY_INFO
/*
* Check if whole sector is erased
*/
if (i != (info->sector_count-1))
size = info->start[i+1] - info->start[i];
else
size = info->start[0] + info->size - info->start[i];
erased = 1;
flash = (volatile unsigned long *)info->start[i];
size = size >> 2; /* divide by 4 for longword access */
for (k=0; k<size; k++)
{
if (*flash++ != 0xffffffff)
{
erased = 0;
break;
}
}

if ((i % 5) == 0)
printf ("/n ");
/* print empty and read-only info */
printf (" %08lX%s%s",
info->start[i],
erased ? " E" : " ",
info->protect[i] ? "RO " : " ");
#else
if ((i % 5) == 0)
printf ("/n ");
printf (" %08lX%s",
info->start[i],
info->protect[i] ? " (RO)" : " ");
#endif

}
printf ("/n");
return;
}
获取FLASH大小
static ulong flash_get_size (vu_long *addr, flash_info_t *info)
{
short i;
short n;
CFG_FLASH_WORD_SIZE value;
ulong base = (ulong)addr;
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr;
#CFG_FLASH_WORD_SIZE等于unsign short在B2.h中定义

debug("[%s, %d] Entering .../n", __FUNCTION__, __LINE__);
/* Write auto select command: read Manufacturer ID */
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
#B2.h中定义#define CFG_FLASH_ADDR0 0x5555
#define CFG_FLASH_ADDR1 0x2AAA
<<<<<<无法理解?>>>>>>
value = addr2[CFG_FLASH_READ0];
#获取flash的厂商ID
switch (value) {
case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
info->flash_id = FLASH_MAN_AMD;
break;
case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT:
info->flash_id = FLASH_MAN_FUJ;
break;
case (CFG_FLASH_WORD_SIZE)SST_MANUFACT:
info->flash_id = FLASH_MAN_SST;
break;
case (CFG_FLASH_WORD_SIZE)STM_MANUFACT:
info->flash_id = FLASH_MAN_STM;
break;
default:
info->flash_id = FLASH_UNKNOWN;
info->sector_count = 0;
info->size = 0;
return (0); /* no or unknown flash */
}
value = addr2[CFG_FLASH_READ1]; /* device ID */
#获取flash的设备ID
switch (value) {
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T:
info->flash_id += FLASH_AM400T;
info->sector_count = 11;
info->size = 0x00080000;
break; /* => 0.5 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B:
info->flash_id += FLASH_AM400B;
info->sector_count = 11;
info->size = 0x00080000;
break; /* => 0.5 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T:
info->flash_id += FLASH_AM800T;
info->sector_count = 19;
info->size = 0x00100000;
break; /* => 1 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B:
info->flash_id += FLASH_AM800B;
info->sector_count = 19;
info->size = 0x00100000;
break; /* => 1 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T:
info->flash_id += FLASH_AM160T;
info->sector_count = 35;
info->size = 0x00200000;
break; /* => 2 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B:
info->flash_id += FLASH_AM160B;
info->sector_count = 35;
info->size = 0x00200000;
break; /* => 2 MB */
case (CFG_FLASH_WORD_SIZE)STM_ID_29W320DT:
info->flash_id += FLASH_STMW320DT;
info->sector_count = 67;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T:
info->flash_id += FLASH_AM320T;
info->sector_count = 71;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B:
info->flash_id += FLASH_AM320B;
info->sector_count = 71;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T:
info->flash_id += FLASH_AMDL322T;
info->sector_count = 71;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B:
info->flash_id += FLASH_AMDL322B;
info->sector_count = 71;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T:
info->flash_id += FLASH_AMDL323T;
info->sector_count = 71;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B:
info->flash_id += FLASH_AMDL323B;
info->sector_count = 71;
info->size = 0x00400000; break; /* => 4 MB */
case (CFG_FLASH_WORD_SIZE)AMD_ID_LV640U:
info->flash_id += FLASH_AM640U;
info->sector_count = 128;
info->size = 0x00800000; break; /* => 8 MB */
case (CFG_FLASH_WORD_SIZE)SST_ID_xF800A:
info->flash_id += FLASH_SST800A;
info->sector_count = 16;
info->size = 0x00100000;
break; /* => 1 MB */
case (CFG_FLASH_WORD_SIZE)SST_ID_xF160A:
info->flash_id += FLASH_SST160A;
info->sector_count = 32;
info->size = 0x00200000;
break; /* => 2 MB */
default:
info->flash_id = FLASH_UNKNOWN;
return (0); /* => no or unknown flash */
}
#根据开发板Flash的情况,设定id,sector_count,size参数,若无则皆为0
/* set up sector start address table */
#设定起始地址表,与flash_get_offsets中的相同
if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U)) {
for (i = 0; i < info->sector_count; i++)
info->start[i] = base + (i * 0x00010000);
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) {
/* set sector offsets for bottom boot block type */
for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */
info->start[i] = base;
base += 8 << 10;
}
while (i < info->sector_count) { /* 64k regular sectors */
info->start[i] = base;
base += 64 << 10;
++i;
}
} else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) {
/* set sector offsets for top boot block type */
base += info->size;
i = info->sector_count;
for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */
base -= 8 << 10;
--i;
info->start[i] = base;
}
while (i > 0) { /* 64k regular sectors */
base -= 64 << 10;
--i;
info->start[i] = base;
}
} else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT) {
/* set sector offsets for top boot block type */
base += info->size;
i = info->sector_count;
/* 1 x 16k boot sector */
base -= 16 << 10;
--i;
info->start[i] = base;
/* 2 x 8k boot sectors */
for (n=0; n<2; ++n) {
base -= 8 << 10;
--i;
info->start[i] = base;

}

/* 1 x 32k boot sector */
base -= 32 << 10;
--i;
info->start[i] = base;

while (i > 0) { /* 64k regular sectors */
base -= 64 << 10;
--i;
info->start[i] = base;
}
} else {
if (info->flash_id & FLASH_BTYPE) {
/* set sector offsets for bottom boot block type */
info->start[0] = base + 0x00000000;
info->start[1] = base + 0x00004000;
info->start[2] = base + 0x00006000;
info->start[3] = base + 0x00008000;
for (i = 4; i < info->sector_count; i++) {
info->start[i] = base + (i * 0x00010000) - 0x00030000;
}
} else {
/* set sector offsets for top boot block type */
i = info->sector_count - 1;
info->start[i--] = base + info->size - 0x00004000;
info->start[i--] = base + info->size - 0x00006000;
info->start[i--] = base + info->size - 0x00008000;
for (; i >= 0; i--) {
info->start[i] = base + i * 0x00010000;
}
}
}
#检测保护的片段
for (i = 0; i < info->sector_count; i++) {
/* read sector protection at sector address, (A7 .. A0) = 0x02 */
/* D0 = 1 if protected */
addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]);
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
info->protect[i] = 0;
else
info->protect[i] = addr2[CFG_FLASH_READ2] & 1;
}

if (info->flash_id != FLASH_UNKNOWN) {
addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0];
*addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
}
return (info->size);
}
擦除函数
int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *addr2;
int flag, prot, sect, l_sect;
ulong start, now, last;
int i;
if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
printf ("- missing/n");
} else {
printf ("- no sectors to erase/n");
}
return 1;
}
if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted/n");
return 1;
}
prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}
if (prot) {
printf ("- Warning: %d protected sectors will not be erased!/n",
prot);
} else {
printf ("/n");
}
l_sect = -1;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00500050; /* block erase */
for (i=0; i<50; i++)
udelay(1000); /* wait 1 ms */
} else {
if (sect == s_first) {
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
}
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
}
l_sect = sect;
}
}
/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();
/* wait at least 80us - let's wait 1 ms */
udelay (1000);
/*
* We wait for the last triggered sector
*/
if (l_sect < 0)
goto DONE;
start = get_timer (0);
last = start;
addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout/n");
return 1;
}
/* show that we're waiting */
if ((now - last) > 1000) { /* every second */
putc ('.');
last = now;
}
}
DONE:
/* reset to read mode */
addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */

printf (" done/n");
return 0;
}
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
写缓冲函数
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong cp, wp, data;
int i, l, rc;

wp = (addr & ~3); /* get lower word aligned address */

/*
* handle unaligned start bytes
*/
if ((l = addr - wp) != 0) {
data = 0;
for (i=0, cp=wp; i<l; ++i, ++cp) {
#ifdef CONFIG_B2
data = data | ((*(uchar *)cp)<<(8*i));
#else
data = (data << 8) | (*(uchar *)cp);
#endif
}
for (; i<4 && cnt>0; ++i) {
#ifdef CONFIG_B2
data = data | ((*src++)<<(8*i));
#else
data = (data << 8) | *src++;
#endif
--cnt;
++cp;
}
for (; cnt==0 && i<4; ++i, ++cp) {
#ifdef CONFIG_B2
data = data | ((*(uchar *)cp)<<(8*i));
#else
data = (data << 8) | (*(uchar *)cp);
#endif
}

if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
}

/*
* handle word aligned part
*/
while (cnt >= 4) {
data = 0;
#ifdef CONFIG_B2
data = (*(ulong*)src);
src += 4;
#else
for (i=0; i<4; ++i) {
data = (data << 8) | *src++;
}
#endif
if ((rc = write_word(info, wp, data)) != 0) {
return (rc);
}
wp += 4;
cnt -= 4;
}

if (cnt == 0) {
return (0);
}

/*
* handle unaligned tail bytes
*/
data = 0;
for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
#ifdef CONFIG_B2
data = data | ((*src++)<<(8*i));
#else
data = (data << 8) | *src++;
#endif
--cnt;
}
for (; i<4; ++i, ++cp) {
#ifdef CONFIG_B2
data = data | ((*(uchar *)cp)<<(8*i));
#else
data = (data << 8) | (*(uchar *)cp);
#endif
}

return (write_word(info, wp, data));
}

/*-----------------------------------------------------------------------
* Write a word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
写字函数
static int write_word (flash_info_t *info, ulong dest, ulong data)
{
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
ulong start;
int flag;
int i;

/* Check if Flash is (sufficiently) erased */
if ((*((volatile ulong *)dest) & data) != data) {
return (2);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();

for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++)
{
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;

dest2[i] = data2[i];

/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();

/* data polling for D7 */
start = get_timer (0);
while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
}

return (0);
}
3include->flash.h
typedef struct {
ulong size; /* total bank size in bytes */
ushort sector_count; /* number of erase units */
ulong flash_id; /* combined device & manufacturer code */
ulong start[CFG_MAX_FLASH_SECT]; /* physical sector start addresses */
uchar protect[CFG_MAX_FLASH_SECT]; /* sector protection status */
#ifdef CFG_FLASH_CFI
uchar portwidth; /* the width of the port */
uchar chipwidth; /* the width of the chip */
ushort buffer_size; /* # of bytes in write buffer */
ulong erase_blk_tout; /* maximum block erase timeout */
ulong write_tout; /* maximum write timeout */
ulong buffer_write_tout; /* maximum buffer write timeout */
ushort vendor; /* the primary vendor id */
ushort cmd_reset; /* Vendor specific reset command */
ushort interface; /* used for x8/x16 adjustments */
ushort legacy_unlock; /* support Intel legacy (un)locking */
#endif
} flash_info_t;
4common->flash.c
#include <common.h>
#include <flash.h>

#if !defined(CFG_NO_FLASH)
extern flash_info_t flash_info[]; /* info for FLASH chips */
FLASH保护
void flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
{
ulong b_end = info->start[0] + info->size - 1; /* bank end address */
short s_end = info->sector_count - 1; /* index of last sector */
int i;

debug ("flash_protect %s: from 0x%08lX to 0x%08lX/n",
(flag & FLAG_PROTECT_SET) ? "ON" :
(flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???",
from, to);

/* Do nothing if input data is bad. */
if (info->sector_count == 0 || info->size == 0 || to < from) {
return;
}
#无用数据时什么都不做
/* There is nothing to do if we have no data about the flash
* or the protect range and flash range don't overlap.
*/
if (info->flash_id == FLASH_UNKNOWN ||
to < info->start[0] || from > b_end) {
return;
}
#写的数据超出范围,或者无数据时,什么都不做
for (i=0; i<info->sector_count; ++i) {
ulong end; /* last address in current sect */

end = (i == s_end) ? b_end : info->start[i + 1] - 1;

/* Update protection if any part of the sector
* is in the specified range.
*/
if (from <= end && to >= info->start[i]) {
if (flag & FLAG_PROTECT_CLEAR) {
#if defined(CFG_FLASH_PROTECTION)
flash_real_protect(info, i, 0);
#else
info->protect[i] = 0;
#endif /* CFG_FLASH_PROTECTION */
debug ("protect off %d/n", i);
}
else if (flag & FLAG_PROTECT_SET) {
#if defined(CFG_FLASH_PROTECTION)
flash_real_protect(info, i, 1);
#else
info->protect[i] = 1;
#endif /* CFG_FLASH_PROTECTION */
debug ("protect on %d/n", i);
}
}
}
}
写地址到info
flash_info_t *addr2info (ulong addr)
{
#ifndef CONFIG_SPD823TS
flash_info_t *info;
int i;

for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
if (info->flash_id != FLASH_UNKNOWN &&
addr >= info->start[0] &&
/* WARNING - The '- 1' is needed if the flash
* is at the end of the address space, since
* info->start[0] + info->size wraps back to 0.
* Please don't change this unless you understand this.
*/
addr <= info->start[0] + info->size - 1) {
return (info);
}
#判断数据是否有用,若有用,则返回info
}
#endif /* CONFIG_SPD823TS */
return (NULL);
}
/*-----------------------------------------------------------------------
* Copy memory to flash.
* Make sure all target addresses are within Flash bounds,
* and no protected sectors are hit.
* Returns:
* ERR_OK 0 - OK
* ERR_TIMOUT 1 - write timeout
* ERR_NOT_ERASED 2 - Flash not erased
* ERR_PROTECTED 4 - target range includes protected sectors
* ERR_INVAL 8 - target address not in Flash memory
* ERR_ALIGN 16 - target address not aligned on boundary
* (only some targets require alignment)
*/
写FLASH
int flash_write (char *src, ulong addr, ulong cnt)
{
#ifdef CONFIG_SPD823TS
return (ERR_TIMOUT); /* any other error codes are possible as well */
#else
int i;
ulong end = addr + cnt - 1;
flash_info_t *info_first = addr2info (addr);
flash_info_t *info_last = addr2info (end );
flash_info_t *info;

if (cnt == 0) {
return (ERR_OK);
}

if (!info_first || !info_last) {
return (ERR_INVAL);
}

for (info = info_first; info <= info_last; ++info) {
ulong b_end = info->start[0] + info->size; /* bank end addr */
short s_end = info->sector_count - 1;
for (i=0; i<info->sector_count; ++i) {
ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];

if ((end >= info->start[i]) && (addr < e_addr) &&
(info->protect[i] != 0) ) {
return (ERR_PROTECTED);
}
}
}

/* finally write data to flash */
for (info = info_first; info <= info_last && cnt>0; ++info) {
ulong len;

len = info->start[0] + info->size - addr;
if (len > cnt)
len = cnt;
if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) {
return (i);
}
cnt -= len;
addr += len;
src += len;
}
return (ERR_OK);
#endif /* CONFIG_SPD823TS */
}
错误类型显示
void flash_perror (int err)
{
switch (err) {
case ERR_OK:
break;
case ERR_TIMOUT:
puts ("Timeout writing to Flash/n");
break;
case ERR_NOT_ERASED:
puts ("Flash not Erased/n");
break;
case ERR_PROTECTED:
puts ("Can't write to protected Flash sectors/n");
break;
case ERR_INVAL:
puts ("Outside available Flash/n");
break;
case ERR_ALIGN:
puts ("Start and/or end address not on sector boundary/n");
break;
case ERR_UNKNOWN_FLASH_VENDOR:
puts ("Unknown Vendor of Flash/n");
break;
case ERR_UNKNOWN_FLASH_TYPE:
puts ("Unknown Type of Flash/n");
break;
case ERR_PROG_ERROR:
puts ("General Flash Programming Error/n");
break;
default:
printf ("%s[%d] FIXME: rc=%d/n", __FILE__, __LINE__, err);
break;
}
}

二 执行流程
在lib_arm->board.c中的start_armboot函数是第2阶段的起始,我们从这里开始分析:
1) flash_init()被调用;
2) 初始化所有的BANK为FLASH_UNKNOW;
3) 调用flash_get_size()。通过判断FLASH类型,获得FLASH的大小,并且返回info->size,存放入size_b0;
4) 调用flash_get_offsets()设置BANK起始地址表,无返回;
5) 调用flash_protect()判断写入信息是否可用
6) 返回size_b0
7) 调用display_flash_config (size);定义为static void display_flash_config (ulong size){puts ("Flash: ");print_size (size, "/n");} 打印FLASH容量信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: