加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

nor flash

发布时间:2020-12-15 18:26:28 所属栏目:百科 来源:网络整理
导读:1.NOR Flash的介绍 ?? NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失。NOR FLASH支持Execute ON Chip,即程序可以直接在FLASH片内执行。这点和NAND FLASH不一样。因此,在嵌入是系统中,NOR FLASH很适合作为启动程序的存储介质。NOR FLASH的读取和RAM
<1>.NOR Flash的介绍 ?? NOR FLASH 是很常见的一种存储芯片,数据掉电不会丢失。NOR FLASH支持Execute ON Chip,即程序可以直接在FLASH片内执行。这点和NAND FLASH不一样。因此,在嵌入是系统中,NOR FLASH很适合作为启动程序的存储介质。NOR FLASH的读取和RAM很类似,但不可以直接进行写操作。对NOR FLASH的写操作需要遵循特定的命令序列,最终由芯片内部的控制单元完成写操作。从支持的最小访问单元来看,NOR FLASH一般分为 8 位的和16位的(当然,也有很多NOR FLASH芯片同时支持8位模式和是16 位模式,具体的工作模式通过特定的管脚进行选择) 。 对8位的 NOR FLASH芯片,或是工作在8-BIT模式的芯片来说,一个地址对应一个BYTE(8-BIT)的数据。例如一块8-BIT的NOR FLASH,假设容量为4个 BYTE。那芯片应该有8个数据信号D7-D0 和2个地址信号,A1-A0。地址0x0对应第0个 BYTE,地址0x1对应于第1BYTE,地址0x2对应于第2个 BYTE,而地址0x3则对应于第3个BYTE. 对16位的 NOR FLASH芯片,或是工作在16-BIT模式的芯片来说,一个地址对应于一个16-BIT的数据。例如,一块16-BIT的 NOR FLASH,假设其容量为4个BYTE。那芯片应该有16 个数据信号线D15-D0 和1个地址信A0。地址 0x0对应于芯片内部的第0个16-BIT,地址0x1对应于芯片内部的第1个16-BIT。 FLASH一般都分为很多个SECTOR,每个SECTOR包括一定数量的存储单元。对有些大容量的FLASH,还分为不同的BANK,每个BANK包括一定数目的SECTOR。FLASH的擦除操作一般都是以SECTOR,BANK或是整片FLASH为单位的。在对FLASH进行写操作的时候,每个BIT可以通过编程由1变为0,但不可以有0修改为1。为了保证写操作的正确性,在执行写操作前,都要执行擦除操作。擦除操作会把FLASH的一个SECTOR,一个BANK或是整片FLASH 的值全修改为0xFF。这样,写操作就可以正确完成了。 <2>.具体操作介绍--对应芯片SST39VF1601 ①.读操作 ? 对norflash的读操作比较简单,系统上电后会自动进入读模式,而且也不需要额外的命令来实现读操作,下面的代码就实现了 NOR Flash的操作。? ? static unsigned int Read_SST1601(unsigned int addr) ? { ?? return *((volatile unsigned int *)(addr)); ? } ②.复位操作 ? norflash不仅能够实现硬件复位,而且可以实现软件复位。软件复位的操作是向任一地址写入复位命令0xF0。下面的函数实现 了软件复位: ? static void Reset_SST1601(void) ? { ?? *((volatile unsigned int *)0x0) = 0xf0; ? } ③.写操作 ? norflash的擦除操作和写操作要稍微复杂一些,它们需要4个或6个周期来完成,每一个周期都要把相应的命令写入norflash 中的某一命令寄存器中。写操作的过程为第一个周期是把命令0xAA写入地址为0x5555的命令寄存器中,第二个周期是把命令0x55写 入地址为0x2AAA命令寄存器中,第三个周期是把命令0xA0再写入地址为0x5555命令寄存器中,第四个周期为真正地把要写入的数据 写入到norflash的地址中。下面的函数实现了写操作,其中该函数的两个输入参数分别为要写入的数据和地址,为了方便,我们 事先定义好命令寄存器.【注】参考芯片手册 ? #define??? flash_base????????????? 0x00000000 ? #define??? CMD_ADDR0????????????? *((volatile unsigned int *)(0x555<<1+flash_base))? ? #define??? CMD_ADDR1????????????? *((volatile unsigned int *)(0x2aa<<1+flash_base)) ? static unsigned char SST1601_Program(unsigned int addr,unsigned int dat) ? { ?? CMD_ADDR0 = 0xaa; ?? CMD_ADDR1 = 0x55; ?? CMD_ADDR0 = 0xa0; ?? *((volatile unsigned int *)(addr)) = dat; ?? return check_toggle(); ? } ? static unsigned char check_toggle() ? { ?? volatile unsigned int newtoggle,oldtoggle; ?? oldtoggle = *((volatile unsigned int *)0x0); ?? while(1) ?? {???? ??? newtoggle = *((volatile unsigned int *)0x0);?????????? ??? if((oldtoggle & 0x40)==(newtoggle & 0x40)) ???????????????????? break;????????? ??? if(newtoggle & 0x20)?????????? //DQ5 ??? { ???????????????????? oldtoggle = *((volatile unsigned int *)0x0); ???????????????????? newtoggle = *((volatile unsigned int *)0x0);??????????????? ???????????????????? if((oldtoggle & 0x40)==(newtoggle & 0x40)) ??????????????????????????? break; ???????????????????? else ??????????????????????????? return 0;???????? //错误 ??? }???? ??? oldtoggle = newtoggle; ?? } ?? return 1;???????? //正确 ? } ? check_toggle()的原理是连续两次读取数据总线上的数据,判断数据总线上的第6位数值(DQ6)是否翻转,如果没有翻转则正 确,否则还要判断第5位(DQ5),以确定是否是因为超时而引起的翻转。 ④.擦除操作 ? 写操作只能使“1”变为“0”,而只有擦除才能使“0”变为“1”。因此在写之前一定要先擦除。擦除分为块擦除和整片擦除。块擦除 的过程为第一个周期是把命令0xAA写入地址为0x5555的命令寄存器中,第二个周期是把命令0x55写入地址为0x2AAA命令寄存器中, 第三个周期是把命令0x80再写入地址为0x5555命令寄存器中,第四个周期是把命令0xAA写入地址为0x5555的命令寄存器中,第五个 周期是把命令0x55再写入地址为0x2AAA命令寄存器中,第六个周期是把命令0x30写入要擦除块的首地址内。下面的函数为块擦除, 其中输入参数为要擦除块的首地址.【注】参考芯片手册 ? unsigned char SST1601_sector_erase(unsigned int section_addr) ? { ?? CMD_ADDR0 = 0xaa; ?? CMD_ADDR1 = 0x55; ?? CMD_ADDR0 = 0x80; ?? CMD_ADDR0 = 0xaa; ?? CMD_ADDR1 = 0x55; ?? *((unsigned int *)(section_addr)) = 0x30;??? ?? return check_toggle(); ? } ⑤.读取芯片ID ? 对norflash另一个比较常用的操作是读取芯片的ID。读取厂商ID的过程为第一个周期是把命令0xAA写入地址为0x555的命令寄存器 中,第二个周期是把命令0x55写入地址为0x2AA命令寄存器中,第三个周期是把命令0x90再写入地址为0x555命令寄存器中,第四个周期 为读取地址为0x100中的内容,即厂商ID(0x1C)。读取设备ID的过程的前三个周期与读取厂商ID相同,第四个周期是读取地址为0x01中 的内容,即设备ID(0x2249)。下面的函数为读取芯片ID: ? unsigned int get_en29lv160ab_id(void) ? { ?? U32 temp=0; ?? CMD_ADDR0 = 0xaa; ?? CMD_ADDR1 = 0x55; ?? CMD_ADDR0 = 0x90;? ?? temp = (*(volatile unsigned short *)(flash_base+ (0x100<<1)))<<16; ?? temp |= (*(volatile unsigned short *)(flash_base + (1<<1));?????? ?? return temp; ? } <3>.实例分析 ? 见附件:flash.c

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读