Hexiwear 8MB NOR flash memory library.

Dependents:   HexiHeart_Main

Files at this revision

API Documentation at this revision

Comitter:
DimiterK
Date:
Sun Oct 09 23:05:55 2016 +0000
Commit message:
First release

Changed in this revision

W25Q64FV.cpp Show annotated file Show diff for this revision Revisions of this file
W25Q64FV.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/W25Q64FV.cpp	Sun Oct 09 23:05:55 2016 +0000
@@ -0,0 +1,283 @@
+#include "W25Q64FV.h"
+
+W25Q64FV::W25Q64FV(PinName mosi, PinName miso, PinName sclk, PinName cs, int frequency)
+{
+
+    this->cs = new DigitalOut(cs);    
+    this->cs->write(true);
+    this->frequency = frequency;
+
+    spi = new SPI(mosi, miso, sclk);    
+    spi->format(8, 0);
+    spi->frequency(frequency);
+}
+
+W25Q64FV::~W25Q64FV()
+{
+    delete spi;
+    delete cs;
+}
+
+uint16_t W25Q64FV::Id()
+{
+    cs->write(0);
+    spi->write(CMD_MANU_ID);
+    spi->write(0);
+    spi->write(0);
+    spi->write(0);
+    unsigned id = (spi->write(0) << 8) | spi->write(0);
+    cs->write(1);
+    return id;
+}
+
+uint32_t W25Q64FV::JEDECId()
+{
+    cs->write(0);
+    spi->write(CMD_JEDEC_ID);
+    unsigned id = (spi->write(0) << 16) | (spi->write(0) << 8) | spi->write(0);
+    cs->write(1);
+    return id;
+}
+
+void W25Q64FV::writeEnable(void)
+{
+    cs->write(0);
+    spi->write(CMD_WREN);
+    cs->write(1);
+}
+ 
+void W25Q64FV::writeDisable(void)
+{
+    cs->write(0);
+    spi->write(CMD_WR_DISABLE) ;
+    cs->write(1);
+}   
+
+uint8_t W25Q64FV::readStatus(void)
+{   
+    uint8_t data ;
+    cs->write(0);
+    spi->write(CMD_RDSR1) ;
+    data = spi->write(DUMMY) ;                     // dummy
+    cs->write(1);
+    return( data ) ;
+}
+
+void W25Q64FV::writeStatusReg(int addr)            // Write SR cmd 01h + 3B data
+{   
+    cs->write(0);
+    spi->write(CMD_WRSR1) ;                         // Write SR cmd 01h
+    spi->write((addr >> 16)&0xFF) ;                // address
+    spi->write((addr >>  8)&0xFF) ;
+    spi->write(addr & 0xFF) ;
+    cs->write(1);
+}
+
+void W25Q64FV::writeSecurityReg(int addr)          // WRSCUR cmd 2Fh + 1B data
+{   
+    cs->write(0);
+   // spi->write(CMD_WRSCUR) ;                         // Write SR cmd 01h
+    spi->write(addr & 0xFF) ;
+    cs->write(1);
+}
+
+
+uint8_t W25Q64FV::readByte(int addr)                  // Single Byte Read
+{
+    uint8_t data ;    
+    cs->write(0);
+    spi->write(CMD_READ_DATA) ;                         // send 03h
+    spi->write((addr >> 16)&0xFF) ;
+    spi->write((addr >>  8)&0xFF) ;
+    spi->write(addr & 0xFF) ;
+    data = spi->write(DUMMY) ;                     // write data is dummy 
+    cs->write(1);
+    return( data ) ;                                // return 1 byte 
+}
+ 
+bool W25Q64FV::read(uint32_t addr, uint8_t* dst, uint32_t len)
+{
+    cs->write(0);
+    spi->write(0x03);
+    spi->write((addr >> 16) & 0xff);
+    spi->write((addr >> 8) & 0xff);
+    spi->write(addr & 0xff);
+    for (uint32_t i=0; i<len; ++i)
+        dst[i] = spi->write(0);
+    cs->write(1);
+    
+    return true;
+}
+
+void W25Q64FV::hsread(uint32_t addr, uint8_t* dst, uint32_t len, int frequency)
+{
+    int save_frequency = this->frequency;
+    spi->frequency(frequency);
+    cs->write(0);
+    spi->write(0x0B);
+    spi->write((addr >> 16) & 0xff);
+    spi->write((addr >> 8) & 0xff);
+    spi->write(addr & 0xff);
+    spi->write(0); // dummy
+    for (uint32_t i=0; i<len; ++i)
+        dst[i] = spi->write(0);
+    cs->write(1);
+    spi->frequency(save_frequency);
+}
+
+uint8_t W25Q64FV::readSFDP(int addr)               // Read SFDP
+{
+    uint8_t data ;    
+    cs->write(0);
+    spi->write(CMD_READ_SFDP) ;                       // send cmd 5Ah
+    spi->write((addr >> 16)&0xFF) ;                // address[23:16]
+    spi->write((addr >>  8)&0xFF) ;                // address[15:8]
+    spi->write(addr & 0xFF) ;                      // address[7:0]
+    spi->write(DUMMY) ;                            // dummy cycle
+    data = spi->write(DUMMY) ;                     // return 1 byte 
+    cs->write(1);
+    return( data ) ;
+}
+
+uint8_t W25Q64FV::wait_while_busy(void)
+{
+    uint8_t temp = 0;
+    cs->write(0);           //Enable device
+    spi->write(CMD_RDSR1);   //Send RDSR command
+    temp = spi->write(DUMMY);
+    cs->write(1);          //Disable
+    if (temp & 0x01) return 1;
+    else return 0;
+}
+
+
+bool W25Q64FV::page_program(uint32_t addr, uint8_t* write_buffer, uint8_t len)
+{
+    // no point in writing FF as an empty sector already has those
+    // (and if not empty, write won't succeed)
+    bool skipped = false;
+    while (len > 0 && *write_buffer == 0xFF)
+    {
+        ++write_buffer;
+        --len;
+        ++addr;
+        skipped = true;
+    }
+    if (len == 0 && skipped)
+        return true; // special case when succeeds when nothing to do
+
+    if (len < 1 || len > 256)
+        return false;
+        
+    // write enable
+    writeEnable();
+
+    cs->write(0);
+    spi->write(0x02);
+    spi->write((uint8_t)(addr >> 16));
+    spi->write((uint8_t)(addr >> 8));
+    spi->write((uint8_t)addr);
+    for (uint16_t i=0; i<len; ++i)
+        spi->write(write_buffer[i]);
+    cs->write(1);
+    wait_while_busy();
+    
+    return true;
+}
+
+void W25Q64FV::sector_erase_4k(uint32_t addr)
+{
+    cs->write(0);
+    spi->write(CMD_ERASE_SECTOR);
+    spi->write((uint8_t)(addr >> 16));
+    spi->write((uint8_t)(addr >> 8));
+    spi->write((uint8_t)addr);
+    cs->write(1);
+    wait_while_busy();
+}
+
+void W25Q64FV::block_erase_32k(uint32_t addr)
+{
+    cs->write(0);
+    spi->write(CMD_ERASE_BLOCK32);
+    spi->write((uint8_t)(addr >> 16));
+    spi->write((uint8_t)(addr >> 8));
+    spi->write((uint8_t)addr);
+    cs->write(1);
+    wait_while_busy();
+}    
+
+void W25Q64FV::block_erase_64k(uint32_t addr)
+{
+    cs->write(0);
+    spi->write(CMD_ERASE_BLOCK64);
+    spi->write((uint8_t)(addr >> 16));
+    spi->write((uint8_t)(addr >> 8));
+    spi->write((uint8_t)addr);
+    cs->write(1);
+    wait_while_busy();
+}    
+
+void W25Q64FV::chip_erase()
+{
+    cs->write(0);
+    spi->write(CMD_ERASE_CHIP);
+    cs->write(1);
+    wait_while_busy();
+}
+
+
+
+
+
+
+void W25Q64FV::writeArray(uint32_t address, uint8_t* pData, uint32_t arrayLength)
+{
+    unsigned int i = 0;
+    cs->write(0);                        //Enable device
+    spi->write(CMD_WREN);                //Send WREN command
+    cs->write(1);                      //Disable device
+
+    cs->write(0);                        //Enable device
+    spi->write(CMD_PAGEPROG);            //Send Byte Program command
+    spi->write((uint8_t)(address >> 16) & 0xFF);
+    spi->write((uint8_t)(address >>  8) & 0xFF);
+    spi->write(0x00);
+
+    for (i=0;i<arrayLength;i++)
+    {
+        spi->write(pData[i]);            //Send byte to be programmed 
+    }
+    cs->write(1);              //Disable device
+ 
+    //Wait Busy
+    while ((readStatus() & 0x01) == 0x01) //Waste time until not busy
+    {
+    }
+}
+
+
+void W25Q64FV::readArray(uint32_t address, uint8_t* pData, uint32_t arrayLength)
+{
+    unsigned int i = 0;
+
+    cs->write(0);                                    //Enable device
+    spi->write(CMD_READ_DATA);                       //Read command
+    spi->write((uint8_t)(address >> 16));
+    spi->write((uint8_t)(address >>  8));
+    spi->write((uint8_t) address);
+
+    for (i = 0; i <arrayLength; i++)                //Read until no_bytes is reached
+    {
+        pData[i] = spi->write(DUMMY);                      //Receive bytes
+    }
+    cs->write(1);                                  //Disable device
+
+    //Wait Busy
+    while (readStatus() & 0x01)      //Waste time until not busy
+    {
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/W25Q64FV.h	Sun Oct 09 23:05:55 2016 +0000
@@ -0,0 +1,102 @@
+#include <mbed.h>
+#include <stdint.h>
+
+#define CMD_WREN                0x06
+#define CMD_WR_DISABLE          0x04
+#define CMD_RDSR1               0x05
+#define CMD_RDSR2               0x35
+#define CMD_WRSR1               0x01  //write status register
+#define CMD_PAGEPROG            0x02
+
+#define CMD_ERASE_SECTOR        0x20
+#define CMD_ERASE_BLOCK32       0x52
+#define CMD_ERASE_BLOCK64       0xD8
+#define CMD_ERASE_CHIP          0x60
+
+#define CMD_PROG_SUSPEND        0x75
+#define CMD_PROG_RESUME         0x7A
+#define CMD_PWR_DOWN            0xB9
+
+#define CMD_READ_DATA           0x03
+#define CMD_READ_HS             0x0B
+
+#define CMD_MANU_ID             0x90        
+#define CMD_JEDEC_ID            0x9F        // Read Manufacturer and JDEC Device ID 
+#define CMD_UNIQUE_ID           0x4B
+
+#define CMD_READ_SFDP           0x5A
+#define CMD_ERASE_SEC_REG       0x44
+#define CMD_PROG_SEC_REG        0x42
+#define CMD_READ_SEC_REG        0x48
+#define CMD_ENABLE_RES          0x66
+#define CMD_RESET               0x99
+
+#define DUMMY                   0x00 // Dummy byte which can be changed to any value
+
+
+class W25Q64FV
+{
+public:
+
+    static const int SID_LEN = 32;
+    static const int SECTOR_LEN = 4096;
+    static const int PAGE_LEN = 256;
+    static const int MAX_ADDR = 0x7FFFFF;
+
+private:
+
+    SPI* spi;
+    DigitalOut* cs;
+
+    int frequency; 
+    static uint8_t sector_buffer[SECTOR_LEN];
+
+
+public:
+    W25Q64FV(PinName mosi, PinName miso, PinName sclk, PinName cs, int frequency=10000000);
+    ~W25Q64FV();
+    
+    uint16_t Id();
+    uint32_t JEDECId();
+
+    // Read Status Register    
+    // bit 0 BUSY 1=Write in progress
+    // bit 1 WEL  1=Write Enabled
+    // bit 2 BP0  block write protection
+    // bit 3 BP1  block write protection
+    // bit 4 BP2  block write protection
+    // bit 5 BP3  block write protection
+    // bit 6 SEC  1=Security ID space locked
+    // bit 7 BPL  1=BP0..BP3 are read-only, 0=r/w
+    uint8_t readStatus();
+    void    writeStatusReg(int addr); // Write Status Register
+    
+    void    writeEnable();            // Write Enable
+    void    writeDisable();           // Write Disable
+    
+    void    writeSecurityReg(int addr);
+
+    uint8_t wait_while_busy(void);
+
+    uint8_t readByte(int32_t addr);
+    bool    read(uint32_t addr, uint8_t* dst, uint32_t len);
+    
+    void    hsread(uint32_t addr, uint8_t* dst, uint32_t len, int frequency);
+
+
+    uint8_t readSFDP(int addr);
+
+    void    sector_erase_4k(uint32_t addr);
+    void    block_erase_32k(uint32_t addr);
+    void    block_erase_64k(uint32_t addr);
+    void    chip_erase();
+
+    bool    page_program(uint32_t addr, uint8_t* write_buffer, uint8_t len);
+
+    bool    write(int32_t addr, uint8_t* write_buffer, int32_t len);
+    
+    void    writeArray(uint32_t address, uint8_t* pData, uint32_t arrayLength);
+    void    readArray(uint32_t address, uint8_t* pData, uint32_t arrayLength);
+
+    
+};
\ No newline at end of file