Hexiwear 8MB NOR flash memory library.
Revision 0:b71060e03299, committed 2016-10-09
- 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 |
diff -r 000000000000 -r b71060e03299 W25Q64FV.cpp --- /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 + { + } +} + + +
diff -r 000000000000 -r b71060e03299 W25Q64FV.h --- /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