SPI driver for M25P* flash devices.

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

Committer:
mfiore
Date:
Thu Dec 04 14:09:10 2014 +0000
Revision:
0:137807d94795
Child:
1:17246d2dfff3
SpiFlash25: initial commit

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