TEST
Dependencies: max32630fthr Adafruit_FeatherOLED USBDevice
Drivers/SPIBlockDevice/SPIFBlockDevice.cpp@4:291477e8690d, 2020-04-19 (annotated)
- Committer:
- wwwarunraj
- Date:
- Sun Apr 19 11:19:57 2020 +0000
- Revision:
- 4:291477e8690d
- Parent:
- 1:f60eafbf009a
19/04
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gmehmet | 1:f60eafbf009a | 1 | /* mbed Microcontroller Library |
gmehmet | 1:f60eafbf009a | 2 | * Copyright (c) 2016 ARM Limited |
gmehmet | 1:f60eafbf009a | 3 | * |
gmehmet | 1:f60eafbf009a | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
gmehmet | 1:f60eafbf009a | 5 | * you may not use this file except in compliance with the License. |
gmehmet | 1:f60eafbf009a | 6 | * You may obtain a copy of the License at |
gmehmet | 1:f60eafbf009a | 7 | * |
gmehmet | 1:f60eafbf009a | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
gmehmet | 1:f60eafbf009a | 9 | * |
gmehmet | 1:f60eafbf009a | 10 | * Unless required by applicable law or agreed to in writing, software |
gmehmet | 1:f60eafbf009a | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
gmehmet | 1:f60eafbf009a | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
gmehmet | 1:f60eafbf009a | 13 | * See the License for the specific language governing permissions and |
gmehmet | 1:f60eafbf009a | 14 | * limitations under the License. |
gmehmet | 1:f60eafbf009a | 15 | */ |
gmehmet | 1:f60eafbf009a | 16 | |
gmehmet | 1:f60eafbf009a | 17 | #include "SPIFBlockDevice.h" |
gmehmet | 1:f60eafbf009a | 18 | |
gmehmet | 1:f60eafbf009a | 19 | |
gmehmet | 1:f60eafbf009a | 20 | // Read/write/erase sizes |
gmehmet | 1:f60eafbf009a | 21 | #define SPIF_READ_SIZE 1 |
gmehmet | 1:f60eafbf009a | 22 | #define SPIF_PROG_SIZE 1 |
gmehmet | 1:f60eafbf009a | 23 | #define SPIF_SE_SIZE 4096 |
gmehmet | 1:f60eafbf009a | 24 | #define SPIF_TIMEOUT 10000 |
gmehmet | 1:f60eafbf009a | 25 | |
gmehmet | 1:f60eafbf009a | 26 | // Debug available |
gmehmet | 1:f60eafbf009a | 27 | #define SPIF_DEBUG 0 |
gmehmet | 1:f60eafbf009a | 28 | |
gmehmet | 1:f60eafbf009a | 29 | // MX25R Series Register Command Table. |
gmehmet | 1:f60eafbf009a | 30 | enum ops { |
gmehmet | 1:f60eafbf009a | 31 | SPIF_NOP = 0x00, // No operation |
gmehmet | 1:f60eafbf009a | 32 | SPIF_READ = 0x03, // Read data |
gmehmet | 1:f60eafbf009a | 33 | SPIF_PROG = 0x02, // Program data |
gmehmet | 1:f60eafbf009a | 34 | SPIF_SE = 0x20, // 4KB Sector Erase |
gmehmet | 1:f60eafbf009a | 35 | SPIF_CE = 0xc7, // Chip Erase |
gmehmet | 1:f60eafbf009a | 36 | SPIF_SFDP = 0x5a, // Read SFDP |
gmehmet | 1:f60eafbf009a | 37 | SPIF_WREN = 0x06, // Write Enable |
gmehmet | 1:f60eafbf009a | 38 | SPIF_WRDI = 0x04, // Write Disable |
gmehmet | 1:f60eafbf009a | 39 | SPIF_RDSR = 0x05, // Read Status Register |
gmehmet | 1:f60eafbf009a | 40 | SPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID |
gmehmet | 1:f60eafbf009a | 41 | }; |
gmehmet | 1:f60eafbf009a | 42 | |
gmehmet | 1:f60eafbf009a | 43 | // Status register from RDSR |
gmehmet | 1:f60eafbf009a | 44 | // [- stuff -| wel | wip ] |
gmehmet | 1:f60eafbf009a | 45 | // [- 6 -| 1 | 1 ] |
gmehmet | 1:f60eafbf009a | 46 | #define SPIF_WEL 0x2 |
gmehmet | 1:f60eafbf009a | 47 | #define SPIF_WIP 0x1 |
gmehmet | 1:f60eafbf009a | 48 | |
gmehmet | 1:f60eafbf009a | 49 | |
gmehmet | 1:f60eafbf009a | 50 | SPIFBlockDevice::SPIFBlockDevice( |
gmehmet | 1:f60eafbf009a | 51 | PinName mosi, PinName miso, PinName sclk, PinName cs, int freq) |
gmehmet | 1:f60eafbf009a | 52 | : _spi(mosi, miso, sclk), _cs(cs), _size(0) |
gmehmet | 1:f60eafbf009a | 53 | { |
gmehmet | 1:f60eafbf009a | 54 | _cs = 1; |
gmehmet | 1:f60eafbf009a | 55 | _spi.frequency(freq); |
gmehmet | 1:f60eafbf009a | 56 | } |
gmehmet | 1:f60eafbf009a | 57 | |
gmehmet | 1:f60eafbf009a | 58 | int SPIFBlockDevice::init() |
gmehmet | 1:f60eafbf009a | 59 | { |
gmehmet | 1:f60eafbf009a | 60 | // Check for vendor specific hacks, these should move into more general |
gmehmet | 1:f60eafbf009a | 61 | // handling when possible. RDID is not used to verify a device is attached. |
gmehmet | 1:f60eafbf009a | 62 | uint8_t id[3]; |
gmehmet | 1:f60eafbf009a | 63 | _cmdread(SPIF_RDID, 0, 3, 0x0, id); |
gmehmet | 1:f60eafbf009a | 64 | |
gmehmet | 1:f60eafbf009a | 65 | switch (id[0]) { |
gmehmet | 1:f60eafbf009a | 66 | case 0xbf: |
gmehmet | 1:f60eafbf009a | 67 | // SST devices come preset with block protection |
gmehmet | 1:f60eafbf009a | 68 | // enabled for some regions, issue gbpu instruction to clear |
gmehmet | 1:f60eafbf009a | 69 | _wren(); |
gmehmet | 1:f60eafbf009a | 70 | _cmdwrite(0x98, 0, 0, 0x0, NULL); |
gmehmet | 1:f60eafbf009a | 71 | break; |
gmehmet | 1:f60eafbf009a | 72 | } |
gmehmet | 1:f60eafbf009a | 73 | |
gmehmet | 1:f60eafbf009a | 74 | // Check that device is doing ok |
gmehmet | 1:f60eafbf009a | 75 | int err = _sync(); |
gmehmet | 1:f60eafbf009a | 76 | if (err) { |
gmehmet | 1:f60eafbf009a | 77 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 78 | } |
gmehmet | 1:f60eafbf009a | 79 | |
gmehmet | 1:f60eafbf009a | 80 | // Check JEDEC serial flash discoverable parameters for device |
gmehmet | 1:f60eafbf009a | 81 | // specific info |
gmehmet | 1:f60eafbf009a | 82 | uint8_t header[16]; |
gmehmet | 1:f60eafbf009a | 83 | _cmdread(SPIF_SFDP, 4, 16, 0x0, header); |
gmehmet | 1:f60eafbf009a | 84 | |
gmehmet | 1:f60eafbf009a | 85 | // Verify SFDP signature for sanity |
gmehmet | 1:f60eafbf009a | 86 | // Also check that major/minor version is acceptable |
gmehmet | 1:f60eafbf009a | 87 | if (!(memcmp(&header[0], "SFDP", 4) == 0 && header[5] == 1)) { |
gmehmet | 1:f60eafbf009a | 88 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 89 | } |
gmehmet | 1:f60eafbf009a | 90 | |
gmehmet | 1:f60eafbf009a | 91 | // The SFDP spec indicates the standard table is always at offset 0 |
gmehmet | 1:f60eafbf009a | 92 | // in the parameter headers, we check just to be safe |
gmehmet | 1:f60eafbf009a | 93 | if (!(header[8] == 0 && header[10] == 1)) { |
gmehmet | 1:f60eafbf009a | 94 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 95 | } |
gmehmet | 1:f60eafbf009a | 96 | |
gmehmet | 1:f60eafbf009a | 97 | // Parameter table pointer, spi commands are BE, SFDP is LE, |
gmehmet | 1:f60eafbf009a | 98 | // also sfdp command expects extra read wait byte |
gmehmet | 1:f60eafbf009a | 99 | uint32_t table_addr = ( |
gmehmet | 1:f60eafbf009a | 100 | (header[14] << 24) | |
gmehmet | 1:f60eafbf009a | 101 | (header[13] << 16) | |
gmehmet | 1:f60eafbf009a | 102 | (header[12] << 8 )); |
gmehmet | 1:f60eafbf009a | 103 | uint8_t table[8]; |
gmehmet | 1:f60eafbf009a | 104 | _cmdread(SPIF_SFDP, 4, 8, table_addr, table); |
gmehmet | 1:f60eafbf009a | 105 | |
gmehmet | 1:f60eafbf009a | 106 | // Check erase size, currently only supports 4kbytes |
gmehmet | 1:f60eafbf009a | 107 | // TODO support erase size != 4kbytes? |
gmehmet | 1:f60eafbf009a | 108 | // TODO support other erase opcodes from the sector descriptions |
gmehmet | 1:f60eafbf009a | 109 | if ((table[0] & 0x3) != 0x1 || table[1] != SPIF_SE) { |
gmehmet | 1:f60eafbf009a | 110 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 111 | } |
gmehmet | 1:f60eafbf009a | 112 | |
gmehmet | 1:f60eafbf009a | 113 | // Check address size, currently only supports 3byte addresses |
gmehmet | 1:f60eafbf009a | 114 | // TODO support address > 3bytes? |
gmehmet | 1:f60eafbf009a | 115 | // TODO check for devices larger than 2Gbits? |
gmehmet | 1:f60eafbf009a | 116 | if ((table[2] & 0x4) != 0 || (table[7] & 0x80) != 0) { |
gmehmet | 1:f60eafbf009a | 117 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 118 | } |
gmehmet | 1:f60eafbf009a | 119 | |
gmehmet | 1:f60eafbf009a | 120 | // Get device density, stored as size in bits - 1 |
gmehmet | 1:f60eafbf009a | 121 | uint32_t density = ( |
gmehmet | 1:f60eafbf009a | 122 | (table[7] << 24) | |
gmehmet | 1:f60eafbf009a | 123 | (table[6] << 16) | |
gmehmet | 1:f60eafbf009a | 124 | (table[5] << 8 ) | |
gmehmet | 1:f60eafbf009a | 125 | (table[4] << 0 )); |
gmehmet | 1:f60eafbf009a | 126 | _size = (density/8) + 1; |
gmehmet | 1:f60eafbf009a | 127 | |
gmehmet | 1:f60eafbf009a | 128 | return 0; |
gmehmet | 1:f60eafbf009a | 129 | } |
gmehmet | 1:f60eafbf009a | 130 | |
gmehmet | 1:f60eafbf009a | 131 | int SPIFBlockDevice::deinit() |
gmehmet | 1:f60eafbf009a | 132 | { |
gmehmet | 1:f60eafbf009a | 133 | // Latch write disable just to keep noise |
gmehmet | 1:f60eafbf009a | 134 | // from changing the device |
gmehmet | 1:f60eafbf009a | 135 | _cmdwrite(SPIF_WRDI, 0, 0, 0x0, NULL); |
gmehmet | 1:f60eafbf009a | 136 | |
gmehmet | 1:f60eafbf009a | 137 | return 0; |
gmehmet | 1:f60eafbf009a | 138 | } |
gmehmet | 1:f60eafbf009a | 139 | |
gmehmet | 1:f60eafbf009a | 140 | void SPIFBlockDevice::_cmdread( |
gmehmet | 1:f60eafbf009a | 141 | uint8_t op, uint32_t addrc, uint32_t retc, |
gmehmet | 1:f60eafbf009a | 142 | uint32_t addr, uint8_t *rets) |
gmehmet | 1:f60eafbf009a | 143 | { |
gmehmet | 1:f60eafbf009a | 144 | |
gmehmet | 1:f60eafbf009a | 145 | _cs = 0; |
gmehmet | 1:f60eafbf009a | 146 | _spi.write(op); |
gmehmet | 1:f60eafbf009a | 147 | |
gmehmet | 1:f60eafbf009a | 148 | for (uint32_t i = 0; i < addrc; i++) { |
gmehmet | 1:f60eafbf009a | 149 | _spi.write(0xff & (addr >> 8*(addrc-1 - i))); |
gmehmet | 1:f60eafbf009a | 150 | } |
gmehmet | 1:f60eafbf009a | 151 | |
gmehmet | 1:f60eafbf009a | 152 | for (uint32_t i = 0; i < retc; i++) { |
gmehmet | 1:f60eafbf009a | 153 | rets[i] = _spi.write(0); |
gmehmet | 1:f60eafbf009a | 154 | } |
gmehmet | 1:f60eafbf009a | 155 | _cs = 1; |
gmehmet | 1:f60eafbf009a | 156 | |
gmehmet | 1:f60eafbf009a | 157 | |
gmehmet | 1:f60eafbf009a | 158 | |
gmehmet | 1:f60eafbf009a | 159 | if (SPIF_DEBUG) { |
gmehmet | 1:f60eafbf009a | 160 | printf("spif <- %02x", op); |
gmehmet | 1:f60eafbf009a | 161 | for (uint32_t i = 0; i < addrc; i++) { |
gmehmet | 1:f60eafbf009a | 162 | if (i < addrc) { |
gmehmet | 1:f60eafbf009a | 163 | printf("%02lx", 0xff & (addr >> 8*(addrc-1 - i))); |
gmehmet | 1:f60eafbf009a | 164 | } else { |
gmehmet | 1:f60eafbf009a | 165 | printf(" "); |
gmehmet | 1:f60eafbf009a | 166 | } |
gmehmet | 1:f60eafbf009a | 167 | } |
gmehmet | 1:f60eafbf009a | 168 | printf(" "); |
gmehmet | 1:f60eafbf009a | 169 | for (uint32_t i = 0; i < 16 && i < retc; i++) { |
gmehmet | 1:f60eafbf009a | 170 | printf("%02x", rets[i]); |
gmehmet | 1:f60eafbf009a | 171 | } |
gmehmet | 1:f60eafbf009a | 172 | if (retc > 16) { |
gmehmet | 1:f60eafbf009a | 173 | printf("..."); |
gmehmet | 1:f60eafbf009a | 174 | } |
gmehmet | 1:f60eafbf009a | 175 | printf("\n"); |
gmehmet | 1:f60eafbf009a | 176 | } |
gmehmet | 1:f60eafbf009a | 177 | } |
gmehmet | 1:f60eafbf009a | 178 | |
gmehmet | 1:f60eafbf009a | 179 | void SPIFBlockDevice::_cmdwrite( |
gmehmet | 1:f60eafbf009a | 180 | uint8_t op, uint32_t addrc, uint32_t argc, |
gmehmet | 1:f60eafbf009a | 181 | uint32_t addr, const uint8_t *args) |
gmehmet | 1:f60eafbf009a | 182 | { |
gmehmet | 1:f60eafbf009a | 183 | _cs = 0; |
gmehmet | 1:f60eafbf009a | 184 | _spi.write(op); |
gmehmet | 1:f60eafbf009a | 185 | |
gmehmet | 1:f60eafbf009a | 186 | for (uint32_t i = 0; i < addrc; i++) { |
gmehmet | 1:f60eafbf009a | 187 | _spi.write(0xff & (addr >> 8*(addrc-1 - i))); |
gmehmet | 1:f60eafbf009a | 188 | } |
gmehmet | 1:f60eafbf009a | 189 | |
gmehmet | 1:f60eafbf009a | 190 | for (uint32_t i = 0; i < argc; i++) { |
gmehmet | 1:f60eafbf009a | 191 | _spi.write(args[i]); |
gmehmet | 1:f60eafbf009a | 192 | } |
gmehmet | 1:f60eafbf009a | 193 | _cs = 1; |
gmehmet | 1:f60eafbf009a | 194 | |
gmehmet | 1:f60eafbf009a | 195 | if (SPIF_DEBUG) { |
gmehmet | 1:f60eafbf009a | 196 | printf("spif -> %02x", op); |
gmehmet | 1:f60eafbf009a | 197 | for (uint32_t i = 0; i < addrc; i++) { |
gmehmet | 1:f60eafbf009a | 198 | if (i < addrc) { |
gmehmet | 1:f60eafbf009a | 199 | printf("%02lx", 0xff & (addr >> 8*(addrc-1 - i))); |
gmehmet | 1:f60eafbf009a | 200 | } else { |
gmehmet | 1:f60eafbf009a | 201 | printf(" "); |
gmehmet | 1:f60eafbf009a | 202 | } |
gmehmet | 1:f60eafbf009a | 203 | } |
gmehmet | 1:f60eafbf009a | 204 | printf(" "); |
gmehmet | 1:f60eafbf009a | 205 | for (uint32_t i = 0; i < 16 && i < argc; i++) { |
gmehmet | 1:f60eafbf009a | 206 | printf("%02x", args[i]); |
gmehmet | 1:f60eafbf009a | 207 | } |
gmehmet | 1:f60eafbf009a | 208 | if (argc > 16) { |
gmehmet | 1:f60eafbf009a | 209 | printf("..."); |
gmehmet | 1:f60eafbf009a | 210 | } |
gmehmet | 1:f60eafbf009a | 211 | printf("\n"); |
gmehmet | 1:f60eafbf009a | 212 | } |
gmehmet | 1:f60eafbf009a | 213 | } |
gmehmet | 1:f60eafbf009a | 214 | |
gmehmet | 1:f60eafbf009a | 215 | int SPIFBlockDevice::_sync() |
gmehmet | 1:f60eafbf009a | 216 | { |
gmehmet | 1:f60eafbf009a | 217 | for (int i = 0; i < SPIF_TIMEOUT; i++) { |
gmehmet | 1:f60eafbf009a | 218 | // Read status register until write not-in-progress |
gmehmet | 1:f60eafbf009a | 219 | uint8_t status; |
gmehmet | 1:f60eafbf009a | 220 | _cmdread(SPIF_RDSR, 0, 1, 0x0, &status); |
gmehmet | 1:f60eafbf009a | 221 | |
gmehmet | 1:f60eafbf009a | 222 | // Check WIP bit |
gmehmet | 1:f60eafbf009a | 223 | if (!(status & SPIF_WIP)) { |
gmehmet | 1:f60eafbf009a | 224 | return 0; |
gmehmet | 1:f60eafbf009a | 225 | } |
gmehmet | 1:f60eafbf009a | 226 | |
gmehmet | 1:f60eafbf009a | 227 | wait_ms(1); |
gmehmet | 1:f60eafbf009a | 228 | } |
gmehmet | 1:f60eafbf009a | 229 | |
gmehmet | 1:f60eafbf009a | 230 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 231 | } |
gmehmet | 1:f60eafbf009a | 232 | |
gmehmet | 1:f60eafbf009a | 233 | int SPIFBlockDevice::_wren() |
gmehmet | 1:f60eafbf009a | 234 | { |
gmehmet | 1:f60eafbf009a | 235 | _cmdwrite(SPIF_WREN, 0, 0, 0x0, NULL); |
gmehmet | 1:f60eafbf009a | 236 | |
gmehmet | 1:f60eafbf009a | 237 | for (int i = 0; i < SPIF_TIMEOUT; i++) { |
gmehmet | 1:f60eafbf009a | 238 | // Read status register until write latch is enabled |
gmehmet | 1:f60eafbf009a | 239 | uint8_t status; |
gmehmet | 1:f60eafbf009a | 240 | _cmdread(SPIF_RDSR, 0, 1, 0x0, &status); |
gmehmet | 1:f60eafbf009a | 241 | |
gmehmet | 1:f60eafbf009a | 242 | // Check WEL bit |
gmehmet | 1:f60eafbf009a | 243 | if (status & SPIF_WEL) { |
gmehmet | 1:f60eafbf009a | 244 | return 0; |
gmehmet | 1:f60eafbf009a | 245 | } |
gmehmet | 1:f60eafbf009a | 246 | |
gmehmet | 1:f60eafbf009a | 247 | wait_ms(1); |
gmehmet | 1:f60eafbf009a | 248 | } |
gmehmet | 1:f60eafbf009a | 249 | |
gmehmet | 1:f60eafbf009a | 250 | return BD_ERROR_DEVICE_ERROR; |
gmehmet | 1:f60eafbf009a | 251 | } |
gmehmet | 1:f60eafbf009a | 252 | |
gmehmet | 1:f60eafbf009a | 253 | int SPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) |
gmehmet | 1:f60eafbf009a | 254 | { |
gmehmet | 1:f60eafbf009a | 255 | // Check the address and size fit onto the chip. |
gmehmet | 1:f60eafbf009a | 256 | MBED_ASSERT(is_valid_read(addr, size)); |
gmehmet | 1:f60eafbf009a | 257 | |
gmehmet | 1:f60eafbf009a | 258 | _cmdread(SPIF_READ, 3, size, addr, static_cast<uint8_t *>(buffer)); |
gmehmet | 1:f60eafbf009a | 259 | return 0; |
gmehmet | 1:f60eafbf009a | 260 | } |
gmehmet | 1:f60eafbf009a | 261 | |
gmehmet | 1:f60eafbf009a | 262 | int SPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) |
gmehmet | 1:f60eafbf009a | 263 | { |
gmehmet | 1:f60eafbf009a | 264 | // Check the address and size fit onto the chip. |
gmehmet | 1:f60eafbf009a | 265 | MBED_ASSERT(is_valid_program(addr, size)); |
gmehmet | 1:f60eafbf009a | 266 | |
gmehmet | 1:f60eafbf009a | 267 | while (size > 0) { |
gmehmet | 1:f60eafbf009a | 268 | int err = _wren(); |
gmehmet | 1:f60eafbf009a | 269 | if (err) { |
gmehmet | 1:f60eafbf009a | 270 | return err; |
gmehmet | 1:f60eafbf009a | 271 | } |
gmehmet | 1:f60eafbf009a | 272 | |
gmehmet | 1:f60eafbf009a | 273 | // Write up to 256 bytes a page |
gmehmet | 1:f60eafbf009a | 274 | // TODO handle unaligned programs |
gmehmet | 1:f60eafbf009a | 275 | uint32_t off = addr % 256; |
gmehmet | 1:f60eafbf009a | 276 | uint32_t chunk = (off + size < 256) ? size : (256-off); |
gmehmet | 1:f60eafbf009a | 277 | _cmdwrite(SPIF_PROG, 3, chunk, addr, static_cast<const uint8_t *>(buffer)); |
gmehmet | 1:f60eafbf009a | 278 | buffer = static_cast<const uint8_t*>(buffer) + chunk; |
gmehmet | 1:f60eafbf009a | 279 | addr += chunk; |
gmehmet | 1:f60eafbf009a | 280 | size -= chunk; |
gmehmet | 1:f60eafbf009a | 281 | |
gmehmet | 1:f60eafbf009a | 282 | wait_ms(1); |
gmehmet | 1:f60eafbf009a | 283 | |
gmehmet | 1:f60eafbf009a | 284 | err = _sync(); |
gmehmet | 1:f60eafbf009a | 285 | if (err) { |
gmehmet | 1:f60eafbf009a | 286 | return err; |
gmehmet | 1:f60eafbf009a | 287 | } |
gmehmet | 1:f60eafbf009a | 288 | } |
gmehmet | 1:f60eafbf009a | 289 | |
gmehmet | 1:f60eafbf009a | 290 | return 0; |
gmehmet | 1:f60eafbf009a | 291 | } |
gmehmet | 1:f60eafbf009a | 292 | |
gmehmet | 1:f60eafbf009a | 293 | int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t size) |
gmehmet | 1:f60eafbf009a | 294 | { |
gmehmet | 1:f60eafbf009a | 295 | // Check the address and size fit onto the chip. |
gmehmet | 1:f60eafbf009a | 296 | MBED_ASSERT(is_valid_erase(addr, size)); |
gmehmet | 1:f60eafbf009a | 297 | |
gmehmet | 1:f60eafbf009a | 298 | while (size > 0) { |
gmehmet | 1:f60eafbf009a | 299 | int err = _wren(); |
gmehmet | 1:f60eafbf009a | 300 | if (err) { |
gmehmet | 1:f60eafbf009a | 301 | return err; |
gmehmet | 1:f60eafbf009a | 302 | } |
gmehmet | 1:f60eafbf009a | 303 | |
gmehmet | 1:f60eafbf009a | 304 | // Erase 4kbyte sectors |
gmehmet | 1:f60eafbf009a | 305 | // TODO support other erase sizes? |
gmehmet | 1:f60eafbf009a | 306 | uint32_t chunk = 4096; |
gmehmet | 1:f60eafbf009a | 307 | _cmdwrite(SPIF_SE, 3, 0, addr, NULL); |
gmehmet | 1:f60eafbf009a | 308 | addr += chunk; |
gmehmet | 1:f60eafbf009a | 309 | size -= chunk; |
gmehmet | 1:f60eafbf009a | 310 | |
gmehmet | 1:f60eafbf009a | 311 | err = _sync(); |
gmehmet | 1:f60eafbf009a | 312 | if (err) { |
gmehmet | 1:f60eafbf009a | 313 | return err; |
gmehmet | 1:f60eafbf009a | 314 | } |
gmehmet | 1:f60eafbf009a | 315 | } |
gmehmet | 1:f60eafbf009a | 316 | |
gmehmet | 1:f60eafbf009a | 317 | return 0; |
gmehmet | 1:f60eafbf009a | 318 | } |
gmehmet | 1:f60eafbf009a | 319 | |
gmehmet | 1:f60eafbf009a | 320 | bd_size_t SPIFBlockDevice::get_read_size() const |
gmehmet | 1:f60eafbf009a | 321 | { |
gmehmet | 1:f60eafbf009a | 322 | return SPIF_READ_SIZE; |
gmehmet | 1:f60eafbf009a | 323 | } |
gmehmet | 1:f60eafbf009a | 324 | |
gmehmet | 1:f60eafbf009a | 325 | bd_size_t SPIFBlockDevice::get_program_size() const |
gmehmet | 1:f60eafbf009a | 326 | { |
gmehmet | 1:f60eafbf009a | 327 | return SPIF_PROG_SIZE; |
gmehmet | 1:f60eafbf009a | 328 | } |
gmehmet | 1:f60eafbf009a | 329 | |
gmehmet | 1:f60eafbf009a | 330 | bd_size_t SPIFBlockDevice::get_erase_size() const |
gmehmet | 1:f60eafbf009a | 331 | { |
gmehmet | 1:f60eafbf009a | 332 | return SPIF_SE_SIZE; |
gmehmet | 1:f60eafbf009a | 333 | } |
gmehmet | 1:f60eafbf009a | 334 | |
gmehmet | 1:f60eafbf009a | 335 | bd_size_t SPIFBlockDevice::size() const |
gmehmet | 1:f60eafbf009a | 336 | { |
gmehmet | 1:f60eafbf009a | 337 | return _size; |
gmehmet | 1:f60eafbf009a | 338 | } |