![](/media/cache/group/logo.png.50x50_q85.jpg)
A board support package for the LPC4088 Display Module.
Dependencies: DM_HttpServer DM_USBHost
Dependents: lpc4088_displaymodule_emwin lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI ... more
Fork of DMSupport by
SPIFI.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "SPIFI.h" 00018 #include "mbed_debug.h" 00019 #include "BiosLoader.h" 00020 00021 00022 /****************************************************************************** 00023 * Defines and typedefs 00024 *****************************************************************************/ 00025 00026 #define SPIFI_DBG 0 00027 00028 /* 00029 * The SPIFI_ROM_PTR (0x1FFF1FF8) points to an area where the pointers to 00030 * different drivers in ROM are stored. 00031 */ 00032 typedef struct { 00033 /*const*/ unsigned p_usbd; // USBROMD 00034 /*const*/ unsigned p_clib; 00035 /*const*/ unsigned p_cand; 00036 /*const*/ unsigned p_pwrd; // PWRROMD 00037 /*const*/ unsigned p_promd; // DIVROMD 00038 /*const*/ SPIFI_RTNS *pSPIFID; // SPIFIROMD 00039 /*const*/ unsigned p_dev3; 00040 /*const*/ unsigned p_dev4; 00041 } ROM; 00042 00043 #define ROM_DRIVERS_PTR ((ROM *)(*((unsigned int *)SPIFI_ROM_PTR))) 00044 #define IS_ADDR_IN_SPIFI(__addr) ( (((uint32_t)(__addr)) & 0xff000000) == SPIFI_MEM_BASE ) 00045 00046 #define SPIFI_MIN(__a, __b) (((__a) < (__b)) ? (__a) : (__b)) 00047 00048 /****************************************************************************** 00049 * Local variables 00050 *****************************************************************************/ 00051 00052 /****************************************************************************** 00053 * Private Functions 00054 *****************************************************************************/ 00055 00056 SPIFI::SpifiError SPIFI::translateError(int err, bool verify) 00057 { 00058 SpifiError res; 00059 00060 _verError = 0; 00061 00062 if (err == 0) 00063 { 00064 res = Ok; 00065 } 00066 else if ((err >= Uninitialized) && (err <= UnknownError)) 00067 { 00068 // This is a known error code 00069 res = (SpifiError)err; 00070 } 00071 else if ((err >= InternalError) && (err <= EraseConflict)) 00072 { 00073 // This is a known error code 00074 res = (SpifiError)err; 00075 } 00076 else if (verify) 00077 { 00078 // As verification was selected and err is not in the list of known 00079 // codes this falls into this category in the User's Manual: 00080 // 00081 // "Other non-zero values can occur if options selects verification. 00082 // They will be the address in the SPIFI memory area at which the 00083 // first discrepancy was found." 00084 _verError = err; 00085 res = Verification; 00086 } 00087 else 00088 { 00089 // Should never happen :-) as all listed error codes are covered but 00090 // to be on the safe side and not interpret this as a success, a generic 00091 // error is set. 00092 res = UnknownError; 00093 } 00094 return res; 00095 } 00096 00097 /****************************************************************************** 00098 * Public Functions 00099 *****************************************************************************/ 00100 00101 SPIFI::SPIFI() 00102 { 00103 _verError = 0; 00104 _initialized = false; 00105 _device = UnknownDevice; 00106 _memorySize = 0; 00107 _eraseBlockSize = 0; 00108 00109 _romData = (SPIFIobj*)malloc(sizeof(SPIFIobj)); 00110 if (_romData == NULL) { 00111 debug("SPIFI: Failed to allocate memory for ROM data\n"); 00112 } 00113 } 00114 00115 SPIFI::~SPIFI() 00116 { 00117 if (_romData != NULL) { 00118 free(_romData); 00119 } 00120 } 00121 00122 SPIFI::SpifiError SPIFI::init() 00123 { 00124 if (!_initialized) { 00125 00126 // Turn on SPIFI block as it is disabled on reset 00127 LPC_SC->PCONP |= 0x00010000; 00128 00129 // Configure clock source as Main PLL and divider 2 to get 60MHz 00130 uint32_t spifi_clk_div = 2; 00131 LPC_SC->SPIFICLKSEL = (1<<8) | spifi_clk_div; 00132 00133 // pinsel for SPIFI 00134 LPC_IOCON->P2_7 = 5; /* SPIFI_CSN @ P2.7 */ 00135 LPC_IOCON->P0_22 = 5; /* SPIFI_CLK @ P0.22 */ 00136 LPC_IOCON->P0_15 = 5; /* SPIFI_IO2 @ P0.15 */ 00137 LPC_IOCON->P0_16 = 5; /* SPIFI_IO3 @ P0.16 */ 00138 LPC_IOCON->P0_17 = 5; /* SPIFI_IO1 @ P0.17 */ 00139 LPC_IOCON->P0_18 = 5; /* SPIFI_IO0 @ P0.18 */ 00140 00141 uint32_t spifi_clk_mhz = (SystemCoreClock / spifi_clk_div) / 1000000; 00142 00143 _spifi = ROM_DRIVERS_PTR->pSPIFID; 00144 00145 /* Typical time tCS is 20 ns min, we give 200 ns to be on safer side */ 00146 int rc = _spifi->spifi_init (_romData, spifi_clk_mhz/5, S_FULLCLK+S_RCVCLK, spifi_clk_mhz); 00147 if (rc) { 00148 _spifi = NULL; 00149 return translateError(rc); 00150 } 00151 00152 /* Make sure it is a tested flash module */ 00153 if ((_romData->mfger == 1) && (_romData->devType == 0x2) && (_romData->devID == 0x15) && (_romData->memSize > 0x100000)) 00154 { 00155 _device = Spansion_S25FL032; 00156 _memorySize = _romData->memSize; 00157 _eraseBlockSize = 64*1024; 00158 } 00159 else if ((_romData->mfger == 0xef) && (_romData->devType == 0x40) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000)) 00160 { 00161 _device = Winbond_W25Q64FV; 00162 _memorySize = _romData->memSize; 00163 _eraseBlockSize = 4*1024; 00164 } 00165 else if ((_romData->mfger == 0xc2) && (_romData->devType == 0x20) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000)) 00166 { 00167 _device = Macronix_MX25L6435E; 00168 _memorySize = _romData->memSize; 00169 _eraseBlockSize = 4*1024; 00170 } 00171 else if ((_romData->mfger == 0xc2) && (_romData->devType == 0x20) && (_romData->devID == 0x18) && (_romData->memSize > 0x100000)) 00172 { 00173 _device = Macronix_MX25L12835F; 00174 _memorySize = _romData->memSize; 00175 _eraseBlockSize = 4*1024; 00176 } 00177 else if (BiosLoader::instance().isKnownSPIFIMemory(_romData->mfger, _romData->devType, _romData->devID, _romData->memSize, &_eraseBlockSize)) 00178 { 00179 /* The BIOS was able to identify the FLASH and we will use the 00180 * eraseBlockSize specified in the BIOS. 00181 */ 00182 _device = SpecifiedInBios; 00183 _memorySize = _romData->memSize; 00184 } 00185 else 00186 { 00187 debug("SPIFI::init(): Memory is unknown and may not work as expected\n"); 00188 debug("ID: mfgr 0x%02x, devType 0x%02x, devID 0x%02x, memSize 0x%x\n", 00189 _romData->mfger, _romData->devType, _romData->devID, _romData->memSize); 00190 00191 // Asuming it has 64Kb erase blocks (i.e. same setup as the Spansion S25FL032 00192 _device = UnknownDevice; 00193 _memorySize = _romData->memSize; 00194 _eraseBlockSize = 64*1024; 00195 00196 /* 00197 * If this happens, check the manufacturer and device information 00198 * and compare with the data sheet for your chip. Also make sure 00199 * that the sector sizes are the same (i.e. 64KB) for your chip. 00200 * If everything is the same then add an exception for your chip. 00201 */ 00202 } 00203 00204 _initialized = true; 00205 } 00206 return Ok; 00207 } 00208 00209 SPIFI::SpifiError SPIFI::program(uint32_t dest, unsigned len, char* src, Options options, bool verify, char* scratch) 00210 { 00211 unsigned written = 0; 00212 SPIFIopers opers; 00213 opers.dest = (char *)dest; 00214 opers.length = SPIFI_MIN(len, PROG_SIZE); 00215 opers.scratch = scratch; 00216 opers.protect = 0; 00217 opers.options = options; 00218 if (verify) { 00219 opers.options |= S_VERIFY_PROG; 00220 } 00221 00222 if (IS_ADDR_IN_SPIFI(src)) 00223 { 00224 // The SPIFI ROM driver cannot write data from SPIFI into 00225 // SPIFI (i.e. cannot read and write at the same time). 00226 // The workaround is to copy the source data into a buffer 00227 // in local memory and use that as source for the write 00228 // instead. 00229 while (written < len) { 00230 memcpy(_addrConflictBuff, src + written, opers.length); 00231 int rc = _spifi->spifi_program(_romData, _addrConflictBuff, &opers); 00232 if (rc) 00233 { 00234 // got an error 00235 return translateError(rc, verify); 00236 } 00237 written += opers.length; 00238 opers.dest += opers.length; 00239 opers.length = SPIFI_MIN(len - written, PROG_SIZE); 00240 } 00241 } 00242 else 00243 { 00244 while (written < len) { 00245 int rc = _spifi->spifi_program(_romData, src + written, &opers); 00246 if (rc) 00247 { 00248 // got an error 00249 return translateError(rc, verify); 00250 } 00251 written += opers.length; 00252 opers.dest += opers.length; 00253 opers.length = SPIFI_MIN(len - written, PROG_SIZE); 00254 } 00255 } 00256 00257 return Ok; 00258 } 00259 00260 SPIFI::SpifiError SPIFI::erase(uint32_t dest, unsigned len, bool verify, char* scratch) 00261 { 00262 SPIFIopers opers; 00263 opers.dest = (char *)dest; 00264 opers.length = len; 00265 opers.scratch = scratch; 00266 opers.protect = 0; 00267 if (verify) { 00268 opers.options = S_VERIFY_ERASE; 00269 } else { 00270 opers.options = S_NO_VERIFY; 00271 } 00272 int rc = _spifi->spifi_erase(_romData, &opers); 00273 return translateError(rc); 00274 }
Generated on Tue Jul 12 2022 14:18:31 by
![doxygen](doxygen.png)