SPI driver for M25P* flash devices.

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

Committer:
Mike Fiore
Date:
Thu Dec 11 14:37:34 2014 -0600
Revision:
1:17246d2dfff3
Parent:
0:137807d94795
Child:
3:b173ba8ad165
add optional pins for W and HOLD

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
Mike Fiore 1:17246d2dfff3 25 SpiFlash25::SpiFlash25(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName W, PinName HOLD, int page_size)
mfiore 0:137807d94795 26 : _spi(mosi, miso, sclk),
mfiore 0:137807d94795 27 _cs(cs),
Mike Fiore 1:17246d2dfff3 28 _w(W),
Mike Fiore 1:17246d2dfff3 29 _hold(HOLD),
mfiore 0:137807d94795 30 _page_size(page_size)
mfiore 0:137807d94795 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 1:17246d2dfff3 36 if (_w != NC)
Mike Fiore 1:17246d2dfff3 37 _w = 1;
Mike Fiore 1:17246d2dfff3 38 if (_hold != NC)
Mike Fiore 1:17246d2dfff3 39 _hold = 1;
Mike Fiore 1:17246d2dfff3 40
mfiore 0:137807d94795 41 _cs.write(0);
mfiore 0:137807d94795 42 _spi.write(READ_IDENTIFICATION);
mfiore 0:137807d94795 43 _id[ID_MANUFACTURER] = _spi.write(0x00);
mfiore 0:137807d94795 44 _id[ID_MEM_TYPE] = _spi.write(0x00);
mfiore 0:137807d94795 45 _id[ID_MEM_SIZE] = _spi.write(0x00);
mfiore 0:137807d94795 46 _cs.write(1);
mfiore 0:137807d94795 47
mfiore 0:137807d94795 48 _mem_size = 1 << _id[ID_MEM_SIZE];
mfiore 0:137807d94795 49 }
mfiore 0:137807d94795 50
mfiore 0:137807d94795 51 void SpiFlash25::format(int bits, int mode) {
mfiore 0:137807d94795 52 _spi.format(bits, mode);
mfiore 0:137807d94795 53 }
mfiore 0:137807d94795 54
mfiore 0:137807d94795 55 void SpiFlash25::frequency(int hz) {
mfiore 0:137807d94795 56 _spi.frequency(hz);
mfiore 0:137807d94795 57 }
mfiore 0:137807d94795 58
mfiore 0:137807d94795 59 bool SpiFlash25::read(int addr, int len, char* data) {
mfiore 0:137807d94795 60 if (addr + len > _mem_size) {
mfiore 0:137807d94795 61 return false;
mfiore 0:137807d94795 62 }
mfiore 0:137807d94795 63
mfiore 0:137807d94795 64 enable_write();
mfiore 0:137807d94795 65
mfiore 0:137807d94795 66 _cs.write(0);
mfiore 0:137807d94795 67 _spi.write(READ_DATA);
mfiore 0:137807d94795 68 _spi.write(high_byte(addr));
mfiore 0:137807d94795 69 _spi.write(mid_byte(addr));
mfiore 0:137807d94795 70 _spi.write(low_byte(addr));
mfiore 0:137807d94795 71
mfiore 0:137807d94795 72 for (int i = 0; i < len; i++) {
mfiore 0:137807d94795 73 data[i] = _spi.write(0x00);
mfiore 0:137807d94795 74 }
mfiore 0:137807d94795 75
mfiore 0:137807d94795 76 _cs.write(1);
mfiore 0:137807d94795 77
mfiore 0:137807d94795 78 return true;
mfiore 0:137807d94795 79 }
mfiore 0:137807d94795 80
mfiore 0:137807d94795 81 bool SpiFlash25::write(int addr, int len, const char* data) {
mfiore 0:137807d94795 82 if (addr + len > _mem_size) {
mfiore 0:137807d94795 83 return false;
mfiore 0:137807d94795 84 }
mfiore 0:137807d94795 85
mfiore 0:137807d94795 86 int written = 0;
mfiore 0:137807d94795 87 int write_size = 0;
mfiore 0:137807d94795 88
mfiore 0:137807d94795 89 while (written < len) {
mfiore 0:137807d94795 90 write_size = _page_size - ((addr + written) % _page_size);
mfiore 0:137807d94795 91 if (written + write_size > len) {
mfiore 0:137807d94795 92 write_size = len - written;
mfiore 0:137807d94795 93 }
mfiore 0:137807d94795 94
mfiore 0:137807d94795 95 if (! write_page(addr + written, write_size, data + written)) {
mfiore 0:137807d94795 96 return false;
mfiore 0:137807d94795 97 }
mfiore 0:137807d94795 98
mfiore 0:137807d94795 99 written += write_size;
mfiore 0:137807d94795 100 }
mfiore 0:137807d94795 101
mfiore 0:137807d94795 102 return true;
mfiore 0:137807d94795 103 }
mfiore 0:137807d94795 104
mfiore 0:137807d94795 105 char* SpiFlash25::read_id() {
mfiore 0:137807d94795 106 return _id;
mfiore 0:137807d94795 107 }
mfiore 0:137807d94795 108
mfiore 0:137807d94795 109 char SpiFlash25::read_status() {
mfiore 0:137807d94795 110 char status;
mfiore 0:137807d94795 111
mfiore 0:137807d94795 112 _cs.write(0);
mfiore 0:137807d94795 113 _spi.write(READ_STATUS);
mfiore 0:137807d94795 114 status = _spi.write(0x00);
mfiore 0:137807d94795 115 _cs.write(1);
mfiore 0:137807d94795 116
mfiore 0:137807d94795 117 return status;
mfiore 0:137807d94795 118 }
mfiore 0:137807d94795 119
mfiore 0:137807d94795 120 void SpiFlash25::clear_sector(int addr) {
mfiore 0:137807d94795 121 enable_write();
mfiore 0:137807d94795 122
mfiore 0:137807d94795 123 _cs.write(0);
mfiore 0:137807d94795 124 _spi.write(SECTOR_ERASE);
mfiore 0:137807d94795 125 _spi.write(high_byte(addr));
mfiore 0:137807d94795 126 _spi.write(mid_byte(addr));
mfiore 0:137807d94795 127 _spi.write(low_byte(addr));
mfiore 0:137807d94795 128 _cs.write(1);
mfiore 0:137807d94795 129
mfiore 0:137807d94795 130 wait_for_write();
mfiore 0:137807d94795 131 }
mfiore 0:137807d94795 132
mfiore 0:137807d94795 133 void SpiFlash25::clear_mem() {
mfiore 0:137807d94795 134 enable_write();
mfiore 0:137807d94795 135
mfiore 0:137807d94795 136 _cs.write(0);
mfiore 0:137807d94795 137 _spi.write(BULK_ERASE);
mfiore 0:137807d94795 138 _cs.write(1);
mfiore 0:137807d94795 139
mfiore 0:137807d94795 140 wait_for_write();
mfiore 0:137807d94795 141 }
mfiore 0:137807d94795 142
mfiore 0:137807d94795 143 bool SpiFlash25::write_page(int addr, int len, const char* data) {
mfiore 0:137807d94795 144 enable_write();
mfiore 0:137807d94795 145
mfiore 0:137807d94795 146 _cs.write(0);
mfiore 0:137807d94795 147 _spi.write(PAGE_PROGRAM);
mfiore 0:137807d94795 148 _spi.write(high_byte(addr));
mfiore 0:137807d94795 149 _spi.write(mid_byte(addr));
mfiore 0:137807d94795 150 _spi.write(low_byte(addr));
mfiore 0:137807d94795 151
mfiore 0:137807d94795 152 for (int i = 0; i < len; i++) {
mfiore 0:137807d94795 153 _spi.write(data[i]);
mfiore 0:137807d94795 154 }
mfiore 0:137807d94795 155
mfiore 0:137807d94795 156 _cs.write(1);
mfiore 0:137807d94795 157 wait_for_write();
mfiore 0:137807d94795 158
mfiore 0:137807d94795 159 return true;
mfiore 0:137807d94795 160 }
mfiore 0:137807d94795 161
mfiore 0:137807d94795 162 void SpiFlash25::enable_write() {
mfiore 0:137807d94795 163 _cs.write(0);
mfiore 0:137807d94795 164 _spi.write(WRITE_ENABLE);
mfiore 0:137807d94795 165 _cs.write(1);
mfiore 0:137807d94795 166 }
mfiore 0:137807d94795 167
mfiore 0:137807d94795 168 void SpiFlash25::wait_for_write() {
mfiore 0:137807d94795 169 while (read_status() & STATUS_WIP) {
mfiore 0:137807d94795 170 wait_us(10);
mfiore 0:137807d94795 171 }
Mike Fiore 1:17246d2dfff3 172 }