MultiTech / SpiFlash25

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SpiFlash25.cpp Source File

SpiFlash25.cpp

00001 /* Library for SPI flash 25* devices.
00002  * Copyright (c) 2014 Multi-Tech Systems
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00020  * SOFTWARE.
00021  */
00022 
00023 #include "SpiFlash25.h"
00024 
00025 SpiFlash25::SpiFlash25(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName W, PinName HOLD, int page_size, int mem_size)
00026 :   _spi(mosi, miso, sclk),
00027     _cs(cs),
00028     _mem_size(mem_size),
00029     _page_size(page_size)
00030 {
00031 
00032     _cs.write(1);
00033     _spi.format(8, 3);
00034     _spi.frequency(75000000);
00035 
00036     if (W != NC) {
00037         _w = new DigitalOut(W);
00038         _w->write(1);
00039     }
00040     if (HOLD != NC) {
00041         _hold = new DigitalOut(HOLD);
00042         _hold->write(1);
00043     }
00044 
00045     wakeup();
00046 }
00047 
00048 void SpiFlash25::format(int bits, int mode) {
00049     _spi.format(bits, mode);
00050 }
00051 
00052 void SpiFlash25::frequency(int hz) {
00053     _spi.frequency(hz);
00054 }
00055 
00056 bool SpiFlash25::read(int addr, int len, char* data) {
00057     if (addr + len > _mem_size) {
00058         return false;
00059     }
00060 
00061     enable_write();
00062 
00063     _cs.write(0);
00064     _spi.write(READ_DATA);
00065     _spi.write(high_byte(addr));
00066     _spi.write(mid_byte(addr));
00067     _spi.write(low_byte(addr));
00068 
00069     for (int i = 0; i < len; i++) {
00070         data[i] = _spi.write(0x00);
00071     }
00072 
00073     _cs.write(1);
00074 
00075     return true;
00076 }
00077 
00078 bool SpiFlash25::write(int addr, int len, const char* data) {
00079     if (addr + len > _mem_size) {
00080         return false;
00081     }
00082 
00083     int written = 0;
00084     int write_size = 0;
00085 
00086     while (written < len) {
00087         write_size = _page_size - ((addr + written) % _page_size);
00088         if (written + write_size > len) {
00089             write_size = len - written;
00090         }
00091 
00092         if (! write_page(addr + written, write_size, data + written)) {
00093             return false;
00094         }
00095 
00096         written += write_size;
00097     }
00098 
00099     return true;
00100 }
00101 
00102 char* SpiFlash25::read_id() {
00103     _cs.write(0);
00104     _spi.write(READ_IDENTIFICATION);
00105     _id[ID_MANUFACTURER] = _spi.write(0x00);
00106     _id[ID_MEM_TYPE] = _spi.write(0x00);
00107     _id[ID_MEM_SIZE] = _spi.write(0x00);
00108     _cs.write(1);
00109 
00110     return _id;
00111 }
00112 
00113 void SpiFlash25::write_status(char data) {
00114     enable_write(); 
00115     _cs.write(0);
00116     _spi.write(WRITE_STATUS);
00117     _spi.write(data);   
00118     _cs.write(1);
00119     wait_for_write(15);    
00120 }
00121 
00122 char SpiFlash25::read_status() {
00123     char status;
00124 
00125     _cs.write(0);
00126     _spi.write(READ_STATUS);
00127     status = _spi.write(0x00);
00128     _cs.write(1);
00129 
00130     return status;
00131 }
00132 
00133 void SpiFlash25::clear_sector(int addr) {
00134     enable_write();
00135 
00136     _cs.write(0);
00137     _spi.write(SECTOR_ERASE);
00138     _spi.write(high_byte(addr));
00139     _spi.write(mid_byte(addr));
00140     _spi.write(low_byte(addr));
00141     _cs.write(1);
00142 
00143     wait_for_write(3000);
00144 }
00145 
00146 void SpiFlash25::clear_mem() {
00147     enable_write();
00148 
00149     _cs.write(0);
00150     _spi.write(BULK_ERASE);
00151     _cs.write(1);
00152 
00153     wait_for_write(20000);
00154 }
00155 
00156 bool SpiFlash25::write_page(int addr, int len, const char* data) {
00157     enable_write();
00158 
00159     _cs.write(0);
00160     _spi.write(PAGE_PROGRAM);
00161     _spi.write(high_byte(addr));
00162     _spi.write(mid_byte(addr));
00163     _spi.write(low_byte(addr));
00164 
00165     for (int i = 0; i < len; i++) {
00166         _spi.write(data[i]);
00167     }
00168 
00169     _cs.write(1);
00170 
00171     return wait_for_write(5);
00172 }
00173 
00174 void SpiFlash25::enable_write() {
00175     _cs.write(0);
00176     _spi.write(WRITE_ENABLE);
00177     _cs.write(1);
00178 }
00179 
00180 bool SpiFlash25::wait_for_write(int32_t timeout_ms) {
00181     timeout_ms *= 100;
00182     while ((read_status() & STATUS_WIP) && (timeout_ms-- > 0)) {
00183         wait_us(10);
00184     }
00185     return timeout_ms > 0;
00186 }
00187 
00188 void SpiFlash25::deep_power_down() {
00189     _cs.write(0);
00190     _spi.write(DEEP_POWER_DOWN);
00191     _cs.write(1);
00192 }
00193 
00194 void SpiFlash25::wakeup() {
00195     _cs.write(0);
00196     _spi.write(DEEP_POWER_DOWN_RELEASE);
00197     _cs.write(1);
00198 }
00199