nor flash操作
这一节来了解在jz2440上的nor flash的操作,jz2440上有nor flash和nand flash两种flash,这两种flash的基本的差别如下
nor | nand | |
---|---|---|
接口 | 像内存一样,引脚较多 | 引脚少,可以复用 |
容量 | 小 | 大 |
读操作 | 简单,像内存一样直接读 | 复杂,需要使用指令 |
写操作 | 使用命令来写(慢) | 使用命令来写(快) |
特性 | 无位反转 | 存在位反转,坏块 |
jz2440上的Nor flash的接口如下图所示
jz2440中的nor flash配置为16位的位宽,从上图来看,CPU发出的地址LADDR1接到了nor flash的地址线A0上,所以nor flash看到的地址是CPU右移一位得到的
1、nor flash指令
nor flash是像内存一样的接口,所以它的读操作像内存一样直接去读就行了,对于nor flash的写操作就稍微麻烦一些了,需要使用固定的指令去对nor flash进行写操作,但是在写之前需要对nor flash进行擦除
在获取nor flash设备信息的时候,先进入nor flash的CFI模式,CFI(通用的flash接口),进入CFI模式之后就可以获取到nor flash的基本设备信息了
要获取的基本信息也就是上面这些了,下面通过一张表格来对这些内容进行整理
地址 | 指令 | 地址 | 指令 | |
---|---|---|---|---|
解锁 | 0x555 | 0xaa | 0x2aa | 0x55 |
复位 | 任意地址 | 0xf0 | ||
进入CFI模式 | 0x55 | 0x98 |
读ID | 解锁,往0x555写入0x90,读0地址是厂家ID,读1地址是设备ID,复位退出读ID模式 |
---|---|
读容量 | 进入CFI模式,读取0x27地址的值,可以计算出容量 |
读取regions容量 | 进入CFI模式,读取0x2c地址处的值 |
擦除块 | 先解锁,往0x555地址写入0x80,再解锁,往擦除地址处写入0x30 |
写操作 | 先解锁,往0x555地址写入0xa0,然后往写入地址处发送要写的值 |
对于nor flash的基本操作指令就了解了,在这里要对上面的regions进行说明,1个nor flash中含有1个或者多个regions,而一个regions含有一个或者多个block,读出regions之后还需要读出该regions含有多少个block,每一个block的容量是多少,从[2D,30]的地址就存在这些内容,[2D,2E]的值+1就表示该region含有多少block,[2F,30]*256表示一个block的容量是多少,然后往后移动4个字节获取下一个regions的信息
2、测试程序
封装对nor flash的一些指令函数
#define NOR_FLASH_BASE 0 /* jz2440 nor -> cs0 , base addr = 0 */
/* 在地址偏移0ff的地方发出数据value */
void nor_write_word(unsigned int base,unsigned int off,unsigned int value)
{
/* 发出指令,因为CPU的地址线A1接nor flash的地址线A0,所以这里发出的地址要向左偏移一位
nor flash接收的时候再向右偏移一位,就保证了地址不变
*/volatile unsigned short *p = (volatile unsigned short *)(base + (off << 1));*p = value;
}
/* 调用上面的函数 */
void nor_cmd(unsigned int off,unsigned int cmd)
{nor_write_word(NOR_FLASH_BASE,off,cmd);}
/* 读取两个字节的数据,地址同样要偏移 */
unsigned int nor_read_word(unsigned int base,unsigned int off)
{volatile unsigned short *p = (volatile unsigned short *)(base + (off << 1));return *p;
}
unsigned int nor_data(unsigned int off)
{return nor_read_word(NOR_FLASH_BASE,off);
}
测试主程序
void nor_flash_test()
{char c;printf("\n\r");while (1) {printf("\n\r[s] scan nor flash\n\r");printf("[e] erase nor flash\n\r");printf("[w] write nor flash\n\r");printf("[r] read nor flash\n\r");printf("[q] quit\n\r");printf("Enter selection: ");c = getchar();printf("%c\n\r",c);switch(c) {
case 'q':case 'Q':return;
case 's':case 'S': do_scan_nor();break;case 'e':case 'E':do_erase_nor();break;case 'w':case 'W':do_write_nor();break;case 'r':case 'R':do_read_nor();break;default:break;}printf("continue......");getchar();}
}
扫描设备函数
void do_scan_nor(void)
{
char str[4];unsigned int size;int regions,blocks,block_size;int block_addr,region_info_base;int i,j,cnt;int vender,device;/* 打印厂家ID、设备ID */nor_cmd(0x555,0xaa); // 解锁nor_cmd(0x2aa,0x55);nor_cmd(0x555,0x90); // 读IDvender = nor_data(0); //厂家IDdevice = nor_data(1); //设备IDnor_cmd(0,0xf0); // 复位nor_cmd(0x55, 0x98); // 进入CFI模式str[0] = nor_data(0x10);str[1] = nor_data(0x11);str[2] = nor_data(0x12);str[3] = '\0';size = 1 << nor_data(0x27); // 计算容量regions = nor_data(0x2c); // 计算regions个数/* 打印容量 */printf("nor size = 0x%x,%dM\n\r",size,size/(1024*1024));printf("venderID = 0x%x,deviceID = 0x%x\n\r",vender,device);/*打印设备扇区起始地址1个nor flash中含有1个或者多个region1个region含有1个或者多个block(扇区)*/region_info_base = 0x2d;block_addr = 0;printf("nor blocks:\n\r");cnt = 0;for (i = 0; i < regions; i++) {/* 组装2D和2E地址处的值,拼装成一个十六位的数据,这里为什么要左移呢,因为我们获取到的2个字节的数据高8位是0,
我们只要每两个字节的低字节就行了,所以将2E地址处的数据左移8位获得低字节处的数据和2D地址处的数据低字节进行拼装*/
blocks = 1 + nor_data(region_info_base) + (nor_data(region_info_base+1)<<8);block_size=256*(nor_data(region_info_base+2)+(nor_data(region_info_base+3)<<8));/* 地址往后偏移4个字节,读取下一个region的信息 */region_info_base += 4;for (j = 0; j < blocks; j++) {printHex(block_addr); /* 打印每个block的起始地址 */printf(" ");block_addr += block_size;cnt++;if (cnt % 5 == 0)printf("\n\r");}
}
/* 退回CFI模式 */nor_cmd(0x0, 0xf0);
}
擦除块操作
void do_erase_nor()
{unsigned int addr;printf("please enter the address to earse: ");addr = get_uint();nor_cmd(0x555,0xaa); // 解锁nor_cmd(0x2aa,0x55); // 擦除指令nor_cmd(0x555,0x80); // earse nor_cmd(0x555,0xaa); // 解锁nor_cmd(0x2aa,0x55);//nor_cmd(addr>>1,0x30); // 发出扇区地址nor_cmd(addr,0x30);wait_ready(addr); //等待完成
}
写操作
void do_write_nor()
{unsigned int addr;unsigned char str[100];int i,j;unsigned int val;printf("please enter the address to write: ");addr = get_uint();printf("please enter the string to write: ");gets(str);/* str[0] str[1]构造16位的数据,写 */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); //写指令//nor_cmd(addr>>1, val);nor_cmd(addr,val);/* 等待烧写完成 */wait_ready(addr);i += 2;j += 2;addr += 2;}val = str[i];nor_cmd(0x555,0xaa); // 解锁nor_cmd(0x2aa,0x55);nor_cmd(0x555,0xa0);//nor_cmd(addr>>1, val); //写入最后的数据nor_cmd(addr,val);/* 等待烧写完成 */wait_ready(addr);}
读函数
void do_read_nor(void)
{unsigned int addr;volatile unsigned char *p;unsigned char c,str[16];int i,j = 0;/* 地址,长度为64字节 */printf("please enter the address : ");addr = get_uint();p = (volatile unsigned char *)(addr<<1);for (i = 0; i < 4; i++) {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('.');elseputchar(str[j]);}}
}
等待函数
void wait_ready(unsigned int addr)
{unsigned int val;unsigned int pre;val = nor_data(addr >> 1);pre = nor_data(addr >> 1);while ((val & (1 << 6)) != (pre & (1 << 6))) {pre = val;val = nor_data(addr >> 1);}
}
测试程序均已写完,最底层的函数就是根据CPU和nor flash之间的地址差来发出地址和数据,上面一层的函数就是根据上面总结的操作指令对nor flash发出
固定的指令而已,在写程序的过程中遇到了一个让我不能想通的问题,在这里记录一下:
在上面我的擦除和读写函数里往地址处写值得时候都采用了两种写法,这两种写法都是可以的nor_cmd(0x555,0xa0); //写指令//nor_cmd(addr>>1, val);
比如说要执行写操作,我要往0x0010 0000的地址处写入一串字符,那么我要写的这个地址可以是CPU发出的实际地址,也可以理解成是nor flash看到的实际地址
1、如果要写入的地址是CPU发出的实际地址,那么在发出写指令的时候就要把地址就行右移nor_cmd(addr>>1, val);为什么呢?因为这个函数实际上调用的是nor_write_word函数,在nor_write_word函数里又会把CPU发出的地址进行左移,这样一来CPU发出的地址就和我们开始输入的地址是一样的,那么nor flash接收到的数据可就不是这个地址了,nor flash接收到的数据是CPU发出的地址右移一位得到的,所以在nor flash上实际写的地址并不是我们发出的地址,同理,在擦除地址的时候也要把地址就行右移一位,但是这个时候读数据操作是不需要进行移动的,因为进行读操作时是没有调用我们的更底层的发送指令的,直接将我们输入的地址发出去的,那么我们输入和写地址一样的地址进行读数据的话,读取到的是Nor flash上进行右移一位的地址处的数据,和之间写的地址就匹配上了。
2、如果要写入的地址是nor flash上的实际地址,那么在执行写操作时不需要把地址进行右移,这样的话调用nor_write_word函数把我们
发出的地址就行了左移,那么nor flash在接收的时候会把地址进行右移,看到的地址就是我们实际想要写入的地址,同理,在进行擦除操作的时候也是不需要将地址进行右移的,但是,这个时候要进行读操作的话,需要手动将要读取的地址进行左移一位,nor flash接收的右移一位的地址就和之前写和擦除的地址一致了,这样的话就和CPU实际发出的地址匹配上了,这样才能将读写的地址进行统一。
总结:这个问题在我写程序的时候困扰了我很久,一直没有想到这是怎么回事,后来慢慢的就想到了这一点,然后进行试验,结果正确。
nor flash操作相关推荐
- 会考flash中文字变形为三角形_关于信息技术会考 Flash操作题实用模版
<信息技术会考 Flash操作题.doc>由会员分享,可免费在线阅读全文,更多与<信息技术会考 Flash操作题>相关文档资源请在帮帮文库(www.woc88.com)数亿文档 ...
- 初中计算机flash操作,初中信息技术FLASH基础知识
<初中信息技术FLASH基础知识>由会员分享,可在线阅读,更多相关<初中信息技术FLASH基础知识(26页珍藏版)>请在人人文库网上搜索. 1.FLASH 第一课,一.Flas ...
- S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A)
S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A) S3C2440内部集成了一个Nand flash控制器.S3C2440的Nand flash控制器包含了如下的特性: l ...
- linux flash擦除命令,Linux下flash操作读、写、擦除步骤
描述 1. 背景介绍 在板上,ZYNQ PL部分通过EMC连接一片NOR FLASH,地址空间如下: 可以看到NOR FLASH的起始地址为0x80000000,这是物理地址,可以把数据存放在以该地址 ...
- 会考flash中文字变形为三角形_会考Flash操作知识点
<会考Flash操作知识点>由会员分享,可在线阅读,更多相关<会考Flash操作知识点(5页珍藏版)>请在人人文库网上搜索. 1.2012年会考Flash操作知识点会考标准要求 ...
- 单片机FLASH操作
FLASH 操作: 查看程序已经占用的FLASH的扇区,剩余的扇区就是可以操作而不会使程序发生错乱的区域. 找到listing文件夹下面的.map文件 搜索Memory Map of the imag ...
- 初中计算机flash考试题,【信息技术中考专区】Flash操作题专练(七)!
原标题:[信息技术中考专区]Flash操作题专练(七)! 微机中考·flash操作题 ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ 中考微机中 常用的 ...
- stm32 HAL库 Flash操作简介
stm32 HAL库 Flash操作简介 目录 第一stm32,flash介绍 查看代码段,以判断代码长度 flash的基本操作规则 stm32 HAL库 Flash操作指南 stm32f1xx_ha ...
- 会考flash中文字变形为三角形_信息技术会考 Flash操作题(样例3)
<信息技术会考 Flash操作题.doc>由会员分享,可免费在线阅读全文,更多与<信息技术会考 Flash操作题>相关文档资源请在帮帮文库(www.woc88.com)数亿文档 ...
- STM32 flash操作
对芯片内部flash进行操作的函数,包括读取,状态,擦除,写入等等,可以允许程序去操作flash上的数据. 基础应用1,FLASH时序延迟几个周期,等待总线同步操作.推荐按照单片机系统运行频率,0-2 ...
最新文章
- 浅谈Java throw, throws, try catch异常处理
- mysql server-存储引擎
- php mysql $_php中mysql语句的基本写法
- 一句 Task.Result 就死锁, 这代码还怎么写?
- 缓存在哪里_什么是MyBatis缓存技术
- 新款iPhone SE并未搭载U1超宽带芯片,后续恐不支持AirTag
- [转载] 远程方法调用(RMI)与远程过程调用(RPC)
- 想要做音乐玩音乐,有这一个软件就够了!
- 网吧系统快速设置工具
- 8位数控分频器的设计_数控分频器的设计实验报告
- 云计算概论-大数据与云计算
- 常用网线T568A或T568B类型详细讲解
- 易观CTO郭炜:开源,不是天才的甜点,而是勤奋者的盛宴
- HIT-SC-Lab1 Convex Hull的算法实现(JAVA)
- 机器学习-算法原理与编程实践(郑捷.著)-阅读笔记
- 真三国无双8二十四项修改器风灵月影版
- redis通过key模糊搜索_jedis模糊查询key
- [Spark版本更新]--2.3.0发行说明(一)
- 05- 防火墙用户管理
- Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed.
热门文章
- 用popart构建常染色体单倍型网络(Autosomal haplotypes network construction with popart)...
- 空气压缩机自动控制Multisim仿真
- 计算机论文可以写电子,计算机电子技术论文
- Mysql tinyint(1)与tinyint(4)的区别
- 浏览器 代理服务器无法响应
- 安装 Node.js
- 开发板ping不通虚拟机
- js 删除字符串中第一个逗号
- Local Storage和Session Storage详解
- Python08--文件读取及写入操作