關於uboot下cp.b如果兩個地址同爲flash地時,buffer無法正常寫的原因

第一、cp.b命令說明

cp [.b, .w, .l] source target count

       - copy memory

cp命令可以在內存中複製數據塊,包括對Flash的讀寫操作。

第1個參數source是要複製的數據塊起始地址。

第2個參數target是數據塊要複製到的地址。這個地 址如果在Flash中, 那麼會直接調用寫Flash的函數操作。所以U-Boot寫Flash就使用這個命令,當然需要先把對應Flash區域擦乾淨。

第3個參數count是要複製的數目,根據cp.b cp.w cp.l分別以字節、字、長字爲單位。

第二、一般我們在用這個命令時第一個參數一般爲sdram的地址空間,這時我們調用這個命令是可以正常操作的,但是如果第一個參數如果是片外norflash的地址,錢對不同的norflash就有問題了,會發現如果count大於1時,寫入norflash的數據是不對的。這是爲什麼呢?根本的原因要看一下這個flash的底層寫函數如下:

static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len)

{
flash_sect_t sector;
int cnt;
int retcode;
void *src = cp;
void *dst = (void *)dest;
void *dst2 = dst;
int flag = 1;
uint offset = 0;
unsigned int shift;
uchar write_cmd;


switch (info->portwidth) {
case FLASH_CFI_8BIT:
shift = 0;
break;
case FLASH_CFI_16BIT:
shift = 1;
break;
case FLASH_CFI_32BIT:
shift = 2;
break;
case FLASH_CFI_64BIT:
shift = 3;
break;
default:
retcode = ERR_INVAL;
goto out_unmap;
}


cnt = len >> shift;


while ((cnt-- > 0) && (flag == 1)) {
switch (info->portwidth) {
case FLASH_CFI_8BIT:
flag = ((flash_read8(dst2) & flash_read8(src)) ==
flash_read8(src));
src += 1, dst2 += 1;
break;
case FLASH_CFI_16BIT:
flag = ((flash_read16(dst2) & flash_read16(src)) ==
flash_read16(src));
src += 2, dst2 += 2;
break;
case FLASH_CFI_32BIT:
flag = ((flash_read32(dst2) & flash_read32(src)) ==
flash_read32(src));
src += 4, dst2 += 4;
break;
case FLASH_CFI_64BIT:
flag = ((flash_read64(dst2) & flash_read64(src)) ==
flash_read64(src));
src += 8, dst2 += 8;
break;
}
}
if (!flag) {
retcode = ERR_NOT_ERASED;
goto out_unmap;
}


src = cp;
sector = find_sector (info, dest);


switch (info->vendor) {
case CFI_CMDSET_INTEL_PROG_REGIONS:
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
write_cmd = (info->vendor == CFI_CMDSET_INTEL_PROG_REGIONS) ?
FLASH_CMD_WRITE_BUFFER_PROG : FLASH_CMD_WRITE_TO_BUFFER;
flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
flash_write_cmd (info, sector, 0, FLASH_CMD_READ_STATUS);
flash_write_cmd (info, sector, 0, write_cmd);
retcode = flash_status_check (info, sector,
     info->buffer_write_tout,
     "write to buffer");
if (retcode == ERR_OK) {
/* reduce the number of loops by the width of
* the port */
cnt = len >> shift;
flash_write_cmd (info, sector, 0, cnt - 1);
while (cnt-- > 0) {
switch (info->portwidth) {
case FLASH_CFI_8BIT:
flash_write8(flash_read8(src), dst);
src += 1, dst += 1;
break;
case FLASH_CFI_16BIT:
flash_write16(flash_read16(src), dst);
src += 2, dst += 2;
break;
case FLASH_CFI_32BIT:
flash_write32(flash_read32(src), dst);
src += 4, dst += 4;
break;
case FLASH_CFI_64BIT:
flash_write64(flash_read64(src), dst);
src += 8, dst += 8;
break;
default:
retcode = ERR_INVAL;
goto out_unmap;
}
}
flash_write_cmd (info, sector, 0,
FLASH_CMD_WRITE_BUFFER_CONFIRM);
retcode = flash_full_status_check (
info, sector, info->buffer_write_tout,
"buffer write");
}


break;


case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
flash_unlock_seq(info,0);//發送unlock


#ifdef CONFIG_FLASH_SPANSION_S29WS_N
offset = ((unsigned long)dst - info->start[sector]) >> shift;
#endif
flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER);//發送 write buffer command
cnt = len >> shift;
flash_write_cmd(info, sector, offset, cnt - 1);
switch (info->portwidth) {
case FLASH_CFI_8BIT:
while (cnt-- > 0) {
flash_write8(flash_read8(src), dst);//在這裏是在寫命令發完後又去從norflash中去讀,如果src是一個sdram的地址,這樣是沒有問題,但如果是同一個norflash的內部地址,有時是讀不出來正確值的,因爲在發送完write buffer command後,這時norflash已經進入了write buffer 狀態,不是read狀態,這時去讀是讀不正確值,如果這完成這個操作,我們必須在這之前把flash中的數 先讀到一個buffer中,再去調用整個write buffer的操作流程。
src += 1, dst += 1;
}
break;
case FLASH_CFI_16BIT:
while (cnt-- > 0) {

flash_write16(flash_read16(src), dst);
src += 2, dst += 2;


}
break;
case FLASH_CFI_32BIT:
while (cnt-- > 0) {
flash_write32(flash_read32(src), dst);
src += 4, dst += 4;
}
break;
case FLASH_CFI_64BIT:
while (cnt-- > 0) {
flash_write64(flash_read64(src), dst);
src += 8, dst += 8;
}
break;
default:
retcode = ERR_INVAL;
goto out_unmap;
}


flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
printf("****send command 0x29 end!****\n\r");//jackyard
if (use_flash_status_poll(info))
retcode = flash_status_poll(info, src - (1 << shift),
   dst - (1 << shift),
   info->buffer_write_tout,
   "buffer write");
else
retcode = flash_full_status_check(info, sector,
 info->buffer_write_tout,
 "buffer write");
break;


default:
debug ("Unknown Command Set\n");
retcode = ERR_INVAL;
break;
}


out_unmap:
return retcode;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章