关于uboot下cp.b如果两个地址同为flash地时,buffer无法正常写的原因

来源:互联网 发布:网络诈骗的种类有哪些 编辑:程序博客网 时间:2024/05/01 03:58

第一、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;
}

1 0
原创粉丝点击