0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析spi flash驱动及其程序

ss 作者:工程师谭军 2018-10-07 11:26 次阅读
SPI Flash
首先它是个Flash,Flash是什么东西就不多说了(非易失性存储介质),分为NOR和NAND两种(NOR和NAND的区别本篇不做介绍)。SPI一种通信接口。那么严格的来说SPI Flash是一种使用SPI通信的Flash,即,可能指NOR也可能是NAND。但现在大部分情况默认下人们说的SPI Flash指的是SPI NorFlash。早期Norflash的接口是parallel的形式,即把数据线和地址线并排与IC的管脚连接。但是后来发现不同容量的Norflash不能硬件上兼容(数据线和地址线的数量不一样),并且封装比较大,占用了较大的PCB板位置,所以后来逐渐被SPI(串行接口)Norflash所取代。同时不同容量的SPI Norflash管脚也兼容封装也更小。,至于现在很多人说起NOR flash直接都以SPI flash来代称。
NorFlash根据数据传输的位数可以分为并行(Parallel,即地址线和数据线直接和处理器相连)NorFlash和串行(SPI,即通过SPI接口和处理器相连)NorFlash;区别主要就是:1、SPI NorFlash每次传输一bit位的数据,parallel连接的NorFlash每次传输多个bit位的数据(有x8和x16bit两种); 2、SPI NorFlash比parallel便宜,接口简单点,但速度慢。
NandFlash是地址数据线复用的方式,接口标准统一(x8bit和x16bit),所以不同容量再兼容性上基本没什么问题。但是目前对产品的需求越来越小型化以及成本要求也越来越高,所以SPI NandFlash渐渐成为主流,并且采用SPI NANDFlash方案,主控也可以不需要传统NAND控制器,只需要有SPI接口接口操作访问,从而降低成本。另外SPI NandFlash封装比传统的封装也小很多,故节省了PCB板的空间。
怎么用说白了对于Flash就是读写擦,也就是实现flash的驱动。先简单了解下spi flash的物理连接。
之前介绍SPI的时候说过,SPI接口目前的使用是多种方式(具体指的是物理连线有几种方式),Dual SPI、Qual SPI和标准的SPI接口(这种方式肯定不会出现在连接外设是SPI Flash上,这玩意没必要全双工),对于SPI Flash来说,主要就是Dual和Qual这两种方式。具体项目具体看了,理论上在CLK一定的情况下, 线数越多访问速度也越快。我们项目采用的Dual SPI方式,即两线。
浅析spi flash驱动及其程序

移植需要更改sendrcv函数里面内容,宏定义内容

[cpp] view plain copy《code class=“language-cpp”》#define DRV_SPI_FLASH_WRITE_ENABLE (0x06) //Write Enable

#define DRV_SPI_FLASH_WRITE_DISABLE (0x04) //Write Disable

#define DRV_SPI_FLASH_READ_STATUS_REG (0x05) //Read Status Register

#define DRV_SPI_FLASH_WRITE_STATUS_REG (0x01) //Write Status Register

#define DRV_SPI_FLASH_READ_DATA (0x03) //Read Data

#define DRV_SPI_FLASH_FAST_READ (0x0B) //Fast Read

#define DRV_SPI_FLASH_FAST_READ_DUAL_OUTPUT (0x3B) //Fast Read Dual Output

#define DRV_SPI_FLASH_PAGEPROGRAM (0x02) //Page Program

#define DRV_SPI_FLASH_BLOCK_ERASE (0xD8) //Block Erase(64KB)

#define DRV_SPI_FLASH_HALF_BLOCK_ERASE (0x52) //Half Block Erase(32KB)

#define DRV_SPI_FLASH_SECTOR_ERASE (0x20) //Sector Erase(4KB)

#define DRV_SPI_FLASH_CHIP_ERASE (0xC7) //Chip Erase

#define DRV_SPI_FLASH_JEDEC_ID (0x9F) //JEDEC ID

#define APP_SPI3_CS_LOW SCU_SetSpiCsn(SPI3_CSN,LOW)

