A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.
Fork of EALib by
SPIFI.cpp
00001 /* 00002 * Copyright 2013 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 00020 00021 /****************************************************************************** 00022 * Defines and typedefs 00023 *****************************************************************************/ 00024 00025 #define SPIFI_DBG 0 00026 00027 /* 00028 * The SPIFI_ROM_PTR (0x1FFF1FF8) points to an area where the pointers to 00029 * different drivers in ROM are stored. 00030 */ 00031 typedef struct { 00032 /*const*/ unsigned p_usbd; // USBROMD 00033 /*const*/ unsigned p_clib; 00034 /*const*/ unsigned p_cand; 00035 /*const*/ unsigned p_pwrd; // PWRROMD 00036 /*const*/ unsigned p_promd; // DIVROMD 00037 /*const*/ SPIFI_RTNS *pSPIFID; // SPIFIROMD 00038 /*const*/ unsigned p_dev3; 00039 /*const*/ unsigned p_dev4; 00040 } ROM; 00041 00042 #define ROM_DRIVERS_PTR ((ROM *)(*((unsigned int *)SPIFI_ROM_PTR))) 00043 #define IS_ADDR_IN_SPIFI(__addr) ( (((uint32_t)(__addr)) & 0xff000000) == SPIFI_MEM_BASE ) 00044 00045 #define SPIFI_MIN(__a, __b) (((__a) < (__b)) ? (__a) : (__b)) 00046 00047 /****************************************************************************** 00048 * Local variables 00049 *****************************************************************************/ 00050 00051 /****************************************************************************** 00052 * Private Functions 00053 *****************************************************************************/ 00054 00055 SPIFI::SpifiError SPIFI::translateError(int err, bool verify) 00056 { 00057 SpifiError res; 00058 00059 _verError = 0; 00060 00061 if (err == 0) 00062 { 00063 res = Ok; 00064 } 00065 else if ((err >= Uninitialized) && (err <= UnknownError)) 00066 { 00067 // This is a known error code 00068 res = (SpifiError)err; 00069 } 00070 else if ((err >= InternalError) && (err <= EraseConflict)) 00071 { 00072 // This is a known error code 00073 res = (SpifiError)err; 00074 } 00075 else if (verify) 00076 { 00077 // As verification was selected and err is not in the list of known 00078 // codes this falls into this category in the User's Manual: 00079 // 00080 // "Other non-zero values can occur if options selects verification. 00081 // They will be the address in the SPIFI memory area at which the 00082 // first discrepancy was found." 00083 _verError = err; 00084 res = Verification; 00085 } 00086 else 00087 { 00088 // Should never happen :-) as all listed error codes are covered but 00089 // to be on the safe side and not interpret this as a success, a generic 00090 // error is set. 00091 res = UnknownError; 00092 } 00093 return res; 00094 } 00095 00096 /****************************************************************************** 00097 * Public Functions 00098 *****************************************************************************/ 00099 00100 SPIFI::SPIFI() 00101 { 00102 _verError = 0; 00103 _initialized = false; 00104 _device = UnknownDevice; 00105 _memorySize = 0; 00106 _eraseBlockSize = 0; 00107 00108 _romData = (SPIFIobj*)malloc(sizeof(SPIFIobj)); 00109 if (_romData == NULL) { 00110 debug("SPIFI: Failed to allocate memory for ROM data\n"); 00111 } 00112 } 00113 00114 SPIFI::~SPIFI() 00115 { 00116 if (_romData != NULL) { 00117 free(_romData); 00118 } 00119 } 00120 00121 SPIFI::SpifiError SPIFI::init() 00122 { 00123 if (!_initialized) { 00124 00125 // Turn on SPIFI block as it is disabled on reset 00126 LPC_SC->PCONP |= 0x00010000; 00127 00128 // pinsel for SPIFI 00129 LPC_IOCON->P2_7 = 5; /* SPIFI_CSN @ P2.7 */ 00130 LPC_IOCON->P0_22 = 5; /* SPIFI_CLK @ P0.22 */ 00131 LPC_IOCON->P0_15 = 5; /* SPIFI_IO2 @ P0.15 */ 00132 LPC_IOCON->P0_16 = 5; /* SPIFI_IO3 @ P0.16 */ 00133 LPC_IOCON->P0_17 = 5; /* SPIFI_IO1 @ P0.17 */ 00134 LPC_IOCON->P0_18 = 5; /* SPIFI_IO0 @ P0.18 */ 00135 00136 uint32_t spifi_clk_div = (*((volatile uint32_t*)0x400FC1B4)) & 0x1f; 00137 uint32_t spifi_clk_mhz = (SystemCoreClock / spifi_clk_div) / 1000000; 00138 00139 _spifi = ROM_DRIVERS_PTR->pSPIFID; 00140 00141 /* Typical time tCS is 20 ns min, we give 200 ns to be on safer side */ 00142 int rc = _spifi->spifi_init (_romData, spifi_clk_mhz/5, S_FULLCLK+S_RCVCLK, spifi_clk_mhz); 00143 if (rc) { 00144 _spifi = NULL; 00145 return translateError(rc); 00146 } 00147 00148 /* Make sure it is a tested flash module */ 00149 if ((_romData->mfger == 1) && (_romData->devType == 0x2) && (_romData->devID == 0x15) && (_romData->memSize > 0x100000)) 00150 { 00151 _device = Spansion_S25FL032; 00152 _memorySize = _romData->memSize; 00153 _eraseBlockSize = 64*1024; 00154 } 00155 else if ((_romData->mfger == 0xef) && (_romData->devType == 0x40) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000)) 00156 { 00157 _device = Winbond_W25Q64FV; 00158 _memorySize = _romData->memSize; 00159 _eraseBlockSize = 4*1024; 00160 } 00161 else if ((_romData->mfger == 0xc2) && (_romData->devType == 0x20) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000)) 00162 { 00163 _device = Macronix_MX25L6435EM2I; 00164 _memorySize = _romData->memSize; 00165 _eraseBlockSize = 4*1024; 00166 } 00167 else 00168 { 00169 debug("SPIFI::init(): Memory is unknown and may not work as expected\n"); 00170 00171 // Asuming it has 64Kb erase blocks (i.e. same setup as the Spansion S25FL032 00172 _device = UnknownDevice; 00173 _memorySize = _romData->memSize; 00174 _eraseBlockSize = 64*1024; 00175 00176 /* 00177 * If this happens, check the manufacturer and device information 00178 * and compare with the data sheet for your chip. Also make sure 00179 * that the sector sizes are the same (i.e. 64KB) for your chip. 00180 * If everything is the same then add an exception for your chip. 00181 */ 00182 } 00183 00184 _initialized = true; 00185 } 00186 return Ok; 00187 } 00188 00189 SPIFI::SpifiError SPIFI::program(uint32_t dest, unsigned len, char* src, Options options, bool verify, char* scratch) 00190 { 00191 unsigned written = 0; 00192 SPIFIopers opers; 00193 opers.dest = (char *)dest; 00194 opers.length = SPIFI_MIN(len, PROG_SIZE); 00195 opers.scratch = scratch; 00196 opers.protect = 0; 00197 opers.options = options; 00198 if (verify) { 00199 opers.options |= S_VERIFY_PROG; 00200 } 00201 00202 if (IS_ADDR_IN_SPIFI(src)) 00203 { 00204 // The SPIFI ROM driver cannot write data from SPIFI into 00205 // SPIFI (i.e. cannot read and write at the same time). 00206 // The workaround is to copy the source data into a buffer 00207 // in local memory and use that as source for the write 00208 // instead. 00209 while (written < len) { 00210 memcpy(_addrConflictBuff, src + written, opers.length); 00211 int rc = _spifi->spifi_program(_romData, _addrConflictBuff, &opers); 00212 if (rc) 00213 { 00214 // got an error 00215 return translateError(rc, verify); 00216 } 00217 written += opers.length; 00218 opers.dest += opers.length; 00219 opers.length = SPIFI_MIN(len - written, PROG_SIZE); 00220 } 00221 } 00222 else 00223 { 00224 while (written < len) { 00225 int rc = _spifi->spifi_program(_romData, src + written, &opers); 00226 if (rc) 00227 { 00228 // got an error 00229 return translateError(rc, verify); 00230 } 00231 written += opers.length; 00232 opers.dest += opers.length; 00233 opers.length = SPIFI_MIN(len - written, PROG_SIZE); 00234 } 00235 } 00236 00237 return Ok; 00238 } 00239 00240 SPIFI::SpifiError SPIFI::erase(uint32_t dest, unsigned len, char* src, bool verify, char* scratch) 00241 { 00242 SPIFIopers opers; 00243 opers.dest = (char *)dest; 00244 opers.length = len; 00245 opers.scratch = scratch; 00246 opers.protect = 0; 00247 if (verify) { 00248 opers.options = S_VERIFY_ERASE; 00249 } else { 00250 opers.options = S_NO_VERIFY; 00251 } 00252 int rc = _spifi->spifi_erase(_romData, &opers); 00253 return translateError(rc); 00254 } 00255 00256
Generated on Wed Jul 13 2022 02:29:31 by 1.7.2