SPI Flash
使用了MX25L512的SPI接口的Flash
电路连接图:
总的大小512kb,即64kB,sector的大小为256 Bytes,block的大小为4k Bytes
调试时出现的问题:
1、Flash只能读数据,不能写数据
根源在于Flash的软件写保护没有去掉,这样,写、擦除,甚至写状态寄存器都不能执行。
1)Hardware Protection
Hardware Protection Mode(HPM):by using WP# going low to protect the BP0-BP1 bits and SRWD bit from data change
因为WP#是高电平,所以没有硬件保护,再来看软件保护。
2)Software Protection
Software Protection Mode(SPM):by using BP0-BP1 bits to set the part of flash protected from data change
通过下面几幅图可知,在WP#高电平情况下write status register可以改变SRWD、BP0、BP1的值为0,从而去掉软件写保护。
3)代码实现去除保护
//在所有需要修改的操作之前必须去除软件保护BP0,BP1
//FLASH的状态寄存器
//bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
//SRWD 0 0 0 BP1 BP0 WEL WIP
// 1=status write disable 1=write enable 1=write in process
#define MASK_CLEAR_BPX 0x73 //掩码,设置使能写状态寄存器,清除BP1、BP0
void SPI_WRITE_STATUS() //主要是清除保护,可以写数据
{
unsigned ;
SPI_WRITE_ENABLE(); //设置状态器WEL位为1,在进行写状态寄存器之前必须写使能
status=SPI_READ_STATUS();
NSSMD0=;
SPI0DAT=FLASH_WRITE_STATUS;
while(!SPIF);
SPIF=;
SPI0DAT=status&MASK_CLEAR_BPX;
while(!SPIF);
SPIF=;
NSSMD0=;//cs must go high at the byte boundary,otherwise instruction will be reject and not executed
do //query until WIP convert from 1 to 0 when write status register cycle is finished
{
status=SPI_READ_STATUS();
status=status&0x01;
}while(status);
}
2、sector大小为256 Bytes,但是连续写256 Bytes,只有最后的32 Bytes写进去了
在测试MX25L512的扇区的时候,老是遇到一个问题,写入256个字节,但是读出的是最后32个Bytes,前面的总是0xFF,于是就怀疑是不是扇区
的大小没有datasheet所说的那么大呢?最后测试发现扇区的大小只有32Bytes,如果连续写入的字节数大于32 Bytes,就会把除最后32 Bytes之外
的数据丢弃,只写最后的32 Bytes。仔细翻看datasheet,发现MX25L512MC-12G的扇区为256 Bytes,而MX25L512IE的扇区只有32Bytes原来具体
芯片规格和元件后缀名也有关系。
说明:sector是读写数据的最小单元,block是擦除的最小单元。(有时候sector概念类似于page,要看具体的芯片)
扇区被擦除后内部的数据变为0xFF。
3、SPI接口波形不对
虽然C8051F320已经交叉配置为串口和SPI接口,但是实际情况是还是要在输出的管脚PushPull,
P0MDOUT=0x1D;//0001 1101
否则可能SPI口的OUT输出驱动不了,导致波形都没有。
贴上Flash操作的代码:
#ifndef _SPI_CMD_H_ #define _SPI_CMD_H_ #include"misc.h" //////////////////////////////////////////////// //////////////////MX25L512的flash说明/////////////////// //page:256byte //sector:4kbyte //注意MX25L512MC-12G page为256 bytes //MX25L512IE.. page为32 bytes /////////////////////////////////////////////// #define FLASH_READ_ID 0x9F //读设备ID #define FLASH_WRITE_ENABLE 0x06 //写使能 #define FLASH_WRITE_DISABLE 0x04 //写禁止 #define FLASH_READ_STATUS 0x05 //读状态寄存器 #define FLASH_WRITE_STATUS 0x01 //写状态寄存器 #define FLASH_READ_DATA 0x03 //读数据 #define FLASH_WRITE_DATA 0x02 //写数据 #define FLASH_SECTOR_ERASE 0x20 //擦除一个扇区 ];//缓冲区全局变量,可以保存一个page的256字节 //在头文件中只是申明一下,不能定义,定义变量要在相应的C文件中定义 //以上不然会报错:multiple public definitions void SPI_READ_ID(); void SPI_WRITE_ENABLE(); void SPI_WRITE_DISABLE(); unsigned char SPI_READ_STATUS(); void SPI_WRITE_STATUS(); void SPI_SECTOR_ERASE(unsigned char sectors); void SPI_READ_Page(unsigned char sectors,unsigned char pages); void SPI_WRITE_Page(unsigned char *str,unsigned char sectors,unsigned char pages); void FillDBR(); #endif
#include"SPI_CMD.h"
//#define SPI0INT(x) {SPI0DAT=x;while(!SPIF);SPIF=0;}
//可以用这个定义来取代以下一大段的代码
//SPI0DAT=FLASH_READ_ID;
//while(!SPIF); ----->SPI0DAT=FLASH_READ_ID;
//SPIF=0;
void SPI_READ_ID()
{
NSSMD0=;
SPI0DAT=FLASH_READ_ID;
while(!SPIF);
SPIF=;
SPI0DAT=; //dummy write to output serial clock
while(!SPIF); //wait for value to be read
SPIF=;
sendChar(SPI0DAT);
SPI0DAT=;
while(!SPIF);
SPIF=;
sendChar(SPI0DAT);
SPI0DAT=;
while(!SPIF);
SPIF=;
sendChar(SPI0DAT);
NSSMD0=;
}
void SPI_WRITE_ENABLE()
{
NSSMD0=;
SPI0DAT=FLASH_WRITE_ENABLE;
while(!SPIF);
SPIF=;
NSSMD0=;
}
void SPI_WRITE_DISABLE()
{
NSSMD0=;
SPI0DAT=FLASH_WRITE_DISABLE;
while(!SPIF);
SPIF=;
NSSMD0=;
}
unsigned char SPI_READ_STATUS()
{
NSSMD0=;
SPI0DAT=FLASH_READ_STATUS;//可以将类似的这种形式做成一个宏定义
while(!SPIF);
SPIF=;
SPI0DAT=;
while(!SPIF);
SPIF=;
NSSMD0=;
return SPI0DAT;
}
//在所有需要修改的操作之前必须去除软件保护BP0,BP1
//FLASH的状态寄存器
//bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
//SRWD 0 0 0 BP1 BP0 WEL WIP
// 1=status write disable 1=write enable 1=write in process
#define MASK_CLEAR_BPX 0x73 //掩码,设置使能写状态寄存器,清除BP1、BP0
void SPI_WRITE_STATUS() //主要是清除保护,可以写数据
{
unsigned ;
SPI_WRITE_ENABLE(); //设置状态器WEL位为1,在进行写状态寄存器之前必须写使能
status=SPI_READ_STATUS();
NSSMD0=;
SPI0DAT=FLASH_WRITE_STATUS;
while(!SPIF);
SPIF=;
SPI0DAT=status&MASK_CLEAR_BPX;
while(!SPIF);
SPIF=;
NSSMD0=;//cs must go high at the byte boundary,otherwise instruction will be reject and not executed
do //query until WIP convert from 1 to 0 when write status register cycle is finished
{
status=SPI_READ_STATUS();
status=status&0x01;
}while(status);
}
void SPI_SECTOR_ERASE(unsigned char sectors)
{
unsigned ;
SPI_WRITE_ENABLE();
NSSMD0=;
SPI0DAT=FLASH_SECTOR_ERASE;
while(!SPIF);
SPIF=;
//any address in the sector,but i choose the first address of sector
SPI0DAT=0x00; //high address
while(!SPIF);
SPIF=;
SPI0DAT=sectors<<; //middle address
while(!SPIF);
SPIF=;
SPI0DAT=0x00; //low address
while(!SPIF);
SPIF=;
NSSMD0=;
do //query until WIP convert from 1 to 0 when write status register cycle is finished
{
status=SPI_READ_STATUS();
status=status&0x01;
}while(status);
}
unsigned ];
//读一页256 bytes
void SPI_READ_Page(unsigned char sectors,unsigned char pages)
{
unsigned ;
NSSMD0=;
SPI0DAT=FLASH_READ_DATA; //command
while(!SPIF);
SPIF=;
SPI0DAT=0x00; //read address
while(!SPIF);
SPIF=;
SPI0DAT=(sectors<<) + pages;
while(!SPIF);
SPIF=;
SPI0DAT=0x00;
while(!SPIF);
SPIF=;
;i<;i++) //read a page 256 bytes
{ //实测每页的数据只有32byte,所以一次连续写32byte
SPI0DAT=; //read datas out
while(!SPIF);
SPIF=;
buff[i]=SPI0DAT;
}
NSSMD0=;
}
//写一页256 bytes
void SPI_WRITE_Page(unsigned char *str,unsigned char sectors,unsigned char pages)
{
unsigned ;
unsigned ;
SPI_WRITE_ENABLE(); //在改变数据之前都要进行写使能操作
NSSMD0=;
SPI0DAT=FLASH_WRITE_DATA; //write command
while(!SPIF);
SPIF=;
SPI0DAT=0x00; //write address
while(!SPIF); //最高地址默认为0x00,所以不用传他的参数
SPIF=;
SPI0DAT=(sectors<<) + pages;
while(!SPIF);
SPIF=;
SPI0DAT=0x00;
while(!SPIF);
SPIF=;
;i<;i++) //write a page 256 bytes
{
SPI0DAT=str[i]; //write data in
while(!SPIF);
SPIF=;
}
NSSMD0=;
do //query until WIP convert from 1 to 0 when write cycle is finished
{
status=SPI_READ_STATUS();
status=status&0x01;
}while(status);
}
SPI Flash的更多相关文章
- Nand Flash,Nor Flash,CFI Flash,SPI Flash 之间的关系
前言: 在嵌入式开发中,如uboot的移植,kernel的移植都需要对Flash 有基本的了解.下面细说一下标题中的中Flash中的关系 一,Flash的内存存储结构 flash按照内部存 ...
- 【iCore、iCore2 双核心板】EPCS 实验(SPI Flash)(基于Verilog语言)
_____________________________________ 深入交流QQ群: A: 204255896(1000人超级群,可加入) B: 165201798(500人超级群,满员) C ...
- nand flash,nor flash,spi flash,片上RAM,片外RAM
Flash有掉电数据保存的特点,RAM掉电则数据丢失,但是RAM的速度更高,擦写次数理论上没有限制,而Flash则不行. Nand Flash相比其余的几种flash优势在于可擦写次数多,擦写速度快, ...
- 27.some company's Spi Flash chip replace altera epcsxxx
由于altera公司的epcsxxx芯片比较贵,所以一般用其它公司的spi flash芯片代替也可以.据AlteraFAE描述:“EPCS器件也是选用某家公司的SPIFlash,只是中间经过Alter ...
- OpenRisc-32-ORPSoC烧写外部spi flash
引言 经过前面的分析和介绍,我们对ORPSoC的启动过程(http://blog.csdn.net/rill_zhen/article/details/8855743)和 ORpSoC的debug子系 ...
- SPI FLASH与NOR FLASH的区别?
1.SPI Flash (即SPI Nor Flash)是Nor Flash的一种: 2.NOR Flash根据数据传输的位数可以分为并行(Parallel)NOR Flash和串行(SPI)NOR ...
- SPI Flash(W25Q16DV) 驱动
大体上可分为以下几个部分: 1.注册设备驱动 spi_register_driver 2.分配 mtd_info 结构体 3.配置 mtd_info 结构体 4.注册 mtd_info 结构体 构建 ...
- SPI Flash(W25Q16DV) 基本操作
读取厂家\设备 ID 发送 90H 指令,再发送 00h 的地址,然后接收即可. 代码如下: void SPIFlashReadID(int *pMID, int *pDID) { SPIFlash_ ...
- Jlink使用技巧之烧写SPI Flash存储芯片
前言 大多数玩单片机的人都知道Jlink可以烧写Hex文件,作为ARM仿真调试器,但是知道能烧写SPI Flash的人应该不多,本篇文章将介绍如何使用JLink来烧写或者读取SPI Flash存储器, ...
- SPI Flash Memory 芯片手册阅读
SPI Flash Memory 芯片手册阅读 信息来源
随机推荐
- Ubuntu系统下创建python数据挖掘虚拟环境
虚拟环境: 虚拟环境是用于创建独立的python环境,允许我们使用不同的python模块和版本,而不混淆. 让我们了解一下产品研发过程中虚拟环境的必要性,在python项目中,显然经常要使用不 ...
- windows程序设计读书笔记1——创建窗口
第一个win32程序,简单的创建窗口: #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ...
- QT使用WOL实现远程一键开机(局域网)
功能:让关机的电脑一键开机,需要目标电脑的主板支持,并且插上网线: 效果:相当于手动按了一下目标电脑的开关机按钮. 没啥技术含量,简单开说... 1.获取目标机MAC地址 QByteArray sMa ...
- Gradle方式构建Java多项目
0: 安装IDEA:Linux 上只需下载IDEA的包 并且将路径配置在PATH全局变量中./etc/profile export PATH=$PATH:/opt/Software/IDEA/idea ...
- SQL Server数据库空间管理 (2)
本篇内容主要解决剩余的两个问题:2).日志文件不停增长 4).自动增长和自动收缩 日志文件不停增长的解决 首先,当日志文件超过预期的时候,我们然要看看日志文件中存放了什么内容:DBCC LOG ; ...
- 'adb' 不是内部或外部命令,也不是可运行的程序
启动adb shell的时候,出现如下问题: 'adb' 不是内部或外部命令,也不是可运行的程序或批处理文件. 在确保自己的SDK安装正确的时候,就很好办了,找到SDK安装目录\platform-to ...
- 启动Tomcat的几种方式
启动Tomcat有两种场景,一是部署时启动,二是开发时启动.部署时基本上是通过war包来启动,而开发时的启动方式多种多样,下面拟介绍几种适用于开发时启动Tomcat的方法. 在DOS命令行启动 Apa ...
- iOS断言
来自:http://my.oschina.net/panyong/blog/205573 在看到xmpp项目中的一些代码时,看到如下,不懂该代码是啥意思, 如下: NSAssert(_xmppStre ...
- linux(边压缩边传输边解压)
比如我要转移旧VPS /home/wwwroot 下的web目录到新VPS(123.123.123.123)的/home/wwwroot 目录下 1.进入目录 cd /home/wwwroot ...
- 自动测试工具SilkTest全面介绍
象交互,并最终记录测试结果,用户可以根据这些测试结果来判断测试成功还是失败. 4Test 脚本语言 和绝大多数自动化测试工具一样, SilkTest 可以自动捕捉,检测和重复用户交互的操作从而驱动测试 ...