#define APP_SPI3_CS_HIGH SCU_SetSpiCsn(SPI3_CSN,HIGH)

uint8_t DrvFlashSendRcvByte(uint8_t ucData)

{

uint8_t ucTemp;

while(SPI_GetFlagStatus(SGCC_SPI3_P,SPI_FLAG_RFNE))

ucTemp = SPI_ReceiveData(SGCC_SPI3_P);

SPI_SendData(SGCC_SPI3_P, ucData);

while(0 == SPI_GetFlagStatus(SGCC_SPI3_P,SPI_FLAG_RFNE));

ucTemp = SPI_ReceiveData(SGCC_SPI3_P);

return ucTemp;

}

uint32_t DrvFlashReadID(void)

{

uint32_t ulDevID = 0;

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_JEDEC_ID);

ulDevID |= DrvFlashSendRcvByte(0xFF) 《《 16;

ulDevID |= DrvFlashSendRcvByte(0xFF) 《《 8;

ulDevID |= DrvFlashSendRcvByte(0xFF);

APP_SPI3_CS_HIGH;

return ulDevID;

}

uint8_t DrvFlashReadStausReg(void)

{

uint8_t ucReg;

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_READ_STATUS_REG);

ucReg = DrvFlashSendRcvByte(0xFF);

APP_SPI3_CS_HIGH;

return ucReg;

}

void DrvFlashWaitBusy(void)

{

while((DrvFlashReadStausReg() & 0x01) == 0x01);

}

void DrvFlashWriteEnable(void)

{

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_WRITE_ENABLE);

APP_SPI3_CS_HIGH;

}

void DrvFlashWriteDisable(void)

{

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_WRITE_DISABLE);

APP_SPI3_CS_HIGH;

}

void DrvFlashReadData(uint8_t* pRcvBuf, uint32_t ulReAddr, uint16_t usReNum)

{

uint16_t i;

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_READ_DATA);

DrvFlashSendRcvByte((uint8_t)((ulReAddr)》》16));

DrvFlashSendRcvByte((uint8_t)((ulReAddr)》》8));

DrvFlashSendRcvByte((uint8_t)ulReAddr);

for(i=0; i 《 usReNum; i++)

{

pRcvBuf[i] = DrvFlashSendRcvByte(0XFF);

}

APP_SPI3_CS_HIGH;

}

void DrvFlashPageWrite(uint8_t* pWrBuf, uint32_t ulWrAddr, uint16_t usWrNum)

{

uint16_t i;

DrvFlashWriteEnable();

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_PAGEPROGRAM);

DrvFlashSendRcvByte((uint8_t)((ulWrAddr)》》16));

DrvFlashSendRcvByte((uint8_t)((ulWrAddr)》》8));

DrvFlashSendRcvByte((uint8_t)ulWrAddr);

for(i = 0; i 《 usWrNum; i++)

DrvFlashSendRcvByte(pWrBuf[i]);

APP_SPI3_CS_HIGH;

DrvFlashWaitBusy();

}

void DrvFlashWriteNoCheck(uint8_t* pBuffer, uint32_t addr, uint16_t num)

{

uint16_t pageremain;

pageremain = 256 - addr % 256;//鍗曢〉鍓╀綑瀛楄妭鏁�

if(num 《= pageremain)//涓嶅ぇ浜�256

pageremain = num;

while(1)

{

DrvFlashPageWrite(pBuffer, addr, pageremain);

if(num == pageremain)

break;//鍐欑粨鏉熶簡

else

{

pBuffer += pageremain;

addr += pageremain;

num -= pageremain;//鍑忓幓宸茬粡鍐欏叆鐨勫瓧鑺傛暟

if(num 》 256)

pageremain = 256;//鏈鍙互鍐欏叆涓�椤垫暟鎹�

else

pageremain = num;//鏈�鍚庝竴娆″啓

}

};

}

void DrvFlashWriteData(uint8_t* pBuffer,uint32_t addr,uint16_t num)

