Update version of EALib.

Dependencies:   FATFileSystem

Fork of EALib by IONX

Committer:
embeddedartists
Date:
Wed Dec 11 12:16:40 2013 +0000
Revision:
8:fe3cb3fbb64e
Child:
12:15597e45eea0
Extracted SPIFI initialization code from QSPIFileSystem into new SPIFI class to allow spifi to be used without having to use the file system.

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