SPI driver for M25P* flash devices.

Dependents:   flash-fs-example Dragonfly_Filesystem_Example Dragonfly_Low_Power_Example STM32F407VET6_SPIFlash ... more

Committer:
Leon Lindenfelser
Date:
Fri Jun 26 15:05:25 2020 -0500
Revision:
5:31c110c2536c
Parent:
4:751745dd637f
Update to latest from Multitech git repo

1. Add timeout when waiting for WIP
2. Check 'write in progress bit' after writing the status register
3. Add ability to write the status register
4. Read identification function actually reads identification
5. Hardcode memory size as parameter in constructor
6. Move wakeup() call after CS, WP, and HOLD setup so it wakes the flash if it was sleeping

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 0:137807d94795 1 /* Library for SPI flash 25* devices.
mfiore 0:137807d94795 2 * Copyright (c) 2014 Multi-Tech Systems
mfiore 0:137807d94795 3 *
mfiore 0:137807d94795 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
mfiore 0:137807d94795 5 * of this software and associated documentation files (the "Software"), to deal
mfiore 0:137807d94795 6 * in the Software without restriction, including without limitation the rights
mfiore 0:137807d94795 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
mfiore 0:137807d94795 8 * copies of the Software, and to permit persons to whom the Software is
mfiore 0:137807d94795 9 * furnished to do so, subject to the following conditions:
mfiore 0:137807d94795 10 *
mfiore 0:137807d94795 11 * The above copyright notice and this permission notice shall be included in
mfiore 0:137807d94795 12 * all copies or substantial portions of the Software.
mfiore 0:137807d94795 13 *
mfiore 0:137807d94795 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
mfiore 0:137807d94795 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
mfiore 0:137807d94795 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
mfiore 0:137807d94795 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
mfiore 0:137807d94795 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
mfiore 0:137807d94795 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
mfiore 0:137807d94795 20 * SOFTWARE.
mfiore 0:137807d94795 21 */
mfiore 0:137807d94795 22
mfiore 0:137807d94795 23 #include "SpiFlash25.h"
mfiore 0:137807d94795 24
Leon Lindenfelser 5:31c110c2536c 25 SpiFlash25::SpiFlash25(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName W, PinName HOLD, int page_size, int mem_size)
mfiore 0:137807d94795 26 : _spi(mosi, miso, sclk),
mfiore 0:137807d94795 27 _cs(cs),
Leon Lindenfelser 5:31c110c2536c 28 _mem_size(mem_size),
mfiore 0:137807d94795 29 _page_size(page_size)
mfiore 0:137807d94795 30 {
Mike Fiore 4:751745dd637f 31
mfiore 0:137807d94795 32 _cs.write(1);
mfiore 0:137807d94795 33 _spi.format(8, 3);
mfiore 0:137807d94795 34 _spi.frequency(75000000);
mfiore 0:137807d94795 35
Mike Fiore 3:b173ba8ad165 36 if (W != NC) {
Mike Fiore 3:b173ba8ad165 37 _w = new DigitalOut(W);
Mike Fiore 3:b173ba8ad165 38 _w->write(1);
Mike Fiore 3:b173ba8ad165 39 }
Mike Fiore 3:b173ba8ad165 40 if (HOLD != NC) {
Mike Fiore 3:b173ba8ad165 41 _hold = new DigitalOut(HOLD);
Mike Fiore 3:b173ba8ad165 42 _hold->write(1);
Mike Fiore 3:b173ba8ad165 43 }
Mike Fiore 1:17246d2dfff3 44
Leon Lindenfelser 5:31c110c2536c 45 wakeup();
mfiore 0:137807d94795 46 }
mfiore 0:137807d94795 47
mfiore 0:137807d94795 48 void SpiFlash25::format(int bits, int mode) {
mfiore 0:137807d94795 49 _spi.format(bits, mode);
mfiore 0:137807d94795 50 }
mfiore 0:137807d94795 51
mfiore 0:137807d94795 52 void SpiFlash25::frequency(int hz) {
mfiore 0:137807d94795 53 _spi.frequency(hz);
mfiore 0:137807d94795 54 }
mfiore 0:137807d94795 55
mfiore 0:137807d94795 56 bool SpiFlash25::read(int addr, int len, char* data) {
mfiore 0:137807d94795 57 if (addr + len > _mem_size) {
mfiore 0:137807d94795 58 return false;
mfiore 0:137807d94795 59 }
mfiore 0:137807d94795 60
mfiore 0:137807d94795 61 enable_write();
mfiore 0:137807d94795 62
mfiore 0:137807d94795 63 _cs.write(0);
mfiore 0:137807d94795 64 _spi.write(READ_DATA);
mfiore 0:137807d94795 65 _spi.write(high_byte(addr));
mfiore 0:137807d94795 66 _spi.write(mid_byte(addr));
mfiore 0:137807d94795 67 _spi.write(low_byte(addr));
mfiore 0:137807d94795 68
mfiore 0:137807d94795 69 for (int i = 0; i < len; i++) {
mfiore 0:137807d94795 70 data[i] = _spi.write(0x00);
mfiore 0:137807d94795 71 }
mfiore 0:137807d94795 72
mfiore 0:137807d94795 73 _cs.write(1);
mfiore 0:137807d94795 74
mfiore 0:137807d94795 75 return true;
mfiore 0:137807d94795 76 }
mfiore 0:137807d94795 77
mfiore 0:137807d94795 78 bool SpiFlash25::write(int addr, int len, const char* data) {
mfiore 0:137807d94795 79 if (addr + len > _mem_size) {
mfiore 0:137807d94795 80 return false;
mfiore 0:137807d94795 81 }
mfiore 0:137807d94795 82
mfiore 0:137807d94795 83 int written = 0;
mfiore 0:137807d94795 84 int write_size = 0;
mfiore 0:137807d94795 85
mfiore 0:137807d94795 86 while (written < len) {
mfiore 0:137807d94795 87 write_size = _page_size - ((addr + written) % _page_size);
mfiore 0:137807d94795 88 if (written + write_size > len) {
mfiore 0:137807d94795 89 write_size = len - written;
mfiore 0:137807d94795 90 }
mfiore 0:137807d94795 91
mfiore 0:137807d94795 92 if (! write_page(addr + written, write_size, data + written)) {
mfiore 0:137807d94795 93 return false;
mfiore 0:137807d94795 94 }
mfiore 0:137807d94795 95
mfiore 0:137807d94795 96 written += write_size;
mfiore 0:137807d94795 97 }
mfiore 0:137807d94795 98
mfiore 0:137807d94795 99 return true;
mfiore 0:137807d94795 100 }
mfiore 0:137807d94795 101
mfiore 0:137807d94795 102 char* SpiFlash25::read_id() {
Leon Lindenfelser 5:31c110c2536c 103 _cs.write(0);
Leon Lindenfelser 5:31c110c2536c 104 _spi.write(READ_IDENTIFICATION);
Leon Lindenfelser 5:31c110c2536c 105 _id[ID_MANUFACTURER] = _spi.write(0x00);
Leon Lindenfelser 5:31c110c2536c 106 _id[ID_MEM_TYPE] = _spi.write(0x00);
Leon Lindenfelser 5:31c110c2536c 107 _id[ID_MEM_SIZE] = _spi.write(0x00);
Leon Lindenfelser 5:31c110c2536c 108 _cs.write(1);
Leon Lindenfelser 5:31c110c2536c 109
mfiore 0:137807d94795 110 return _id;
mfiore 0:137807d94795 111 }
mfiore 0:137807d94795 112
Leon Lindenfelser 5:31c110c2536c 113 void SpiFlash25::write_status(char data) {
Leon Lindenfelser 5:31c110c2536c 114 enable_write();
Leon Lindenfelser 5:31c110c2536c 115 _cs.write(0);
Leon Lindenfelser 5:31c110c2536c 116 _spi.write(WRITE_STATUS);
Leon Lindenfelser 5:31c110c2536c 117 _spi.write(data);
Leon Lindenfelser 5:31c110c2536c 118 _cs.write(1);
Leon Lindenfelser 5:31c110c2536c 119 wait_for_write(15);
Leon Lindenfelser 5:31c110c2536c 120 }
Leon Lindenfelser 5:31c110c2536c 121
mfiore 0:137807d94795 122 char SpiFlash25::read_status() {
mfiore 0:137807d94795 123 char status;
mfiore 0:137807d94795 124
mfiore 0:137807d94795 125 _cs.write(0);
mfiore 0:137807d94795 126 _spi.write(READ_STATUS);
mfiore 0:137807d94795 127 status = _spi.write(0x00);
mfiore 0:137807d94795 128 _cs.write(1);
mfiore 0:137807d94795 129
mfiore 0:137807d94795 130 return status;
mfiore 0:137807d94795 131 }
mfiore 0:137807d94795 132
mfiore 0:137807d94795 133 void SpiFlash25::clear_sector(int addr) {
mfiore 0:137807d94795 134 enable_write();
mfiore 0:137807d94795 135
mfiore 0:137807d94795 136 _cs.write(0);
mfiore 0:137807d94795 137 _spi.write(SECTOR_ERASE);
mfiore 0:137807d94795 138 _spi.write(high_byte(addr));
mfiore 0:137807d94795 139 _spi.write(mid_byte(addr));
mfiore 0:137807d94795 140 _spi.write(low_byte(addr));
mfiore 0:137807d94795 141 _cs.write(1);
mfiore 0:137807d94795 142
Leon Lindenfelser 5:31c110c2536c 143 wait_for_write(3000);
mfiore 0:137807d94795 144 }
mfiore 0:137807d94795 145
mfiore 0:137807d94795 146 void SpiFlash25::clear_mem() {
mfiore 0:137807d94795 147 enable_write();
mfiore 0:137807d94795 148
mfiore 0:137807d94795 149 _cs.write(0);
mfiore 0:137807d94795 150 _spi.write(BULK_ERASE);
mfiore 0:137807d94795 151 _cs.write(1);
mfiore 0:137807d94795 152
Leon Lindenfelser 5:31c110c2536c 153 wait_for_write(20000);
mfiore 0:137807d94795 154 }
mfiore 0:137807d94795 155
mfiore 0:137807d94795 156 bool SpiFlash25::write_page(int addr, int len, const char* data) {
mfiore 0:137807d94795 157 enable_write();
mfiore 0:137807d94795 158
mfiore 0:137807d94795 159 _cs.write(0);
mfiore 0:137807d94795 160 _spi.write(PAGE_PROGRAM);
mfiore 0:137807d94795 161 _spi.write(high_byte(addr));
mfiore 0:137807d94795 162 _spi.write(mid_byte(addr));
mfiore 0:137807d94795 163 _spi.write(low_byte(addr));
mfiore 0:137807d94795 164
mfiore 0:137807d94795 165 for (int i = 0; i < len; i++) {
mfiore 0:137807d94795 166 _spi.write(data[i]);
mfiore 0:137807d94795 167 }
mfiore 0:137807d94795 168
mfiore 0:137807d94795 169 _cs.write(1);
mfiore 0:137807d94795 170
Leon Lindenfelser 5:31c110c2536c 171 return wait_for_write(5);
mfiore 0:137807d94795 172 }
mfiore 0:137807d94795 173
mfiore 0:137807d94795 174 void SpiFlash25::enable_write() {
mfiore 0:137807d94795 175 _cs.write(0);
mfiore 0:137807d94795 176 _spi.write(WRITE_ENABLE);
mfiore 0:137807d94795 177 _cs.write(1);
mfiore 0:137807d94795 178 }
mfiore 0:137807d94795 179
Leon Lindenfelser 5:31c110c2536c 180 bool SpiFlash25::wait_for_write(int32_t timeout_ms) {
Leon Lindenfelser 5:31c110c2536c 181 timeout_ms *= 100;
Leon Lindenfelser 5:31c110c2536c 182 while ((read_status() & STATUS_WIP) && (timeout_ms-- > 0)) {
mfiore 0:137807d94795 183 wait_us(10);
mfiore 0:137807d94795 184 }
Leon Lindenfelser 5:31c110c2536c 185 return timeout_ms > 0;
Mike Fiore 1:17246d2dfff3 186 }
Mike Fiore 4:751745dd637f 187
Mike Fiore 4:751745dd637f 188 void SpiFlash25::deep_power_down() {
Mike Fiore 4:751745dd637f 189 _cs.write(0);
Mike Fiore 4:751745dd637f 190 _spi.write(DEEP_POWER_DOWN);
Mike Fiore 4:751745dd637f 191 _cs.write(1);
Mike Fiore 4:751745dd637f 192 }
Mike Fiore 4:751745dd637f 193
Mike Fiore 4:751745dd637f 194 void SpiFlash25::wakeup() {
Mike Fiore 4:751745dd637f 195 _cs.write(0);
Mike Fiore 4:751745dd637f 196 _spi.write(DEEP_POWER_DOWN_RELEASE);
Mike Fiore 4:751745dd637f 197 _cs.write(1);
Mike Fiore 4:751745dd637f 198 }
Leon Lindenfelser 5:31c110c2536c 199