{

uint32_t secpos;

uint16_t secoff;

uint16_t secremain;

uint16_t i;

uint8_t * W25QXX_BUF;

uint8_t W25QXX_BUFFER[4096];

W25QXX_BUF = W25QXX_BUFFER;

secpos = addr / 4096;//鎵囧尯鍦板潃

secoff = addr % 4096;//鍦ㄦ墖鍖哄唴鐨勫亸绉�

secremain = 4096 - secoff;//鎵囧尯鍓╀綑绌洪棿澶у皬

// printf

if(num 《= secremain)//涓嶅ぇ浜庡綋鍓嶆墖鍖哄墿浣欏瓧鑺�

{

secremain = num;

}

while(1)

{

DrvFlashReadData(W25QXX_BUF, secpos * 4096, 4096);//璇诲彇鏁翠釜鎵囧尯

for(i = 0; i 《 secremain; i++)//鏍¢獙鏁版嵁

{

if(W25QXX_BUF[secoff + i] != 0XFF)//闇�瑕佹摝鍑�

break;

}

if(i 《 secremain)//闇�瑕佹摝鍑�

{

DrvFlashSectorErase(secpos * 4096);//鎿﹂櫎鏁翠釜鎵囧尯

for(i = 0; i 《 secremain; i++)

{

W25QXX_BUF[i + secoff] = pBuffer[i];//澶嶅埗

}

DrvFlashWriteNoCheck(W25QXX_BUF, secpos * 4096, 4096);//鍐欏叆鏁翠釜鎵囧尯

}

else

DrvFlashWriteNoCheck(pBuffer, addr, secremain);//鍐欏凡缁忔摝闄や簡鐨勶紝鐩存帴鍐欏叆鎵囧尯鍓╀綑绌洪棿

if(num == secremain)

break;//鍐欑粨鏉熶簡

else//

{

secpos++;//鎵囧尯鍦板潃澧炲姞1

secoff = 0;//鍋忕Щ浣嶇疆涓�0

pBuffer += secremain;//鎸囬拡鍋忕Щ

addr += secremain;//鍐欏湴鍧�鍋忕Щ

num -= secremain;//瀛楄妭鏁伴�掑噺

if(num 》 4096)

secremain = 4096;//涓嬩竴涓墖鍖鸿繕鏄啓涓嶅畬

else

secremain = num;//涓嬩竴涓墖鍖哄彲浠ュ啓瀹屼簡

}

};

}

void DrvFlashChipErase(void)

{

DrvFlashWriteEnable();

DrvFlashWaitBusy();

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_CHIP_ERASE);

APP_SPI3_CS_HIGH;

DrvFlashWaitBusy();

}

void DrvFlashSectorErase(uint32_t ulErAddr)

{

DrvFlashWriteEnable();

DrvFlashWaitBusy();

APP_SPI3_CS_LOW;

DrvFlashSendRcvByte(DRV_SPI_FLASH_SECTOR_ERASE);

DrvFlashSendRcvByte((uint8_t)((ulErAddr)》》16));

DrvFlashSendRcvByte((uint8_t)((ulErAddr)》》8));

DrvFlashSendRcvByte((uint8_t)ulErAddr);

APP_SPI3_CS_HIGH;

DrvFlashWaitBusy();

}

《/code》


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    11

    文章

    1717

    浏览量

    84340
  • SPI Flash
    +关注

    关注

    1

    文章

    13

    浏览量

    10215
