分类: 嵌入式
2011-10-11 10:39:03
Norflash可以运行代码:代码烧在nor上,PC指针从nor的一个地址开始读取代码,执行
Nor的可以直接读就是这样取址执行的
该flash数据线是16位的,即一个地址可操作2个存储单元,实际上可以看作:
一个地址对应一个16位的存储单元。
和cpu的存储单元8位链接需要错开一位,CPU的A0闲置,A1连到A0,以此类推:
A0
A1 A0
A2 A1
A3 A2
A3 A2 A1 A0 A2 A1 A0 读 nor 写 nor
0 0 0 0 0 0 0 0x00 0x00 0x00<<1=0x00 0x00
0 0 0 1 0 0 0 0x01 0x00 0x01<<1=0x02 0x01
0 0 1 0 0 0 1 0x02 0x01 0x02<<1=0x04 0x02
0 0 1 1 0 0 1 0x03 0x01 0x03<<1=0x06 0x03
Cpu读nor的时候:
Cpu发出0x00和0x01,读取到的是nor的0x00地址,nor送出16位的数据
Cpu将0-7位存储到0x00地址处,将8-15存储到0x01地址处
Cpu写nor的时候:
Cpu只发出偶数地址,即0x00(0x01)对应nor的0x00;0x02(0x03)对应nor的0x01;
0x04(0x05)对应nor的0x02;0x06(0x07)对应nor的0x03
Cpu每发出一个偶数地址的时候,将16位的数据发给nor接受,
相当于cpu发偶数地址的时候,也把基数地址的数据发出,偶+奇地址=16位数据
Cpu一次也发出16位的数据
但实际上cpu不一定要发偶数的地址,发奇数的地址也可以,这就需要软件来实现,即转换一下,即将cup发出的地址左移1位,这样就变成了偶数地址,发出16位的数据这样即可例如norflash操作的地址5555H,这是cpu看到的要发出的地址,所以软件5555H<<1即可
总结一下:cpu向nor写数据时候,将cpu发出的地址<<1位,发出16位数据即可。
对norFlash的操作:
读:自动读,无需cpu初始化,表现为cpu从上面取址执行,就像内存一样,常用作启动代码的存储。 读数据的话,直接取地址即可
写:16位的话就是2个字节写,只能把1变为0,故写之前需要擦除(全变为1)
完成及验证:During the internal Program or Erase operation, any consecutiveattempts to read DQ6 will produce alternating “1”sand “0”s, i.e., toggling between 1 and 0. When the internalProgram or Erase operation is completed, the DQ6 bit willstop toggling
擦除:扇区擦除,块擦除,芯片擦除,擦除操作就是把要擦除的部分全部变为1。
完成及验证:During internal Erase operation,any attempt to read DQ7 will produce a ‘0’. Once theinternal Erase operation is completed, DQ7 will produce a‘1’.
写/擦除操作的命令和步骤
示例:擦除方法
#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00005555 << 1)))
#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00002AAA << 1)))
#define CMD_READ_ARRAY 0x000000F0
#define CMD_UNLOCK1 0x000000AA
#define CMD_UNLOCK2 0x00000055
#define CMD_ERASE_SETUP 0x00000080
#define CMD_ERASE_CONFIRM 0x00000030
#define CMD_PROGRAM 0x000000A0
#define CMD_UNLOCK_BYPASS 0x00000020
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;
while (1)
{
if ((*addr & 0x40) != (*addr & 0x40)) //写/擦除完成
continue;
if (*addr & 0x80) //擦除成功验证
{
rc = ERR_OK;
break;
}
}
示例:写入方法
MEM_FLASH_ADDR1 = CMD_UNLOCK1;
MEM_FLASH_ADDR2 = CMD_UNLOCK2;
MEM_FLASH_ADDR1 = CMD_PROGRAM;
*addr = data;while (1)
{
if ((*addr & 0x40) != (*addr & 0x40)) //写/擦除完成
continue;
if ((*addr & 0x80) == (data & 0x80)) //写成功验证
{
rc = ERR_OK;
break;
}
}