1.NOR与NAND的区别
Flash NOR NAND
接口 RAM-Like,引脚多 引脚少,复用(地址数据共用)
容量 小(1-32M) 大(128M+)
读 简单 复杂
写 发出特定命令(慢) 发出特定命令(快)
价格 贵 较便宜
缺点 无位反转、坏块 位反转、坏块
一般存放 bootloader(关键程序) 大文件、视频
xip 可以 不可以
xip(eXecute In Place),即芯片内执行,指应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。flash内执行是指nor flash 不需要初始化,可以直接在flash内执行代码。但往往只执行部分代码,比如初始化RAM.
2.命令表
UBOOT下读写数据
2.1 读数据
md.b为读命令
mw.w为写命令
md.b 0
2.2 读ID
Nor手册
往(555H)写入AAH
往(2AAH)写入55H
往(555H)写入90H
读(0)得到厂家(Manifacture)ID:C2H
读(1)得到设备(Device)ID:22C4/2249
但是由于地址是错开1位的(具体原因可查看第15章),则往CPU写的地址需要addr<<1,即(地址*2)因此:
UBOOT下
往(AAAH)写入AAH
往(554H)写入55H (这两步为解锁命令)
往(AAAH)写入90H(90H为命令)
读(0H)得到厂家(Manifacture)ID:C2H
读(2H)得到设备(Device)ID:22C4/2249
退出读ID状态(即复位)
mw.w aaa aa
mw.w 554 55
mw.w aaa 90
md.w 0 1 #读0地址1次
md.w 2 1
mw.w 0 F0
2.3 CFI模式
CFI(Common Flash Interface)
Nor手册
往(55H)写入98H(进入CFI模式)
读(27H)得到容量2^n的n
退出CFI模式(复位)
UBOOT下
往(AAH)写入98H(进入CFI模式)
读(4EH)得到容量2^n的n
往(0H)写入F0H
3.基本函数
3.1 写函数
Nor Flash 地址线21:即可访问2M内存,0x1FFFFF,其范围地址为 0~0x1FFFFF
#define NOR_FLASH_BASE 0 /* Nor Flash基地址 nor-->cs0,base_addr = 0 */
/* Nor Flash写入一个字
* 基地址:base,偏移地址:offset,写入的值:value
* eg: 55 98
* 往(0 + (0x55)<<1 )写入0x98
*/
void nor_write_word(unsigned int base,unsigned int offset,unsigned short value)
{
volatile unsigned short *p = (volatile unsigned short *) (base + offset<<1);
*p = value;
}
进行封装
void nor_cmd(unsigned int offset,unsigned short cmd)
{
nor_write_word(NOR_FLASH_BASE, offset, cmd);
}
3.2 读函数
/* Nor Flash读取一个字
* 基地址:base,偏移地址:offset
* eg: 55 98
* 往(0 + (0x55)<<1 )写入0x98
*/
unsigned int nor_read_word(unsigned int base,unsigned int offset)
{
volatile unsigned short *p = (volatile unsigned short *) (base + offset<<1);
return *p;
}
进行封装
unsigned int nor_dat(unsigned int offset)
{
return nor_read_word(NOR_FLASH_BASE, offset);
}
4.识别NOR
4.1 读取ID号
往(555H)写入AAH
往(2AAH)写入55H
往(555H)写入90H
读(0)得到厂家(Manifacture)ID:C2H
读(1)得到设备(Device)ID:22C4/2249
/* 1.打印 Manifacture ID、Device ID */
nor_unlock(); //解锁
nor_cmd(0x555,0x90);//读命令
manifa_id = nor_dat(0x00); //读厂家ID
device_id = nor_dat(0x01); //读设备ID
nor_reset_mode(); //复位
4.2 进入CFI Mode
往(55H)写98H
CFI(Common Flash Interface)
/* 1.进入CFI Mode */
nor_cmd(0x55,0x98);
4.3 读取容量
读(27H)得到容量bytes
/* 2.打印容量 */
size = 1<<(nor_dat(0x27));
printf("nor size = 0x%x, %dMrn",size,size>>20);
4.4 读取各个扇区
4.4.1 获得region数量
regions = nor_dat(0x2C);
1
4.4.2 region详细信息
erase block region :里面含有1个或多个block,它们大小都一样,一个nor含有1个或多个region,一个region含有1个或多个block(扇区)
Erase block region information:
前2字节+1:表示该region有多少个block
后2字节*256:表示该block的大小(bytes)
参考CFI标准:
regions的基址从0x2D开始
region_info_base = 0x2D;
block_addr = 0;
for(i = 0;i < regions; i++){
/* 获取block的数量和大小 */
blocks = 1 + nor_dat(region_info_base) + (nor_dat(region_info_base+1)<<8);//低2字节,获取block数量
block_size = 256 * (nor_dat(region_info_base+2) + (nor_dat(region_info_base+3)<<8));//高2字节,获取block大小
region_info_base += 4;//region读取的基址+4
/* 打印每个block的起始地址 */
for(j = 0;j < blocks; j++){
printf("0x%08x ",block_addr);
block_addr += block_size;
if( ((++cnt) % 5) == 0){ //每打印5个换行
printf("rn");
}
}
}
4.5 退出CFI Mode
nor_cmd(0x00,0xF0);//复位
5.写数据
5.1 写入
需要注意一个点,写入的数据是16位的,也就是两个字节,需要一次性写入一个字节,所以在写入之前需要对数据进行整合。
while(str[i] && str[i+1]){//两个字符都不为0时
data = str[i] + (str[i+1]<<8);
nor_unlock();//解锁
nor_cmd(0x555,0xA0); //写命令
nor_cmd(addr>>1,data);
/* 等待烧写完成:读数据Q6,无变化时表示完成*/
wait_ready(addr);
i += 2;
addr += 2;
}
5.2 判断数据写入完成
等待烧写完成:读数据Q6,无变化时表示完成
两次读取的结果不一致,说明数据还在变化,继续等待
//等待读取或擦除完毕
void wait_ready(unsigned int addr)
{
unsigned int pre_val;//上一次的值
unsigned int cur_val;
pre_val = nor_dat(addr>>1);
cur_val = nor_dat(addr>>1);
/* 两次读取的结果不一致,说明数据还在变化,继续等待 */
while((cur_val & (1<<6) != (pre_val &(1<<6)))){//当前的Q6不等于上一次的Q6则等待
pre_val = cur_val;//更新上一次的值
val = nor_dat(addr>>1);//重新获取
}
}
6.测试
6.1 读取
6.2 写入
6.3 擦除
7.问题
7.1 系统异常卡死
执行多次的菜单选择,导致系统卡死
该为定时器造成的异常错误,关闭定时器,则不会卡死
因为当测试nor进入CFI模式时,如果发生了中断,CPU必定读NOR,那么读不到正确的指令,导致程序异常崩溃
7.2 nor数据错误
读取设备ID时,读到的是0x002f,0xea00,改为反汇编中text的[0]上的数据
编译程序加上选项:指定ARM版本指令集-march=armv4 或者指定芯片类型 -mcpu=arm9tdmi
否则像如下的写入操作会被分成两个strb步骤(我们需要的是strh,一次性写入两个字节),最后导致读取设备ID和厂家ID的时候出错。
volatile unsigned short *p =value;
*p = value;
没加编译指定选项(分两次存2个字节)
加了编译指定芯片类型 -mcpu=arm9tdmi(一次性存2个字节)
8.擦除扇区
void erase_nor_flash(void)
{
unsigned int addr;
/* 获得地址*/
printf("Enter the address of sector to erase:");
addr = get_uint();
printf("Erase...rn");
nor_unlock();
nor_cmd(0x555,0x80); //擦除扇区命令
nor_unlock();
nor_cmd(addr>>1,0x30); //发出扇区地址
wait_ready(addr);
}
上一篇:【ARM裸板】Nand Flash基础与时序分析
下一篇:ARM处理器:“冯·诺依曼”体系结构和“哈佛”体系结构
推荐阅读最新更新时间:2024-11-17 17:15
设计资源 培训 开发板 精华推荐
- RD001501-0415,使用 Z51F0811 MCU 的 DMX512-A 接收器参考设计
- RV4145A(2线)低功率接地故障断路器的典型GFI应用电路
- LT3791MPFE 98% 效率 50W (25V/2A) 降压-升压型 LED 驱动器的典型应用电路
- 涂鸦网关插座(蓝牙版)
- STEVAL-IPM15B,基于 IGBT IPM 的 SLLIMM 第二系列模块 STGIB15CH60TS-L 的电机控制电源板
- LTC2242-12、12 位、250Msps 模数转换器的典型应用
- LTC3603EMSE 1.8V、2.5A 降压稳压器(1MHz、突发模式操作)的典型应用电路
- TDA7491MV13TR 25 W 单声道 BTL D 类音频放大器的典型应用
- EVB9512,使用 LAN9512 高速 USB 2.0 转 10/100 以太网集线器的评估板 客户
- nrf24l01发送端航模摇杆遥控