收藏 人收藏

    评论

    相关推荐

    详细讲解重用外设驱动代码_SPI_NOR_Flash存储器

    第六章为重用外设驱动代码,本文内容为6.2 SPI NOR Flash 存储器。
    的头像 发表于 12-21 07:59 1.4w次阅读
    详细讲解重用外设<b class='flag-5'>驱动</b>代码_<b class='flag-5'>SPI_NOR_Flash</b>存储器

    开源的串行SPI Flash通用驱动库SFUD的应用

    SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异
    的头像 发表于 12-15 10:05 2246次阅读

    怎样从SPI FLASH加载FPGA程序

    需要将FPGA程序通过I2C或者RS232加载到FPGA内部,然后通过FPGA存储到SPI FLASH中,再次上电后从SPI FLASH加载
    发表于 04-29 14:46

    Cheap_Flash_FS(普通版)(SPI_Flash版)--嵌入式SPI_FLASH文件系统免费源码

    驱动接口函数.支持SPI_FLASH片上预分配功能(就是擦一次,写多个扇区的功能)加快了FLASH的写速度,且能降低内耗占用量.其上面可以运行FAT文件系统(支持多扇区操作).用户使用本代码,需要自己
    发表于 12-23 09:17

    SPI FLASH驱动

    、netdev组件2.3、协议栈组件2.4、netutils工具集软件包2.5、webnet软件包二、添加驱动和初始化代码1、SPI FLASH驱动2、网卡
    发表于 08-19 09:16

    SPI方式FPGA配置和SPI flash编程

    SPI方式FPGA配置和SPI flash编程
    发表于 05-16 18:01 164次下载
    <b class='flag-5'>SPI</b>方式FPGA配置和<b class='flag-5'>SPI</b> <b class='flag-5'>flash</b>编程

    基于红牛开发板的spi flash读写图片

    SPI:serial peripheral interface串行外围设备接口是一种常见的时钟同步串行通信接口。外置flash按接口分有总线flashSPI
    发表于 09-01 17:16 16次下载
    基于红牛开发板的<b class='flag-5'>spi</b> <b class='flag-5'>flash</b>读写图片

    SPI—外部FLASH-W25Q128

    -ST固件库版本:1.5.1 【 !】功能简介: 读写板载的SPI FLASH芯片。 学习目的:学习STM32的SPI驱动。 【 !!】注意事项: 板子的
    发表于 12-13 15:13 97次下载

    SPI flash是什么,关于SPI FLASH的读写问题

    SPI一种通信接口。那么严格的来说SPI Flash是一种使用SPI通信的Flash,即,可能指NOR也可能是NAND。
    的头像 发表于 09-18 14:38 10.1w次阅读
    <b class='flag-5'>SPI</b> <b class='flag-5'>flash</b>是什么,关于<b class='flag-5'>SPI</b> <b class='flag-5'>FLASH</b>的读写问题

    SPI flash如何运行程序SPI flash有哪些应用

    SPI一种通信接口。那么严格的来说SPI Flash是一种使用SPI通信的Flash,即,可能指NOR也可能是NAND。
    的头像 发表于 09-19 10:54 1.8w次阅读
    <b class='flag-5'>SPI</b> <b class='flag-5'>flash</b>如何运行<b class='flag-5'>程序</b>,<b class='flag-5'>SPI</b> <b class='flag-5'>flash</b>有哪些应用

    浅析FLASH读写----SPI原理及应用

    SPI一种通信接口。那么严格的来说SPI Flash是一种使用SPI通信的Flash,即,可能指NOR也可能是NAND。
    的头像 发表于 10-07 11:32 2.2w次阅读
    <b class='flag-5'>浅析</b><b class='flag-5'>FLASH</b>读写----<b class='flag-5'>SPI</b>原理及应用

    关于SPI_FLASH时序描述及驱动编程

    SPI_FLASH时序描述及驱动编程
    的头像 发表于 03-25 11:15 3173次阅读
    关于<b class='flag-5'>SPI_FLASH</b>时序描述及<b class='flag-5'>驱动</b>编程

    STM32_ SPI读写Flash

    STM32_SPI读写Flash
    的头像 发表于 04-08 10:26 4924次阅读
    STM32_ <b class='flag-5'>SPI</b>读写<b class='flag-5'>Flash</b>

    用于SPI软件的Windows 7驱动程序

    用于SPI软件的Windows 7驱动程序
    发表于 06-10 15:13 9次下载
    用于<b class='flag-5'>SPI</b>软件的Windows 7<b class='flag-5'>驱动程序</b>

    SPI Nand Flash简介

    1.SPI Nand Flash简介SPI Nand Flash顾名思义就是串行接口的Nand Flash,它和普通并行的Nand
    发表于 12-02 10:51 33次下载
    <b class='flag-5'>SPI</b> Nand <b class='flag-5'>Flash</b>简介