Hexiwear 8MB NOR flash memory library.
W25Q64FV.cpp
- Committer:
- DimiterK
- Date:
- 2016-10-09
- Revision:
- 0:b71060e03299
File content as of revision 0:b71060e03299:
#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 { } }