The wait in mci_WaitForEvent will delay all card transactions.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Committer:
dreschpe
Date:
Sun Dec 15 21:58:56 2013 +0000
Revision:
9:da373a015d07
Parent:
8:fe3cb3fbb64e
the wait in mci_WaitForEvent will delay all card transactions.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 8:fe3cb3fbb64e 1 #include "SPIFI.h"
embeddedartists 8:fe3cb3fbb64e 2 #include "mbed_debug.h"
embeddedartists 8:fe3cb3fbb64e 3
embeddedartists 8:fe3cb3fbb64e 4
embeddedartists 8:fe3cb3fbb64e 5 /******************************************************************************
embeddedartists 8:fe3cb3fbb64e 6 * Defines and typedefs
embeddedartists 8:fe3cb3fbb64e 7 *****************************************************************************/
embeddedartists 8:fe3cb3fbb64e 8
embeddedartists 8:fe3cb3fbb64e 9 #define SPIFI_DBG 0
embeddedartists 8:fe3cb3fbb64e 10
embeddedartists 8:fe3cb3fbb64e 11 /*
embeddedartists 8:fe3cb3fbb64e 12 * The SPIFI_ROM_PTR (0x1FFF1FF8) points to an area where the pointers to
embeddedartists 8:fe3cb3fbb64e 13 * different drivers in ROM are stored.
embeddedartists 8:fe3cb3fbb64e 14 */
embeddedartists 8:fe3cb3fbb64e 15 typedef struct {
embeddedartists 8:fe3cb3fbb64e 16 /*const*/ unsigned p_usbd; // USBROMD
embeddedartists 8:fe3cb3fbb64e 17 /*const*/ unsigned p_clib;
embeddedartists 8:fe3cb3fbb64e 18 /*const*/ unsigned p_cand;
embeddedartists 8:fe3cb3fbb64e 19 /*const*/ unsigned p_pwrd; // PWRROMD
embeddedartists 8:fe3cb3fbb64e 20 /*const*/ unsigned p_promd; // DIVROMD
embeddedartists 8:fe3cb3fbb64e 21 /*const*/ SPIFI_RTNS *pSPIFID; // SPIFIROMD
embeddedartists 8:fe3cb3fbb64e 22 /*const*/ unsigned p_dev3;
embeddedartists 8:fe3cb3fbb64e 23 /*const*/ unsigned p_dev4;
embeddedartists 8:fe3cb3fbb64e 24 } ROM;
embeddedartists 8:fe3cb3fbb64e 25
embeddedartists 8:fe3cb3fbb64e 26 #define ROM_DRIVERS_PTR ((ROM *)(*((unsigned int *)SPIFI_ROM_PTR)))
embeddedartists 8:fe3cb3fbb64e 27 #define IS_ADDR_IN_SPIFI(__addr) ( (((uint32_t)(__addr)) & 0xff000000) == SPIFI_MEM_BASE )
embeddedartists 8:fe3cb3fbb64e 28
embeddedartists 8:fe3cb3fbb64e 29 #define SPIFI_MIN(__a, __b) (((__a) < (__b)) ? (__a) : (__b))
embeddedartists 8:fe3cb3fbb64e 30
embeddedartists 8:fe3cb3fbb64e 31 /******************************************************************************
embeddedartists 8:fe3cb3fbb64e 32 * Local variables
embeddedartists 8:fe3cb3fbb64e 33 *****************************************************************************/
embeddedartists 8:fe3cb3fbb64e 34
embeddedartists 8:fe3cb3fbb64e 35 /******************************************************************************
embeddedartists 8:fe3cb3fbb64e 36 * Private Functions
embeddedartists 8:fe3cb3fbb64e 37 *****************************************************************************/
embeddedartists 8:fe3cb3fbb64e 38
embeddedartists 8:fe3cb3fbb64e 39 SPIFI::SpifiError SPIFI::translateError(int err, bool verify)
embeddedartists 8:fe3cb3fbb64e 40 {
embeddedartists 8:fe3cb3fbb64e 41 SpifiError res;
embeddedartists 8:fe3cb3fbb64e 42
embeddedartists 8:fe3cb3fbb64e 43 _verError = 0;
embeddedartists 8:fe3cb3fbb64e 44
embeddedartists 8:fe3cb3fbb64e 45 if (err == 0)
embeddedartists 8:fe3cb3fbb64e 46 {
embeddedartists 8:fe3cb3fbb64e 47 res = Ok;
embeddedartists 8:fe3cb3fbb64e 48 }
embeddedartists 8:fe3cb3fbb64e 49 else if ((err >= Uninitialized) && (err <= UnknownError))
embeddedartists 8:fe3cb3fbb64e 50 {
embeddedartists 8:fe3cb3fbb64e 51 // This is a known error code
embeddedartists 8:fe3cb3fbb64e 52 res = (SpifiError)err;
embeddedartists 8:fe3cb3fbb64e 53 }
embeddedartists 8:fe3cb3fbb64e 54 else if ((err >= InternalError) && (err <= EraseConflict))
embeddedartists 8:fe3cb3fbb64e 55 {
embeddedartists 8:fe3cb3fbb64e 56 // This is a known error code
embeddedartists 8:fe3cb3fbb64e 57 res = (SpifiError)err;
embeddedartists 8:fe3cb3fbb64e 58 }
embeddedartists 8:fe3cb3fbb64e 59 else if (verify)
embeddedartists 8:fe3cb3fbb64e 60 {
embeddedartists 8:fe3cb3fbb64e 61 // As verification was selected and err is not in the list of known
embeddedartists 8:fe3cb3fbb64e 62 // codes this falls into this category in the User's Manual:
embeddedartists 8:fe3cb3fbb64e 63 //
embeddedartists 8:fe3cb3fbb64e 64 // "Other non-zero values can occur if options selects verification.
embeddedartists 8:fe3cb3fbb64e 65 // They will be the address in the SPIFI memory area at which the
embeddedartists 8:fe3cb3fbb64e 66 // first discrepancy was found."
embeddedartists 8:fe3cb3fbb64e 67 _verError = err;
embeddedartists 8:fe3cb3fbb64e 68 res = Verification;
embeddedartists 8:fe3cb3fbb64e 69 }
embeddedartists 8:fe3cb3fbb64e 70 else
embeddedartists 8:fe3cb3fbb64e 71 {
embeddedartists 8:fe3cb3fbb64e 72 // Should never happen :-) as all listed error codes are covered but
embeddedartists 8:fe3cb3fbb64e 73 // to be on the safe side and not interpret this as a success, a generic
embeddedartists 8:fe3cb3fbb64e 74 // error is set.
embeddedartists 8:fe3cb3fbb64e 75 res = UnknownError;
embeddedartists 8:fe3cb3fbb64e 76 }
embeddedartists 8:fe3cb3fbb64e 77 return res;
embeddedartists 8:fe3cb3fbb64e 78 }
embeddedartists 8:fe3cb3fbb64e 79
embeddedartists 8:fe3cb3fbb64e 80 /******************************************************************************
embeddedartists 8:fe3cb3fbb64e 81 * Public Functions
embeddedartists 8:fe3cb3fbb64e 82 *****************************************************************************/
embeddedartists 8:fe3cb3fbb64e 83
embeddedartists 8:fe3cb3fbb64e 84 SPIFI::SPIFI()
embeddedartists 8:fe3cb3fbb64e 85 {
embeddedartists 8:fe3cb3fbb64e 86 _verError = 0;
embeddedartists 8:fe3cb3fbb64e 87 _initialized = false;
embeddedartists 8:fe3cb3fbb64e 88 _device = UnknownDevice;
embeddedartists 8:fe3cb3fbb64e 89 _memorySize = 0;
embeddedartists 8:fe3cb3fbb64e 90 _eraseBlockSize = 0;
embeddedartists 8:fe3cb3fbb64e 91
embeddedartists 8:fe3cb3fbb64e 92 _romData = (SPIFIobj*)malloc(sizeof(SPIFIobj));
embeddedartists 8:fe3cb3fbb64e 93 if (_romData == NULL) {
embeddedartists 8:fe3cb3fbb64e 94 debug("SPIFI: Failed to allocate memory for ROM data\n");
embeddedartists 8:fe3cb3fbb64e 95 }
embeddedartists 8:fe3cb3fbb64e 96 }
embeddedartists 8:fe3cb3fbb64e 97
embeddedartists 8:fe3cb3fbb64e 98 SPIFI::~SPIFI()
embeddedartists 8:fe3cb3fbb64e 99 {
embeddedartists 8:fe3cb3fbb64e 100 if (_romData != NULL) {
embeddedartists 8:fe3cb3fbb64e 101 free(_romData);
embeddedartists 8:fe3cb3fbb64e 102 }
embeddedartists 8:fe3cb3fbb64e 103 }
embeddedartists 8:fe3cb3fbb64e 104
embeddedartists 8:fe3cb3fbb64e 105 SPIFI::SpifiError SPIFI::init()
embeddedartists 8:fe3cb3fbb64e 106 {
embeddedartists 8:fe3cb3fbb64e 107 if (!_initialized) {
embeddedartists 8:fe3cb3fbb64e 108
embeddedartists 8:fe3cb3fbb64e 109 // Turn on SPIFI block as it is disabled on reset
embeddedartists 8:fe3cb3fbb64e 110 LPC_SC->PCONP |= 0x00010000;
embeddedartists 8:fe3cb3fbb64e 111
embeddedartists 8:fe3cb3fbb64e 112 // pinsel for SPIFI
embeddedartists 8:fe3cb3fbb64e 113 LPC_IOCON->P2_7 = 5; /* SPIFI_CSN @ P2.7 */
embeddedartists 8:fe3cb3fbb64e 114 LPC_IOCON->P0_22 = 5; /* SPIFI_CLK @ P0.22 */
embeddedartists 8:fe3cb3fbb64e 115 LPC_IOCON->P0_15 = 5; /* SPIFI_IO2 @ P0.15 */
embeddedartists 8:fe3cb3fbb64e 116 LPC_IOCON->P0_16 = 5; /* SPIFI_IO3 @ P0.16 */
embeddedartists 8:fe3cb3fbb64e 117 LPC_IOCON->P0_17 = 5; /* SPIFI_IO1 @ P0.17 */
embeddedartists 8:fe3cb3fbb64e 118 LPC_IOCON->P0_18 = 5; /* SPIFI_IO0 @ P0.18 */
embeddedartists 8:fe3cb3fbb64e 119
embeddedartists 8:fe3cb3fbb64e 120 uint32_t spifi_clk_div = (*((volatile uint32_t*)0x400FC1B4)) & 0x1f;
embeddedartists 8:fe3cb3fbb64e 121 uint32_t spifi_clk_mhz = (SystemCoreClock / spifi_clk_div) / 1000000;
embeddedartists 8:fe3cb3fbb64e 122
embeddedartists 8:fe3cb3fbb64e 123 _spifi = ROM_DRIVERS_PTR->pSPIFID;
embeddedartists 8:fe3cb3fbb64e 124
embeddedartists 8:fe3cb3fbb64e 125 /* Typical time tCS is 20 ns min, we give 200 ns to be on safer side */
embeddedartists 8:fe3cb3fbb64e 126 int rc = _spifi->spifi_init (_romData, spifi_clk_mhz/5, S_FULLCLK+S_RCVCLK, spifi_clk_mhz);
embeddedartists 8:fe3cb3fbb64e 127 if (rc) {
embeddedartists 8:fe3cb3fbb64e 128 _spifi = NULL;
embeddedartists 8:fe3cb3fbb64e 129 return translateError(rc);
embeddedartists 8:fe3cb3fbb64e 130 }
embeddedartists 8:fe3cb3fbb64e 131
embeddedartists 8:fe3cb3fbb64e 132 /* Make sure it is a tested flash module */
embeddedartists 8:fe3cb3fbb64e 133 if ((_romData->mfger == 1) && (_romData->devType == 0x2) && (_romData->devID == 0x15) && (_romData->memSize > 0x100000))
embeddedartists 8:fe3cb3fbb64e 134 {
embeddedartists 8:fe3cb3fbb64e 135 _device = Spansion_S25FL032;
embeddedartists 8:fe3cb3fbb64e 136 _memorySize = _romData->memSize;
embeddedartists 8:fe3cb3fbb64e 137 _eraseBlockSize = 64*1024;
embeddedartists 8:fe3cb3fbb64e 138 }
embeddedartists 8:fe3cb3fbb64e 139 else if ((_romData->mfger == 0xef) && (_romData->devType == 0x40) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000))
embeddedartists 8:fe3cb3fbb64e 140 {
embeddedartists 8:fe3cb3fbb64e 141 _device = Winbond_W25Q64FV;
embeddedartists 8:fe3cb3fbb64e 142 _memorySize = _romData->memSize;
embeddedartists 8:fe3cb3fbb64e 143 _eraseBlockSize = 4*1024;
embeddedartists 8:fe3cb3fbb64e 144 }
embeddedartists 8:fe3cb3fbb64e 145 else
embeddedartists 8:fe3cb3fbb64e 146 {
embeddedartists 8:fe3cb3fbb64e 147 debug("SPIFI::init(): Memory is unknown and may not work as expected\n");
embeddedartists 8:fe3cb3fbb64e 148
embeddedartists 8:fe3cb3fbb64e 149 // Asuming it has 64Kb erase blocks (i.e. same setup as the Spansion S25FL032
embeddedartists 8:fe3cb3fbb64e 150 _device = UnknownDevice;
embeddedartists 8:fe3cb3fbb64e 151 _memorySize = _romData->memSize;
embeddedartists 8:fe3cb3fbb64e 152 _eraseBlockSize = 64*1024;
embeddedartists 8:fe3cb3fbb64e 153
embeddedartists 8:fe3cb3fbb64e 154 /*
embeddedartists 8:fe3cb3fbb64e 155 * If this happens, check the manufacturer and device information
embeddedartists 8:fe3cb3fbb64e 156 * and compare with the data sheet for your chip. Also make sure
embeddedartists 8:fe3cb3fbb64e 157 * that the sector sizes are the same (i.e. 64KB) for your chip.
embeddedartists 8:fe3cb3fbb64e 158 * If everything is the same then add an exception for your chip.
embeddedartists 8:fe3cb3fbb64e 159 */
embeddedartists 8:fe3cb3fbb64e 160 }
embeddedartists 8:fe3cb3fbb64e 161
embeddedartists 8:fe3cb3fbb64e 162 _initialized = true;
embeddedartists 8:fe3cb3fbb64e 163 }
embeddedartists 8:fe3cb3fbb64e 164 return Ok;
embeddedartists 8:fe3cb3fbb64e 165 }
embeddedartists 8:fe3cb3fbb64e 166
embeddedartists 8:fe3cb3fbb64e 167 SPIFI::SpifiError SPIFI::program(uint32_t dest, unsigned len, char* src, Options options, bool verify, char* scratch)
embeddedartists 8:fe3cb3fbb64e 168 {
embeddedartists 8:fe3cb3fbb64e 169 unsigned written = 0;
embeddedartists 8:fe3cb3fbb64e 170 SPIFIopers opers;
embeddedartists 8:fe3cb3fbb64e 171 opers.dest = (char *)dest;
embeddedartists 8:fe3cb3fbb64e 172 opers.length = SPIFI_MIN(len, PROG_SIZE);
embeddedartists 8:fe3cb3fbb64e 173 opers.scratch = scratch;
embeddedartists 8:fe3cb3fbb64e 174 opers.protect = 0;
embeddedartists 8:fe3cb3fbb64e 175 opers.options = options;
embeddedartists 8:fe3cb3fbb64e 176 if (verify) {
embeddedartists 8:fe3cb3fbb64e 177 opers.options |= S_VERIFY_PROG;
embeddedartists 8:fe3cb3fbb64e 178 }
embeddedartists 8:fe3cb3fbb64e 179
embeddedartists 8:fe3cb3fbb64e 180 if (IS_ADDR_IN_SPIFI(src))
embeddedartists 8:fe3cb3fbb64e 181 {
embeddedartists 8:fe3cb3fbb64e 182 // The SPIFI ROM driver cannot write data from SPIFI into
embeddedartists 8:fe3cb3fbb64e 183 // SPIFI (i.e. cannot read and write at the same time).
embeddedartists 8:fe3cb3fbb64e 184 // The workaround is to copy the source data into a buffer
embeddedartists 8:fe3cb3fbb64e 185 // in local memory and use that as source for the write
embeddedartists 8:fe3cb3fbb64e 186 // instead.
embeddedartists 8:fe3cb3fbb64e 187 while (written < len) {
embeddedartists 8:fe3cb3fbb64e 188 memcpy(_addrConflictBuff, src + written, opers.length);
embeddedartists 8:fe3cb3fbb64e 189 int rc = _spifi->spifi_program(_romData, _addrConflictBuff, &opers);
embeddedartists 8:fe3cb3fbb64e 190 if (rc)
embeddedartists 8:fe3cb3fbb64e 191 {
embeddedartists 8:fe3cb3fbb64e 192 // got an error
embeddedartists 8:fe3cb3fbb64e 193 return translateError(rc, verify);
embeddedartists 8:fe3cb3fbb64e 194 }
embeddedartists 8:fe3cb3fbb64e 195 written += opers.length;
embeddedartists 8:fe3cb3fbb64e 196 opers.dest += opers.length;
embeddedartists 8:fe3cb3fbb64e 197 opers.length = SPIFI_MIN(len - written, PROG_SIZE);
embeddedartists 8:fe3cb3fbb64e 198 }
embeddedartists 8:fe3cb3fbb64e 199 }
embeddedartists 8:fe3cb3fbb64e 200 else
embeddedartists 8:fe3cb3fbb64e 201 {
embeddedartists 8:fe3cb3fbb64e 202 while (written < len) {
embeddedartists 8:fe3cb3fbb64e 203 int rc = _spifi->spifi_program(_romData, src + written, &opers);
embeddedartists 8:fe3cb3fbb64e 204 if (rc)
embeddedartists 8:fe3cb3fbb64e 205 {
embeddedartists 8:fe3cb3fbb64e 206 // got an error
embeddedartists 8:fe3cb3fbb64e 207 return translateError(rc, verify);
embeddedartists 8:fe3cb3fbb64e 208 }
embeddedartists 8:fe3cb3fbb64e 209 written += opers.length;
embeddedartists 8:fe3cb3fbb64e 210 opers.dest += opers.length;
embeddedartists 8:fe3cb3fbb64e 211 opers.length = SPIFI_MIN(len - written, PROG_SIZE);
embeddedartists 8:fe3cb3fbb64e 212 }
embeddedartists 8:fe3cb3fbb64e 213 }
embeddedartists 8:fe3cb3fbb64e 214
embeddedartists 8:fe3cb3fbb64e 215 return Ok;
embeddedartists 8:fe3cb3fbb64e 216 }
embeddedartists 8:fe3cb3fbb64e 217
embeddedartists 8:fe3cb3fbb64e 218 SPIFI::SpifiError SPIFI::erase(uint32_t dest, unsigned len, char* src, bool verify, char* scratch)
embeddedartists 8:fe3cb3fbb64e 219 {
embeddedartists 8:fe3cb3fbb64e 220 SPIFIopers opers;
embeddedartists 8:fe3cb3fbb64e 221 opers.dest = (char *)dest;
embeddedartists 8:fe3cb3fbb64e 222 opers.length = len;
embeddedartists 8:fe3cb3fbb64e 223 opers.scratch = scratch;
embeddedartists 8:fe3cb3fbb64e 224 opers.protect = 0;
embeddedartists 8:fe3cb3fbb64e 225 if (verify) {
embeddedartists 8:fe3cb3fbb64e 226 opers.options = S_VERIFY_ERASE;
embeddedartists 8:fe3cb3fbb64e 227 } else {
embeddedartists 8:fe3cb3fbb64e 228 opers.options = S_NO_VERIFY;
embeddedartists 8:fe3cb3fbb64e 229 }
embeddedartists 8:fe3cb3fbb64e 230 int rc = _spifi->spifi_erase(_romData, &opers);
embeddedartists 8:fe3cb3fbb64e 231 return translateError(rc);
embeddedartists 8:fe3cb3fbb64e 232 }
embeddedartists 8:fe3cb3fbb64e 233
embeddedartists 8:fe3cb3fbb64e 234