Hexiwear 8MB NOR flash memory library.

Dependents:   HexiHeart_Main

Committer:
DimiterK
Date:
Sun Oct 09 23:05:55 2016 +0000
Revision:
0:b71060e03299
First release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DimiterK 0:b71060e03299 1 #include "W25Q64FV.h"
DimiterK 0:b71060e03299 2
DimiterK 0:b71060e03299 3 W25Q64FV::W25Q64FV(PinName mosi, PinName miso, PinName sclk, PinName cs, int frequency)
DimiterK 0:b71060e03299 4 {
DimiterK 0:b71060e03299 5
DimiterK 0:b71060e03299 6 this->cs = new DigitalOut(cs);
DimiterK 0:b71060e03299 7 this->cs->write(true);
DimiterK 0:b71060e03299 8 this->frequency = frequency;
DimiterK 0:b71060e03299 9
DimiterK 0:b71060e03299 10 spi = new SPI(mosi, miso, sclk);
DimiterK 0:b71060e03299 11 spi->format(8, 0);
DimiterK 0:b71060e03299 12 spi->frequency(frequency);
DimiterK 0:b71060e03299 13 }
DimiterK 0:b71060e03299 14
DimiterK 0:b71060e03299 15 W25Q64FV::~W25Q64FV()
DimiterK 0:b71060e03299 16 {
DimiterK 0:b71060e03299 17 delete spi;
DimiterK 0:b71060e03299 18 delete cs;
DimiterK 0:b71060e03299 19 }
DimiterK 0:b71060e03299 20
DimiterK 0:b71060e03299 21 uint16_t W25Q64FV::Id()
DimiterK 0:b71060e03299 22 {
DimiterK 0:b71060e03299 23 cs->write(0);
DimiterK 0:b71060e03299 24 spi->write(CMD_MANU_ID);
DimiterK 0:b71060e03299 25 spi->write(0);
DimiterK 0:b71060e03299 26 spi->write(0);
DimiterK 0:b71060e03299 27 spi->write(0);
DimiterK 0:b71060e03299 28 unsigned id = (spi->write(0) << 8) | spi->write(0);
DimiterK 0:b71060e03299 29 cs->write(1);
DimiterK 0:b71060e03299 30 return id;
DimiterK 0:b71060e03299 31 }
DimiterK 0:b71060e03299 32
DimiterK 0:b71060e03299 33 uint32_t W25Q64FV::JEDECId()
DimiterK 0:b71060e03299 34 {
DimiterK 0:b71060e03299 35 cs->write(0);
DimiterK 0:b71060e03299 36 spi->write(CMD_JEDEC_ID);
DimiterK 0:b71060e03299 37 unsigned id = (spi->write(0) << 16) | (spi->write(0) << 8) | spi->write(0);
DimiterK 0:b71060e03299 38 cs->write(1);
DimiterK 0:b71060e03299 39 return id;
DimiterK 0:b71060e03299 40 }
DimiterK 0:b71060e03299 41
DimiterK 0:b71060e03299 42 void W25Q64FV::writeEnable(void)
DimiterK 0:b71060e03299 43 {
DimiterK 0:b71060e03299 44 cs->write(0);
DimiterK 0:b71060e03299 45 spi->write(CMD_WREN);
DimiterK 0:b71060e03299 46 cs->write(1);
DimiterK 0:b71060e03299 47 }
DimiterK 0:b71060e03299 48
DimiterK 0:b71060e03299 49 void W25Q64FV::writeDisable(void)
DimiterK 0:b71060e03299 50 {
DimiterK 0:b71060e03299 51 cs->write(0);
DimiterK 0:b71060e03299 52 spi->write(CMD_WR_DISABLE) ;
DimiterK 0:b71060e03299 53 cs->write(1);
DimiterK 0:b71060e03299 54 }
DimiterK 0:b71060e03299 55
DimiterK 0:b71060e03299 56 uint8_t W25Q64FV::readStatus(void)
DimiterK 0:b71060e03299 57 {
DimiterK 0:b71060e03299 58 uint8_t data ;
DimiterK 0:b71060e03299 59 cs->write(0);
DimiterK 0:b71060e03299 60 spi->write(CMD_RDSR1) ;
DimiterK 0:b71060e03299 61 data = spi->write(DUMMY) ; // dummy
DimiterK 0:b71060e03299 62 cs->write(1);
DimiterK 0:b71060e03299 63 return( data ) ;
DimiterK 0:b71060e03299 64 }
DimiterK 0:b71060e03299 65
DimiterK 0:b71060e03299 66 void W25Q64FV::writeStatusReg(int addr) // Write SR cmd 01h + 3B data
DimiterK 0:b71060e03299 67 {
DimiterK 0:b71060e03299 68 cs->write(0);
DimiterK 0:b71060e03299 69 spi->write(CMD_WRSR1) ; // Write SR cmd 01h
DimiterK 0:b71060e03299 70 spi->write((addr >> 16)&0xFF) ; // address
DimiterK 0:b71060e03299 71 spi->write((addr >> 8)&0xFF) ;
DimiterK 0:b71060e03299 72 spi->write(addr & 0xFF) ;
DimiterK 0:b71060e03299 73 cs->write(1);
DimiterK 0:b71060e03299 74 }
DimiterK 0:b71060e03299 75
DimiterK 0:b71060e03299 76 void W25Q64FV::writeSecurityReg(int addr) // WRSCUR cmd 2Fh + 1B data
DimiterK 0:b71060e03299 77 {
DimiterK 0:b71060e03299 78 cs->write(0);
DimiterK 0:b71060e03299 79 // spi->write(CMD_WRSCUR) ; // Write SR cmd 01h
DimiterK 0:b71060e03299 80 spi->write(addr & 0xFF) ;
DimiterK 0:b71060e03299 81 cs->write(1);
DimiterK 0:b71060e03299 82 }
DimiterK 0:b71060e03299 83
DimiterK 0:b71060e03299 84
DimiterK 0:b71060e03299 85 uint8_t W25Q64FV::readByte(int addr) // Single Byte Read
DimiterK 0:b71060e03299 86 {
DimiterK 0:b71060e03299 87 uint8_t data ;
DimiterK 0:b71060e03299 88 cs->write(0);
DimiterK 0:b71060e03299 89 spi->write(CMD_READ_DATA) ; // send 03h
DimiterK 0:b71060e03299 90 spi->write((addr >> 16)&0xFF) ;
DimiterK 0:b71060e03299 91 spi->write((addr >> 8)&0xFF) ;
DimiterK 0:b71060e03299 92 spi->write(addr & 0xFF) ;
DimiterK 0:b71060e03299 93 data = spi->write(DUMMY) ; // write data is dummy
DimiterK 0:b71060e03299 94 cs->write(1);
DimiterK 0:b71060e03299 95 return( data ) ; // return 1 byte
DimiterK 0:b71060e03299 96 }
DimiterK 0:b71060e03299 97
DimiterK 0:b71060e03299 98 bool W25Q64FV::read(uint32_t addr, uint8_t* dst, uint32_t len)
DimiterK 0:b71060e03299 99 {
DimiterK 0:b71060e03299 100 cs->write(0);
DimiterK 0:b71060e03299 101 spi->write(0x03);
DimiterK 0:b71060e03299 102 spi->write((addr >> 16) & 0xff);
DimiterK 0:b71060e03299 103 spi->write((addr >> 8) & 0xff);
DimiterK 0:b71060e03299 104 spi->write(addr & 0xff);
DimiterK 0:b71060e03299 105 for (uint32_t i=0; i<len; ++i)
DimiterK 0:b71060e03299 106 dst[i] = spi->write(0);
DimiterK 0:b71060e03299 107 cs->write(1);
DimiterK 0:b71060e03299 108
DimiterK 0:b71060e03299 109 return true;
DimiterK 0:b71060e03299 110 }
DimiterK 0:b71060e03299 111
DimiterK 0:b71060e03299 112 void W25Q64FV::hsread(uint32_t addr, uint8_t* dst, uint32_t len, int frequency)
DimiterK 0:b71060e03299 113 {
DimiterK 0:b71060e03299 114 int save_frequency = this->frequency;
DimiterK 0:b71060e03299 115 spi->frequency(frequency);
DimiterK 0:b71060e03299 116 cs->write(0);
DimiterK 0:b71060e03299 117 spi->write(0x0B);
DimiterK 0:b71060e03299 118 spi->write((addr >> 16) & 0xff);
DimiterK 0:b71060e03299 119 spi->write((addr >> 8) & 0xff);
DimiterK 0:b71060e03299 120 spi->write(addr & 0xff);
DimiterK 0:b71060e03299 121 spi->write(0); // dummy
DimiterK 0:b71060e03299 122 for (uint32_t i=0; i<len; ++i)
DimiterK 0:b71060e03299 123 dst[i] = spi->write(0);
DimiterK 0:b71060e03299 124 cs->write(1);
DimiterK 0:b71060e03299 125 spi->frequency(save_frequency);
DimiterK 0:b71060e03299 126 }
DimiterK 0:b71060e03299 127
DimiterK 0:b71060e03299 128 uint8_t W25Q64FV::readSFDP(int addr) // Read SFDP
DimiterK 0:b71060e03299 129 {
DimiterK 0:b71060e03299 130 uint8_t data ;
DimiterK 0:b71060e03299 131 cs->write(0);
DimiterK 0:b71060e03299 132 spi->write(CMD_READ_SFDP) ; // send cmd 5Ah
DimiterK 0:b71060e03299 133 spi->write((addr >> 16)&0xFF) ; // address[23:16]
DimiterK 0:b71060e03299 134 spi->write((addr >> 8)&0xFF) ; // address[15:8]
DimiterK 0:b71060e03299 135 spi->write(addr & 0xFF) ; // address[7:0]
DimiterK 0:b71060e03299 136 spi->write(DUMMY) ; // dummy cycle
DimiterK 0:b71060e03299 137 data = spi->write(DUMMY) ; // return 1 byte
DimiterK 0:b71060e03299 138 cs->write(1);
DimiterK 0:b71060e03299 139 return( data ) ;
DimiterK 0:b71060e03299 140 }
DimiterK 0:b71060e03299 141
DimiterK 0:b71060e03299 142 uint8_t W25Q64FV::wait_while_busy(void)
DimiterK 0:b71060e03299 143 {
DimiterK 0:b71060e03299 144 uint8_t temp = 0;
DimiterK 0:b71060e03299 145 cs->write(0); //Enable device
DimiterK 0:b71060e03299 146 spi->write(CMD_RDSR1); //Send RDSR command
DimiterK 0:b71060e03299 147 temp = spi->write(DUMMY);
DimiterK 0:b71060e03299 148 cs->write(1); //Disable
DimiterK 0:b71060e03299 149 if (temp & 0x01) return 1;
DimiterK 0:b71060e03299 150 else return 0;
DimiterK 0:b71060e03299 151 }
DimiterK 0:b71060e03299 152
DimiterK 0:b71060e03299 153
DimiterK 0:b71060e03299 154 bool W25Q64FV::page_program(uint32_t addr, uint8_t* write_buffer, uint8_t len)
DimiterK 0:b71060e03299 155 {
DimiterK 0:b71060e03299 156 // no point in writing FF as an empty sector already has those
DimiterK 0:b71060e03299 157 // (and if not empty, write won't succeed)
DimiterK 0:b71060e03299 158 bool skipped = false;
DimiterK 0:b71060e03299 159 while (len > 0 && *write_buffer == 0xFF)
DimiterK 0:b71060e03299 160 {
DimiterK 0:b71060e03299 161 ++write_buffer;
DimiterK 0:b71060e03299 162 --len;
DimiterK 0:b71060e03299 163 ++addr;
DimiterK 0:b71060e03299 164 skipped = true;
DimiterK 0:b71060e03299 165 }
DimiterK 0:b71060e03299 166 if (len == 0 && skipped)
DimiterK 0:b71060e03299 167 return true; // special case when succeeds when nothing to do
DimiterK 0:b71060e03299 168
DimiterK 0:b71060e03299 169 if (len < 1 || len > 256)
DimiterK 0:b71060e03299 170 return false;
DimiterK 0:b71060e03299 171
DimiterK 0:b71060e03299 172 // write enable
DimiterK 0:b71060e03299 173 writeEnable();
DimiterK 0:b71060e03299 174
DimiterK 0:b71060e03299 175 cs->write(0);
DimiterK 0:b71060e03299 176 spi->write(0x02);
DimiterK 0:b71060e03299 177 spi->write((uint8_t)(addr >> 16));
DimiterK 0:b71060e03299 178 spi->write((uint8_t)(addr >> 8));
DimiterK 0:b71060e03299 179 spi->write((uint8_t)addr);
DimiterK 0:b71060e03299 180 for (uint16_t i=0; i<len; ++i)
DimiterK 0:b71060e03299 181 spi->write(write_buffer[i]);
DimiterK 0:b71060e03299 182 cs->write(1);
DimiterK 0:b71060e03299 183 wait_while_busy();
DimiterK 0:b71060e03299 184
DimiterK 0:b71060e03299 185 return true;
DimiterK 0:b71060e03299 186 }
DimiterK 0:b71060e03299 187
DimiterK 0:b71060e03299 188 void W25Q64FV::sector_erase_4k(uint32_t addr)
DimiterK 0:b71060e03299 189 {
DimiterK 0:b71060e03299 190 cs->write(0);
DimiterK 0:b71060e03299 191 spi->write(CMD_ERASE_SECTOR);
DimiterK 0:b71060e03299 192 spi->write((uint8_t)(addr >> 16));
DimiterK 0:b71060e03299 193 spi->write((uint8_t)(addr >> 8));
DimiterK 0:b71060e03299 194 spi->write((uint8_t)addr);
DimiterK 0:b71060e03299 195 cs->write(1);
DimiterK 0:b71060e03299 196 wait_while_busy();
DimiterK 0:b71060e03299 197 }
DimiterK 0:b71060e03299 198
DimiterK 0:b71060e03299 199 void W25Q64FV::block_erase_32k(uint32_t addr)
DimiterK 0:b71060e03299 200 {
DimiterK 0:b71060e03299 201 cs->write(0);
DimiterK 0:b71060e03299 202 spi->write(CMD_ERASE_BLOCK32);
DimiterK 0:b71060e03299 203 spi->write((uint8_t)(addr >> 16));
DimiterK 0:b71060e03299 204 spi->write((uint8_t)(addr >> 8));
DimiterK 0:b71060e03299 205 spi->write((uint8_t)addr);
DimiterK 0:b71060e03299 206 cs->write(1);
DimiterK 0:b71060e03299 207 wait_while_busy();
DimiterK 0:b71060e03299 208 }
DimiterK 0:b71060e03299 209
DimiterK 0:b71060e03299 210 void W25Q64FV::block_erase_64k(uint32_t addr)
DimiterK 0:b71060e03299 211 {
DimiterK 0:b71060e03299 212 cs->write(0);
DimiterK 0:b71060e03299 213 spi->write(CMD_ERASE_BLOCK64);
DimiterK 0:b71060e03299 214 spi->write((uint8_t)(addr >> 16));
DimiterK 0:b71060e03299 215 spi->write((uint8_t)(addr >> 8));
DimiterK 0:b71060e03299 216 spi->write((uint8_t)addr);
DimiterK 0:b71060e03299 217 cs->write(1);
DimiterK 0:b71060e03299 218 wait_while_busy();
DimiterK 0:b71060e03299 219 }
DimiterK 0:b71060e03299 220
DimiterK 0:b71060e03299 221 void W25Q64FV::chip_erase()
DimiterK 0:b71060e03299 222 {
DimiterK 0:b71060e03299 223 cs->write(0);
DimiterK 0:b71060e03299 224 spi->write(CMD_ERASE_CHIP);
DimiterK 0:b71060e03299 225 cs->write(1);
DimiterK 0:b71060e03299 226 wait_while_busy();
DimiterK 0:b71060e03299 227 }
DimiterK 0:b71060e03299 228
DimiterK 0:b71060e03299 229
DimiterK 0:b71060e03299 230
DimiterK 0:b71060e03299 231
DimiterK 0:b71060e03299 232
DimiterK 0:b71060e03299 233
DimiterK 0:b71060e03299 234 void W25Q64FV::writeArray(uint32_t address, uint8_t* pData, uint32_t arrayLength)
DimiterK 0:b71060e03299 235 {
DimiterK 0:b71060e03299 236 unsigned int i = 0;
DimiterK 0:b71060e03299 237 cs->write(0); //Enable device
DimiterK 0:b71060e03299 238 spi->write(CMD_WREN); //Send WREN command
DimiterK 0:b71060e03299 239 cs->write(1); //Disable device
DimiterK 0:b71060e03299 240
DimiterK 0:b71060e03299 241 cs->write(0); //Enable device
DimiterK 0:b71060e03299 242 spi->write(CMD_PAGEPROG); //Send Byte Program command
DimiterK 0:b71060e03299 243 spi->write((uint8_t)(address >> 16) & 0xFF);
DimiterK 0:b71060e03299 244 spi->write((uint8_t)(address >> 8) & 0xFF);
DimiterK 0:b71060e03299 245 spi->write(0x00);
DimiterK 0:b71060e03299 246
DimiterK 0:b71060e03299 247 for (i=0;i<arrayLength;i++)
DimiterK 0:b71060e03299 248 {
DimiterK 0:b71060e03299 249 spi->write(pData[i]); //Send byte to be programmed
DimiterK 0:b71060e03299 250 }
DimiterK 0:b71060e03299 251 cs->write(1); //Disable device
DimiterK 0:b71060e03299 252
DimiterK 0:b71060e03299 253 //Wait Busy
DimiterK 0:b71060e03299 254 while ((readStatus() & 0x01) == 0x01) //Waste time until not busy
DimiterK 0:b71060e03299 255 {
DimiterK 0:b71060e03299 256 }
DimiterK 0:b71060e03299 257 }
DimiterK 0:b71060e03299 258
DimiterK 0:b71060e03299 259
DimiterK 0:b71060e03299 260 void W25Q64FV::readArray(uint32_t address, uint8_t* pData, uint32_t arrayLength)
DimiterK 0:b71060e03299 261 {
DimiterK 0:b71060e03299 262 unsigned int i = 0;
DimiterK 0:b71060e03299 263
DimiterK 0:b71060e03299 264 cs->write(0); //Enable device
DimiterK 0:b71060e03299 265 spi->write(CMD_READ_DATA); //Read command
DimiterK 0:b71060e03299 266 spi->write((uint8_t)(address >> 16));
DimiterK 0:b71060e03299 267 spi->write((uint8_t)(address >> 8));
DimiterK 0:b71060e03299 268 spi->write((uint8_t) address);
DimiterK 0:b71060e03299 269
DimiterK 0:b71060e03299 270 for (i = 0; i <arrayLength; i++) //Read until no_bytes is reached
DimiterK 0:b71060e03299 271 {
DimiterK 0:b71060e03299 272 pData[i] = spi->write(DUMMY); //Receive bytes
DimiterK 0:b71060e03299 273 }
DimiterK 0:b71060e03299 274 cs->write(1); //Disable device
DimiterK 0:b71060e03299 275
DimiterK 0:b71060e03299 276 //Wait Busy
DimiterK 0:b71060e03299 277 while (readStatus() & 0x01) //Waste time until not busy
DimiterK 0:b71060e03299 278 {
DimiterK 0:b71060e03299 279 }
DimiterK 0:b71060e03299 280 }
DimiterK 0:b71060e03299 281
DimiterK 0:b71060e03299 282
DimiterK 0:b71060e03299 283