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