initial

Dependencies:   mbed

Committer:
yihui
Date:
Mon Jan 11 02:32:24 2016 +0000
Revision:
0:638edba3adf6
initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:638edba3adf6 1 // W25Q16BV.cpp
yihui 0:638edba3adf6 2
yihui 0:638edba3adf6 3 #include"W25Q16BV.h"
yihui 0:638edba3adf6 4
yihui 0:638edba3adf6 5 // CONSTRUCTOR
yihui 0:638edba3adf6 6 W25Q16BV::W25Q16BV(PinName mosi, PinName miso, PinName sclk, PinName cs) : _spi(mosi, miso, sclk), _cs(cs) {
yihui 0:638edba3adf6 7 _spi.format(SPI_NBIT, SPI_MODE);
yihui 0:638edba3adf6 8 _spi.frequency(SPI_FREQ);
yihui 0:638edba3adf6 9 chipDisable();
yihui 0:638edba3adf6 10
yihui 0:638edba3adf6 11 exitDeepPowerDown();
yihui 0:638edba3adf6 12 // The SPI Flash cannot safely be accessed the first 1-10 ms after power ON
yihui 0:638edba3adf6 13 // wait_us(WAIT_US_TPUW);
yihui 0:638edba3adf6 14 }
yihui 0:638edba3adf6 15
yihui 0:638edba3adf6 16
yihui 0:638edba3adf6 17 // READING
yihui 0:638edba3adf6 18 int W25Q16BV::readByte(int addr) {
yihui 0:638edba3adf6 19 chipEnable();
yihui 0:638edba3adf6 20 _spi.write(R_INST);
yihui 0:638edba3adf6 21 _spi.write((addr >> 16) & 0xff);
yihui 0:638edba3adf6 22 _spi.write((addr >> 8) & 0xff);
yihui 0:638edba3adf6 23 _spi.write((addr ) & 0xff);
yihui 0:638edba3adf6 24 int response = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 25 chipDisable();
yihui 0:638edba3adf6 26 return response;
yihui 0:638edba3adf6 27 }
yihui 0:638edba3adf6 28 int W25Q16BV::readByte(int a2, int a1, int a0) {
yihui 0:638edba3adf6 29 chipEnable();
yihui 0:638edba3adf6 30 _spi.write(R_INST);
yihui 0:638edba3adf6 31 _spi.write(a2);
yihui 0:638edba3adf6 32 _spi.write(a1);
yihui 0:638edba3adf6 33 _spi.write(a0);
yihui 0:638edba3adf6 34 int response = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 35 chipDisable();
yihui 0:638edba3adf6 36 return response;
yihui 0:638edba3adf6 37 }
yihui 0:638edba3adf6 38 void W25Q16BV::readStream(int addr, char* buf, int count) {
yihui 0:638edba3adf6 39 if (count < 1)
yihui 0:638edba3adf6 40 return;
yihui 0:638edba3adf6 41 chipEnable();
yihui 0:638edba3adf6 42 _spi.write(R_INST);
yihui 0:638edba3adf6 43 _spi.write((addr >> 16) & 0xff);
yihui 0:638edba3adf6 44 _spi.write((addr >> 8) & 0xff);
yihui 0:638edba3adf6 45 _spi.write((addr ) & 0xff);
yihui 0:638edba3adf6 46 for (int i = 0; i < count; i++)
yihui 0:638edba3adf6 47 buf[i] = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 48 chipDisable();
yihui 0:638edba3adf6 49 }
yihui 0:638edba3adf6 50 void W25Q16BV::readJEDEC(uint8_t* manId, uint8_t* memType, uint8_t* cap)
yihui 0:638edba3adf6 51 {
yihui 0:638edba3adf6 52 chipEnable();
yihui 0:638edba3adf6 53 _spi.write(JDEC_INST);
yihui 0:638edba3adf6 54 *manId = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 55 *memType = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 56 *cap = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 57 chipDisable();
yihui 0:638edba3adf6 58 }
yihui 0:638edba3adf6 59 uint8_t W25Q16BV::readStatus1()
yihui 0:638edba3adf6 60 {
yihui 0:638edba3adf6 61 uint8_t status;
yihui 0:638edba3adf6 62 chipEnable();
yihui 0:638edba3adf6 63 _spi.write(STATUS1_INST);
yihui 0:638edba3adf6 64 status = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 65 chipDisable();
yihui 0:638edba3adf6 66 return status;
yihui 0:638edba3adf6 67 }
yihui 0:638edba3adf6 68 uint8_t W25Q16BV::readStatus2()
yihui 0:638edba3adf6 69 {
yihui 0:638edba3adf6 70 uint8_t status;
yihui 0:638edba3adf6 71 chipEnable();
yihui 0:638edba3adf6 72 _spi.write(STATUS2_INST);
yihui 0:638edba3adf6 73 status = _spi.write(DUMMY_ADDR);
yihui 0:638edba3adf6 74 chipDisable();
yihui 0:638edba3adf6 75 return status;
yihui 0:638edba3adf6 76 }
yihui 0:638edba3adf6 77
yihui 0:638edba3adf6 78 // WRITING
yihui 0:638edba3adf6 79 void W25Q16BV::writeByte(int addr, int data) {
yihui 0:638edba3adf6 80 writeEnable();
yihui 0:638edba3adf6 81 chipEnable();
yihui 0:638edba3adf6 82 _spi.write(W_INST);
yihui 0:638edba3adf6 83 _spi.write((addr >> 16) & 0xff);
yihui 0:638edba3adf6 84 _spi.write((addr >> 8) & 0xff);
yihui 0:638edba3adf6 85 _spi.write((addr ) & 0xff);
yihui 0:638edba3adf6 86 _spi.write(data);
yihui 0:638edba3adf6 87 chipDisable();
yihui 0:638edba3adf6 88 writeDisable();
yihui 0:638edba3adf6 89 // wait_us(WAIT_US_TBP);
yihui 0:638edba3adf6 90 waitWhileBusy();
yihui 0:638edba3adf6 91 }
yihui 0:638edba3adf6 92 void W25Q16BV::writeByte(int a2, int a1, int a0, int data) {
yihui 0:638edba3adf6 93 writeEnable();
yihui 0:638edba3adf6 94 chipEnable();
yihui 0:638edba3adf6 95 _spi.write(W_INST);
yihui 0:638edba3adf6 96 _spi.write(a2);
yihui 0:638edba3adf6 97 _spi.write(a1);
yihui 0:638edba3adf6 98 _spi.write(a0);
yihui 0:638edba3adf6 99 _spi.write(data);
yihui 0:638edba3adf6 100 chipDisable();
yihui 0:638edba3adf6 101 writeDisable();
yihui 0:638edba3adf6 102 // wait_us(WAIT_US_TBP);
yihui 0:638edba3adf6 103 waitWhileBusy();
yihui 0:638edba3adf6 104 }
yihui 0:638edba3adf6 105 #if 0
yihui 0:638edba3adf6 106 void W25Q16BV::writeStream(int addr, char* buf, int count) {
yihui 0:638edba3adf6 107 if (count < 1)
yihui 0:638edba3adf6 108 return;
yihui 0:638edba3adf6 109 writeEnable();
yihui 0:638edba3adf6 110 chipEnable();
yihui 0:638edba3adf6 111 _spi.write(W_INST);
yihui 0:638edba3adf6 112 _spi.write((addr & ADDR_BMASK2) >> ADDR_BSHIFT2);
yihui 0:638edba3adf6 113 _spi.write((addr & ADDR_BMASK1) >> ADDR_BSHIFT1);
yihui 0:638edba3adf6 114 _spi.write((addr & ADDR_BMASK0) >> ADDR_BSHIFT0);
yihui 0:638edba3adf6 115 for (int i = 0; i < count; i++)
yihui 0:638edba3adf6 116 _spi.write(buf[i]);
yihui 0:638edba3adf6 117 chipDisable();
yihui 0:638edba3adf6 118 writeDisable();
yihui 0:638edba3adf6 119 wait(WAIT_TIME_MS);
yihui 0:638edba3adf6 120 }
yihui 0:638edba3adf6 121 #else
yihui 0:638edba3adf6 122 void W25Q16BV::writeStream(int addr, char* buf, int count)
yihui 0:638edba3adf6 123 {
yihui 0:638edba3adf6 124 int left = count;
yihui 0:638edba3adf6 125 int offset = 0;
yihui 0:638edba3adf6 126 int len = 0;
yihui 0:638edba3adf6 127
yihui 0:638edba3adf6 128 if (count < 1) {
yihui 0:638edba3adf6 129 return;
yihui 0:638edba3adf6 130 }
yihui 0:638edba3adf6 131
yihui 0:638edba3adf6 132 // find length of first page write
yihui 0:638edba3adf6 133 if ((addr / PAGE_SIZE) != ((addr + count) / PAGE_SIZE)) {
yihui 0:638edba3adf6 134 //spans across at least one boundary
yihui 0:638edba3adf6 135 len = PAGE_SIZE - (addr % PAGE_SIZE);
yihui 0:638edba3adf6 136 } else {
yihui 0:638edba3adf6 137 // ends inside same page => use normal length
yihui 0:638edba3adf6 138 len = count % PAGE_SIZE;
yihui 0:638edba3adf6 139 }
yihui 0:638edba3adf6 140
yihui 0:638edba3adf6 141 //break up large write operation into several page write operations
yihui 0:638edba3adf6 142 while (left > 0) {
yihui 0:638edba3adf6 143 writeEnable();
yihui 0:638edba3adf6 144 chipEnable();
yihui 0:638edba3adf6 145 _spi.write(W_INST);
yihui 0:638edba3adf6 146 _spi.write(((addr + offset) >> 16) & 0xff);
yihui 0:638edba3adf6 147 _spi.write(((addr + offset) >> 8) & 0xff);
yihui 0:638edba3adf6 148 _spi.write(((addr + offset) ) & 0xff);
yihui 0:638edba3adf6 149 for (int i = 0; i < len; i++) {
yihui 0:638edba3adf6 150 _spi.write(buf[offset + i]);
yihui 0:638edba3adf6 151 }
yihui 0:638edba3adf6 152 chipDisable();
yihui 0:638edba3adf6 153 //writeDisable();
yihui 0:638edba3adf6 154
yihui 0:638edba3adf6 155 offset += len;
yihui 0:638edba3adf6 156 left -= len;
yihui 0:638edba3adf6 157 len = (left < PAGE_SIZE) ? left : PAGE_SIZE;
yihui 0:638edba3adf6 158
yihui 0:638edba3adf6 159 //wait_us(WAIT_US_TPP);
yihui 0:638edba3adf6 160 waitWhileBusy();
yihui 0:638edba3adf6 161 }
yihui 0:638edba3adf6 162 }
yihui 0:638edba3adf6 163 #endif
yihui 0:638edba3adf6 164
yihui 0:638edba3adf6 165 //ERASING
yihui 0:638edba3adf6 166 void W25Q16BV::chipErase() {
yihui 0:638edba3adf6 167 writeEnable();
yihui 0:638edba3adf6 168 chipEnable();
yihui 0:638edba3adf6 169 _spi.write(C_ERASE_INST);
yihui 0:638edba3adf6 170 chipDisable();
yihui 0:638edba3adf6 171 // writeDisable();
yihui 0:638edba3adf6 172 // wait_us(WAIT_US_TCE);
yihui 0:638edba3adf6 173 waitWhileBusy();
yihui 0:638edba3adf6 174 }
yihui 0:638edba3adf6 175 bool W25Q16BV::blockErase(int startBlock, int num) {
yihui 0:638edba3adf6 176 if ((num < 1) || (startBlock < 0) || ((startBlock+num) > NUM_64KB_BLOCKS)) {
yihui 0:638edba3adf6 177 return false;
yihui 0:638edba3adf6 178 }
yihui 0:638edba3adf6 179 for (int i = 0; i < num; i++) {
yihui 0:638edba3adf6 180 writeEnable();
yihui 0:638edba3adf6 181 chipEnable();
yihui 0:638edba3adf6 182 _spi.write(B_ERASE_INST);
yihui 0:638edba3adf6 183 _spi.write(startBlock + i);
yihui 0:638edba3adf6 184 _spi.write(0);
yihui 0:638edba3adf6 185 _spi.write(0);
yihui 0:638edba3adf6 186 chipDisable();
yihui 0:638edba3adf6 187 // writeDisable();
yihui 0:638edba3adf6 188 // wait_us(WAIT_US_TBE);
yihui 0:638edba3adf6 189 waitWhileBusy();
yihui 0:638edba3adf6 190 }
yihui 0:638edba3adf6 191 return true;
yihui 0:638edba3adf6 192 }
yihui 0:638edba3adf6 193 bool W25Q16BV::sectorErase(int startSector, int num) {
yihui 0:638edba3adf6 194 if ((num < 1) || (startSector < 0) || ((startSector+num) > NUM_SECTORS)) {
yihui 0:638edba3adf6 195 return false;
yihui 0:638edba3adf6 196 }
yihui 0:638edba3adf6 197 int addr = startSector * SECTOR_SIZE;
yihui 0:638edba3adf6 198 for (int i = 0; i < num; i++) {
yihui 0:638edba3adf6 199 writeEnable();
yihui 0:638edba3adf6 200 chipEnable();
yihui 0:638edba3adf6 201 _spi.write(S_ERASE_INST);
yihui 0:638edba3adf6 202 _spi.write((addr >> 16) & 0xff);
yihui 0:638edba3adf6 203 _spi.write((addr >> 8) & 0xff);
yihui 0:638edba3adf6 204 _spi.write((addr ) & 0xff);
yihui 0:638edba3adf6 205 chipDisable();
yihui 0:638edba3adf6 206 // writeDisable();
yihui 0:638edba3adf6 207 // wait_us(WAIT_US_TSE);
yihui 0:638edba3adf6 208 waitWhileBusy();
yihui 0:638edba3adf6 209
yihui 0:638edba3adf6 210 addr += SECTOR_SIZE;
yihui 0:638edba3adf6 211 }
yihui 0:638edba3adf6 212 return true;
yihui 0:638edba3adf6 213 }
yihui 0:638edba3adf6 214
yihui 0:638edba3adf6 215 // deep power down (default state)
yihui 0:638edba3adf6 216 void W25Q16BV::enterDeepPowerDown() {
yihui 0:638edba3adf6 217 chipEnable();
yihui 0:638edba3adf6 218 _spi.write(POWERDOWN_INST);
yihui 0:638edba3adf6 219 chipDisable();
yihui 0:638edba3adf6 220 }
yihui 0:638edba3adf6 221
yihui 0:638edba3adf6 222 // Wakeup from deep power down (default state)
yihui 0:638edba3adf6 223 void W25Q16BV::exitDeepPowerDown() {
yihui 0:638edba3adf6 224 chipEnable();
yihui 0:638edba3adf6 225 _spi.write(POWERUP_INST);
yihui 0:638edba3adf6 226 chipDisable();
yihui 0:638edba3adf6 227 wait_us(WAIT_US_TRES1);
yihui 0:638edba3adf6 228 }
yihui 0:638edba3adf6 229
yihui 0:638edba3adf6 230 void W25Q16BV::waitWhileBusy() {
yihui 0:638edba3adf6 231 uint8_t status = 0;
yihui 0:638edba3adf6 232 int i = 0;
yihui 0:638edba3adf6 233
yihui 0:638edba3adf6 234 do {
yihui 0:638edba3adf6 235 for (i = 0; i < 0x2000; i++);
yihui 0:638edba3adf6 236
yihui 0:638edba3adf6 237 status = readStatus1();
yihui 0:638edba3adf6 238 }
yihui 0:638edba3adf6 239 while ((status & STATUS_1_BUSY) != 0);
yihui 0:638edba3adf6 240 }
yihui 0:638edba3adf6 241
yihui 0:638edba3adf6 242 //ENABLE/DISABLE (private functions)
yihui 0:638edba3adf6 243 void W25Q16BV::writeEnable() {
yihui 0:638edba3adf6 244 chipEnable();
yihui 0:638edba3adf6 245 _spi.write(WE_INST);
yihui 0:638edba3adf6 246 chipDisable();
yihui 0:638edba3adf6 247 }
yihui 0:638edba3adf6 248 void W25Q16BV::writeDisable() {
yihui 0:638edba3adf6 249 chipEnable();
yihui 0:638edba3adf6 250 _spi.write(WD_INST);
yihui 0:638edba3adf6 251 chipDisable();
yihui 0:638edba3adf6 252 }
yihui 0:638edba3adf6 253 void W25Q16BV::chipEnable() {
yihui 0:638edba3adf6 254 _cs = 0;
yihui 0:638edba3adf6 255 }
yihui 0:638edba3adf6 256 void W25Q16BV::chipDisable() {
yihui 0:638edba3adf6 257 _cs = 1;
yihui 0:638edba3adf6 258 }
yihui 0:638edba3adf6 259