Dependencies:   DM_FATFileSystem EthernetInterface HTTPClient mbed-rtos mbed-src

Fork of DMSupport by Embedded Artists

Committer:
embeddedartists
Date:
Fri Jan 09 11:42:06 2015 +0100
Revision:
19:2efb6f5f69a4
Parent:
9:a33326afd686
Child:
22:1a58a518435c
Added support for the new Macronix_MX25L12835F QSPI flash

Who changed what in which revision?

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