A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.

Dependencies:   FATFileSystem

Dependents:   LPC4088test LPC4088test_ledonly LPC4088test_deleteall LPC4088_RAMtest ... more

Committer:
embeddedartists
Date:
Wed Jun 10 08:34:09 2015 +0000
Revision:
20:e1e36493f347
Parent:
18:9f1f1a8b4729
Fixed compiler error in MCIFileSystem regarding us_ticker_api.h

Who changed what in which revision?

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