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