Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of flash25spi by
flash25spi.cpp
00001 /* This library is based on the Ser25lcxxx library by Hendrik Lipka 00002 * It was adapted to flash memory chips on 19.2.2011 by Klaus Steinhammer 00003 00004 * It was further adapted to M25P* SPI Flash memory chips that do not 00005 * support the "RDID" device ID instructions on 25.03.2014 by Richard Thompson 00006 * 00007 * The BSD license also applies to this code - have fun. 00008 */ 00009 00010 /* 00011 * Ser25lcxxx library 00012 * Copyright (c) 2010 Hendrik Lipka 00013 * 00014 * Permission is hereby granted, free of charge, to any person obtaining a copy 00015 * of this software and associated documentation files (the "Software"), to deal 00016 * in the Software without restriction, including without limitation the rights 00017 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00018 * copies of the Software, and to permit persons to whom the Software is 00019 * furnished to do so, subject to the following conditions: 00020 * 00021 * The above copyright notice and this permission notice shall be included in 00022 * all copies or substantial portions of the Software. 00023 * 00024 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00025 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00026 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00027 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00028 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00029 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00030 * THE SOFTWARE. 00031 */ 00032 00033 00034 #include "flash25spi.h" 00035 #include "wait_api.h" 00036 00037 //#define DEBUG 00038 00039 struct dataBase { 00040 uint8_t signature; 00041 size_t memsize; 00042 size_t sectorsize; 00043 size_t pagesize; 00044 }; 00045 00046 const struct dataBase devices[] = { 00047 //signature, memsize, sectorsize, pagesize 00048 { 0x10, 0x20000, 0x8000, 0x100 }, // M25P10-A Numonyx/ST 00049 { 0x11, 0x40000, 0x10000, 0x100 }, // M25P20 Numonyx/ST/Micron 00050 { 0x12, 0x80000, 0x10000, 0x100 }, // M25P40 Numonyx/ST 00051 { 0x00, 0x00, 0x00, 0x00}, // end of table 00052 }; 00053 00054 // Instruction Set 00055 const uint8_t FLASH_WREN = 0x06; // Write Enable 00056 //const uint8_t FLASH_WRDI = 0x04; // Write Disable (Unused) 00057 //const uint8_t FLASH_RDID = 0x9F; // Read Device IDentification (not supported) 00058 const uint8_t FLASH_RDSR = 0x05; // Read Status Register 00059 //const uint8_t FLASH_WRSR = 0x01; // Write Status Register (not used) 00060 const uint8_t FLASH_READ = 0x03; // Read Data Bytes 00061 //const uint8_t FLASH_FAST_READ = 0x0B; // Read Data Bytes Faster 00062 const uint8_t FLASH_PP = 0x02; // Page Program (max pagesize bytes) 00063 const uint8_t FLASH_SE = 0xD8; // Sector Erase 00064 const uint8_t FLASH_BE = 0xC7; // Bulk Erase (wipe complete system) 00065 const uint8_t FLASH_DP = 0xB9; // Deep Power Down (shutdown into very-low-power) 00066 const uint8_t FLASH_RES = 0xAB; // Wake Up and Read Electronic Signature 00067 00068 #define HIGH(x) ((x&0xff0000)>>16) 00069 #define MID(x) ((x&0xff00)>>8) 00070 #define LOW(x) (x&0xff) 00071 00072 00073 FlashM25PSpi::FlashM25PSpi(RTOS_SPI *spi, PinName enable, int bits, int mode) : 00074 _spi(spi) 00075 , _enable(enable) 00076 , _size(0) 00077 { 00078 if (bits) _spi->format(bits, mode); 00079 00080 _enable = 1; 00081 if (osKernelRunning()) { 00082 Thread::wait(1); 00083 } else { 00084 wait_us(1000); 00085 } 00086 _enable = 0; 00087 wait_us(1); 00088 uint8_t chipSig; 00089 // Reset and Ask for chip signature 00090 _spi->write(FLASH_RES); 00091 _spi->write(0); // Dummy writes 00092 _spi->write(0); // Dummy writes 00093 _spi->write(0); // Dummy writes 00094 chipSig = _spi->write(0); // Get Electronic Signature 00095 wait_us(1); 00096 _enable = 1; 00097 00098 unsigned int i = 0; 00099 while (_size == 0) { 00100 if (devices[i].memsize == 0) { // Nobody makes a memory of zero size 00101 #ifdef DEBUG 00102 printf("\r\nUnknown Flash Memory signature: %xh\r\n", chipSig); 00103 #endif 00104 return; 00105 } 00106 if (chipSig == devices[i].signature) { 00107 _size=devices[i].memsize; 00108 _sectorSize=devices[i].sectorsize; 00109 _pageSize=devices[i].pagesize; 00110 #ifdef DEBUG 00111 printf("\r\nFlash Memory Sig:%Xh : %u bytes Org: %x, %x\r\n", 00112 chipSig, _size, _sectorSize, _pageSize); 00113 #endif 00114 } else 00115 i++; 00116 } 00117 } 00118 00119 FlashM25PSpi::~FlashM25PSpi() 00120 { 00121 // Wait until chip finishes cycle 00122 // waitForWrite(); 00123 // Shutdown the flash chip into lowest-power mode 00124 _enable = 0; 00125 wait_us(1); 00126 _spi->write(FLASH_DP); 00127 wait_us(1); 00128 _enable = 1; 00129 } 00130 00131 bool FlashM25PSpi::read(uint32_t startAddr, void* destination, size_t len) 00132 { 00133 // Check size 00134 if (startAddr + len > _size) 00135 return false; 00136 _enable = 0; 00137 wait_us(1); 00138 00139 // Send address 00140 _spi->write(FLASH_READ); 00141 _spi->write(HIGH(startAddr)); 00142 _spi->write(MID(startAddr)); 00143 _spi->write(LOW(startAddr)); 00144 00145 uint8_t dummy = 0; 00146 00147 // Bulk read into destination buffer (DMA) 00148 // Be sure to write the same dummy databyte repeatedly 00149 _spi->bulkReadWrite((uint8_t*)destination, &dummy, len, false); 00150 00151 wait_us(1); 00152 _enable = 1; 00153 return true; 00154 } 00155 00156 bool FlashM25PSpi::write(uint32_t startAddr, const void* data, size_t len) 00157 { 00158 if (startAddr + len > _size) 00159 return false; 00160 00161 // Cast to uint8_t 00162 uint8_t *data8 = (uint8_t*)data; 00163 00164 size_t ofs = 0; 00165 while (ofs < len) { 00166 // calculate amount of data to write into current page 00167 size_t pageLen = _pageSize - ((startAddr + ofs) % _pageSize); 00168 if (ofs + pageLen > len) 00169 pageLen = len - ofs; 00170 // write single page 00171 if (!writePage(startAddr + ofs, data8 + ofs, pageLen)) 00172 return false; // Oh dear 00173 // and switch to next page 00174 ofs += pageLen; 00175 } 00176 return true; 00177 } 00178 00179 bool FlashM25PSpi::writePage(uint32_t startAddr, const uint8_t* data, size_t len) 00180 { 00181 enableWrite(); 00182 00183 _enable = 0; 00184 wait_us(1); 00185 00186 _spi->write(FLASH_PP); 00187 _spi->write(HIGH(startAddr)); 00188 _spi->write(MID(startAddr)); 00189 _spi->write(LOW(startAddr)); 00190 00191 // Bulk write using DMA 00192 _spi->bulkWrite(data, len); 00193 00194 wait_us(1); 00195 // disable to start physical write 00196 _enable = 1; 00197 00198 waitForWrite(); 00199 00200 return true; 00201 } 00202 00203 void FlashM25PSpi::eraseSector(uint32_t addr) 00204 { 00205 addr &= ~(_sectorSize-1); 00206 00207 enableWrite(); 00208 _enable = 0; 00209 wait_us(1); 00210 _spi->write(FLASH_SE); 00211 _spi->write(HIGH(addr)); 00212 _spi->write(MID(addr)); 00213 _spi->write(LOW(addr)); 00214 wait_us(1); 00215 _enable = 1; 00216 waitForWrite(); 00217 } 00218 00219 void FlashM25PSpi::eraseMem() 00220 { 00221 enableWrite(); 00222 _enable = 0; 00223 wait_us(1); 00224 _spi->write(FLASH_BE); 00225 wait_us(1); 00226 _enable = 1; 00227 waitForWrite(); 00228 } 00229 00230 int FlashM25PSpi::readStatus() 00231 { 00232 _enable = 0; 00233 wait_us(1); 00234 _spi->write(FLASH_RDSR); 00235 int status=_spi->write(0x00); 00236 wait_us(1); 00237 _enable = 1; 00238 return status; 00239 } 00240 00241 void FlashM25PSpi::waitForWrite() 00242 { 00243 while (true) { 00244 // Allow something else to do some work 00245 Thread::yield(); 00246 if (0 == (readStatus()&1)) return; 00247 } 00248 } 00249 00250 void FlashM25PSpi::enableWrite() 00251 { 00252 _enable = 0; 00253 wait_us(1); 00254 _spi->write(FLASH_WREN); 00255 wait_us(1); 00256 _enable = 1; 00257 }
Generated on Wed Jul 13 2022 20:11:02 by
1.7.2
