完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
NOR FLASH_MX29LV160DBTI
NOR flash带有SRAM接口,有足够的地址引脚来寻址,可以很容易地存取其内部的每一个字节。 NOR flash是只读存储器,可以轻易的读,却不能够轻易的写。写NOR FLASH需要一些特定的命令。 MX29LV160DBTI NOR flash有21位地址线接口,16 位数据线接口。 NOR flash的容量一般都比较小,一般常见最大的也就只有32M. NOR flash一般用来存一下内核,关键性的程序。 ‘ MX29LV160DBTI的原理图如下 以上图为例来写一些基本的底层代码 注意:由上图可知CPU的A1接的是NOR FALSH的A0,所以在一些地址数据传输上需要注意一些地址的移位! 写出一些基本的指令传送,地址传送,数据传送的函数 #define NOR_FLASH_BASE 0 //根据你的NOR FALSH与CPU连接,片选信号而定,由于我的NOR FLASH片选信号接的是nGCS0,所以基地址为0 void nor_write_word(unsigned int FLASH_base, unsigned int offset, unsigned int val) //向一个基本地址为FLASH_base的NORFALSH的offset地址写入data数据 { volatile unsigned short *p = (volatile unsigned short *)(NOR_FLASH_BASE + (offset 《《 1)); //定义一个双字节指针P *p = val; } void nor_write(unsigned int offset, unsigned int data) //向一个NORFALSH的地址写入data数据 { nor_write_word(NOR_FLASH_BASE, offset, data); } unsigned int nor_read_word(unsigned int base, unsigned int offset) //向一个基地址为base的NORFALSH的offset地址读出数据 { volatile unsigned short *p = (volatile unsigned short *)(base + (offset 《《 1)); return *p; } unsigned int nor_dat(unsigned int offset)//向NORFALSH的offset地址读出数据 { return nor_read_word(NOR_FLASH_BASE, offset); } 了解NOR FLASH 的命令操作 我们可以根据数据手册查看NOR FLASH 的一般命令操作。(擦除,写,读,进入CFI模式等) 由上图可知,如果想要访问芯片的厂家ID,我们需要4周期的命令才可以访问出数据。 同理设备ID也需要四个周期的命令才可以访问出数据。可知道我们芯片设备ID为22C4。 进入NOR FLASH的CFI模式进行查询 我们可以根据NOR FLASH的数据手册,得到如何去查看厂家ID以及其他有关芯片的资料。(例如有多少个region,每个region含有多少个block,每个block有多大)。 以下就是查看NOR_FLASH 一些基本数据的代码: void check_nor_flash(void) { char str[4]; unsigned int size; int regions, i; int region_info_base; int block_addr, blocks, block_size, j; int cnt; int vendor, device; //打印厂家ID、设备ID nor_cmd(0x555, 0xaa); //解锁 nor_cmd(0x2aa, 0x55); nor_cmd(0x555, 0x90); //read id vendor = nor_dat(0); device = nor_dat(1); nor_cmd(0, 0xf0); //reset nor_cmd(0x55, 0x98); //进入cfi模式 str[0] = nor_dat(0x10); str[1] = nor_dat(0x11); str[2] = nor_dat(0x12); str[3] = ‘ ’; printf(“str = %snr”, str); //打印进入CFI模式的QRY //打印容量 size = 1《《(nor_dat(0x27)); printf(“vendor id = 0x%x, device id = 0x%x, nor size = 0x%x, %dMnr”, vendor, device, size, size/(1024*1024)); //打印各个扇区的起始地址 /* 名词解释: * erase block region : 里面含有1个或多个block, 它们的大小一样 * 一个nor flash含有1个或多个region * 一个region含有1个或多个block(扇区) * Erase block region information: * 前2字节+1 : 表示该region有多少个block * 后2字节*256 : 表示block的大小 */ regions = nor_dat(0x2c); region_info_base = 0x2d; block_addr = 0; printf(“Block/Sector start Address:nr”); cnt = 0; for (i = 0; i 《 regions; i++) { blocks = 1 + nor_dat(region_info_base) + (nor_dat(region_info_base+1)《《8); block_size = 256 * (nor_dat(region_info_base+2) + (nor_dat(region_info_base+3)《《8)); region_info_base += 4; for (j = 0; j 《 blocks; j++) { /* 打印每个block的起始地址 */ //printf(“0x%08x ”, block_addr); printHex(block_addr); putchar(‘ ’); cnt++; block_addr += block_size; if (cnt % 5 == 0) printf(“nr”); } } printf(“nr”); /* 退出CFI模式 */ nor_cmd(0, 0xf0); } 进行NOR FLASH的读数据操作 void read_nor_flash(void) { unsigned int addr; volatile unsigned char *p; int i, j; unsigned char c; unsigned char str[16]; /* 获得地址 */ printf(“Enter the address to read: ”); addr = get_uint(); p = (volatile unsigned char *)addr; printf(“Data : nr”); /* 长度固定为64 */ for (i = 0; i 《 4; i++) { /* 每行打印16个数据 */ for (j = 0; j 《 16; j++) { /* 先打印数值 */ c = *p++; str[j] = c; printf(“%02x ”, c); } printf(“ ; ”); for (j = 0; j 《 16; j++) { /* 后打印字符 */ if (str[j] 《 0x20 || str[j] 》 0x7e) //不可视字符一律打印。.. putchar(‘。’); else putchar(str[j]); } printf(“nr”); } } 结果如下:(下面应该是我打印的地址为0的第一块的数据,也就是程序由GCC编译器编译的最开始的汇编代码) NOR FLASH的繁忙状态位 当我们在进行一些擦除或写操作时,NOR FALSH的擦写是需要时间的,我们可以根据等待状态位来判断是否擦除完成!芯片手册如下: 我们可以从芯片手册得知,当我在进行擦除和写操作时,数据位bit6一直在0和1之间切换(Toggling) 故可以根据这一特性写出一个等待擦除或写入完成的函数。 void wait_ready(unsigned int addr) { unsigned int val; unsigned int pre; pre = nor_dat(addr》》1); val = nor_dat(addr》》1); while ((val & (1《《6)) != (pre & (1《《6))) { pre = val; val = nor_dat(addr》》1); } } 进行NOR FLASH的擦除数据的操作 这里一定要注意硬件与NOR FLASH 的连接方式,因为之前的offset地址是基于NOR FLASH 的角度出发的 现在的地址是基于CPU的角度看到的,所以地址要右移1位!!!(CPU的A1 接的是NOR FLASH的A0 ) void erase_nor_flash(void) { unsigned int addr; /* 获得地址 */ printf(“Enter the address of sector to erase: ”); addr = get_uint(); printf(“erasing 。..nr”); nor_cmd(0x555, 0xaa); /* 解锁 */ nor_cmd(0x2aa, 0x55); nor_cmd(0x555, 0x80); /* erase sector */ nor_cmd(0x555, 0xaa); /* 解锁 */ nor_cmd(0x2aa, 0x55); nor_cmd(addr》》1, 0x30); /* 发出扇区地址 地址要右移一位 */ wait_ready(addr); } 进行NOR FLASH的写入数据的操作 void write_nor_flash(void) { unsigned int addr; unsigned char str[100]; int i, j; unsigned int val; /* 获得地址 */ printf(“Enter the address of sector to write: ”); addr = get_uint(); printf(“Enter the string to write: ”); gets(str); printf(“writing 。..nr”); /* str[0],str[1]==》16bit * str[2],str[3]==》16bit */ i = 0; j = 1; while (str[i] && str[j]) { val = str[i] + (str[j]《《8); /* 烧写 */ nor_cmd(0x555, 0xaa); /* 解锁 */ nor_cmd(0x2aa, 0x55); nor_cmd(0x555, 0xa0); /* program */ nor_cmd(addr》》1, val); /* 等待烧写完成 : 读数据, Q6无变化时表示结束 */ wait_ready(addr); i += 2; j += 2; addr += 2; } val = str[i]; /* 烧写 */ nor_cmd(0x555, 0xaa); /* 解锁 */ nor_cmd(0x2aa, 0x55); nor_cmd(0x555, 0xa0); /* program */ nor_cmd(addr》》1, val); /* 等待烧写完成 : 读数据, Q6无变化时表示结束 */ wait_ready(addr); } 以上就是我对NOR FLASH 的所有总结了!!! 我采用的NOR FLASH 型号就是MX29LV160DBTI,容量为2M,有4个区域,每个区域有块,由于每个区域的块的数量是不一样的,我也没有认真去看(浪一下~~)。 第一篇博客就写完了!!可能有一些不足的地方,希望大神的批评和指导!!! |
|
|
|
只有小组成员才能发言,加入小组>>
4273个成员聚集在这个小组
加入小组3275 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4216 浏览 1 评论
4221 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-10 16:10 , Processed in 0.380111 second(s), Total 45, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号