Dependencies:   DM_FATFileSystem EthernetInterface HTTPClient mbed-rtos mbed-src

Fork of DMSupport by Embedded Artists

Committer:
embeddedartists
Date:
Fri Nov 21 11:42:51 2014 +0000
Revision:
0:6b68dac0d986
Child:
3:2fa7755f2cef
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 0:6b68dac0d986 1 /*
embeddedartists 0:6b68dac0d986 2 * Copyright 2013 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 0:6b68dac0d986 127
embeddedartists 0:6b68dac0d986 128 // pinsel for SPIFI
embeddedartists 0:6b68dac0d986 129 LPC_IOCON->P2_7 = 5; /* SPIFI_CSN @ P2.7 */
embeddedartists 0:6b68dac0d986 130 LPC_IOCON->P0_22 = 5; /* SPIFI_CLK @ P0.22 */
embeddedartists 0:6b68dac0d986 131 LPC_IOCON->P0_15 = 5; /* SPIFI_IO2 @ P0.15 */
embeddedartists 0:6b68dac0d986 132 LPC_IOCON->P0_16 = 5; /* SPIFI_IO3 @ P0.16 */
embeddedartists 0:6b68dac0d986 133 LPC_IOCON->P0_17 = 5; /* SPIFI_IO1 @ P0.17 */
embeddedartists 0:6b68dac0d986 134 LPC_IOCON->P0_18 = 5; /* SPIFI_IO0 @ P0.18 */
embeddedartists 0:6b68dac0d986 135
embeddedartists 0:6b68dac0d986 136 uint32_t spifi_clk_div = (*((volatile uint32_t*)0x400FC1B4)) & 0x1f;
embeddedartists 0:6b68dac0d986 137 uint32_t spifi_clk_mhz = (SystemCoreClock / spifi_clk_div) / 1000000;
embeddedartists 0:6b68dac0d986 138
embeddedartists 0:6b68dac0d986 139 _spifi = ROM_DRIVERS_PTR->pSPIFID;
embeddedartists 0:6b68dac0d986 140
embeddedartists 0:6b68dac0d986 141 /* Typical time tCS is 20 ns min, we give 200 ns to be on safer side */
embeddedartists 0:6b68dac0d986 142 int rc = _spifi->spifi_init (_romData, spifi_clk_mhz/5, S_FULLCLK+S_RCVCLK, spifi_clk_mhz);
embeddedartists 0:6b68dac0d986 143 if (rc) {
embeddedartists 0:6b68dac0d986 144 _spifi = NULL;
embeddedartists 0:6b68dac0d986 145 return translateError(rc);
embeddedartists 0:6b68dac0d986 146 }
embeddedartists 0:6b68dac0d986 147
embeddedartists 0:6b68dac0d986 148 /* Make sure it is a tested flash module */
embeddedartists 0:6b68dac0d986 149 if ((_romData->mfger == 1) && (_romData->devType == 0x2) && (_romData->devID == 0x15) && (_romData->memSize > 0x100000))
embeddedartists 0:6b68dac0d986 150 {
embeddedartists 0:6b68dac0d986 151 _device = Spansion_S25FL032;
embeddedartists 0:6b68dac0d986 152 _memorySize = _romData->memSize;
embeddedartists 0:6b68dac0d986 153 _eraseBlockSize = 64*1024;
embeddedartists 0:6b68dac0d986 154 }
embeddedartists 0:6b68dac0d986 155 else if ((_romData->mfger == 0xef) && (_romData->devType == 0x40) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000))
embeddedartists 0:6b68dac0d986 156 {
embeddedartists 0:6b68dac0d986 157 _device = Winbond_W25Q64FV;
embeddedartists 0:6b68dac0d986 158 _memorySize = _romData->memSize;
embeddedartists 0:6b68dac0d986 159 _eraseBlockSize = 4*1024;
embeddedartists 0:6b68dac0d986 160 }
embeddedartists 0:6b68dac0d986 161 else if ((_romData->mfger == 0xc2) && (_romData->devType == 0x20) && (_romData->devID == 0x17) && (_romData->memSize > 0x100000))
embeddedartists 0:6b68dac0d986 162 {
embeddedartists 0:6b68dac0d986 163 _device = Macronix_MX25L6435EM2I;
embeddedartists 0:6b68dac0d986 164 _memorySize = _romData->memSize;
embeddedartists 0:6b68dac0d986 165 _eraseBlockSize = 4*1024;
embeddedartists 0:6b68dac0d986 166 }
embeddedartists 0:6b68dac0d986 167 else
embeddedartists 0:6b68dac0d986 168 {
embeddedartists 0:6b68dac0d986 169 debug("SPIFI::init(): Memory is unknown and may not work as expected\n");
embeddedartists 0:6b68dac0d986 170
embeddedartists 0:6b68dac0d986 171 // Asuming it has 64Kb erase blocks (i.e. same setup as the Spansion S25FL032
embeddedartists 0:6b68dac0d986 172 _device = UnknownDevice;
embeddedartists 0:6b68dac0d986 173 _memorySize = _romData->memSize;
embeddedartists 0:6b68dac0d986 174 _eraseBlockSize = 64*1024;
embeddedartists 0:6b68dac0d986 175
embeddedartists 0:6b68dac0d986 176 /*
embeddedartists 0:6b68dac0d986 177 * If this happens, check the manufacturer and device information
embeddedartists 0:6b68dac0d986 178 * and compare with the data sheet for your chip. Also make sure
embeddedartists 0:6b68dac0d986 179 * that the sector sizes are the same (i.e. 64KB) for your chip.
embeddedartists 0:6b68dac0d986 180 * If everything is the same then add an exception for your chip.
embeddedartists 0:6b68dac0d986 181 */
embeddedartists 0:6b68dac0d986 182 }
embeddedartists 0:6b68dac0d986 183
embeddedartists 0:6b68dac0d986 184 _initialized = true;
embeddedartists 0:6b68dac0d986 185 }
embeddedartists 0:6b68dac0d986 186 return Ok;
embeddedartists 0:6b68dac0d986 187 }
embeddedartists 0:6b68dac0d986 188
embeddedartists 0:6b68dac0d986 189 SPIFI::SpifiError SPIFI::program(uint32_t dest, unsigned len, char* src, Options options, bool verify, char* scratch)
embeddedartists 0:6b68dac0d986 190 {
embeddedartists 0:6b68dac0d986 191 unsigned written = 0;
embeddedartists 0:6b68dac0d986 192 SPIFIopers opers;
embeddedartists 0:6b68dac0d986 193 opers.dest = (char *)dest;
embeddedartists 0:6b68dac0d986 194 opers.length = SPIFI_MIN(len, PROG_SIZE);
embeddedartists 0:6b68dac0d986 195 opers.scratch = scratch;
embeddedartists 0:6b68dac0d986 196 opers.protect = 0;
embeddedartists 0:6b68dac0d986 197 opers.options = options;
embeddedartists 0:6b68dac0d986 198 if (verify) {
embeddedartists 0:6b68dac0d986 199 opers.options |= S_VERIFY_PROG;
embeddedartists 0:6b68dac0d986 200 }
embeddedartists 0:6b68dac0d986 201
embeddedartists 0:6b68dac0d986 202 if (IS_ADDR_IN_SPIFI(src))
embeddedartists 0:6b68dac0d986 203 {
embeddedartists 0:6b68dac0d986 204 // The SPIFI ROM driver cannot write data from SPIFI into
embeddedartists 0:6b68dac0d986 205 // SPIFI (i.e. cannot read and write at the same time).
embeddedartists 0:6b68dac0d986 206 // The workaround is to copy the source data into a buffer
embeddedartists 0:6b68dac0d986 207 // in local memory and use that as source for the write
embeddedartists 0:6b68dac0d986 208 // instead.
embeddedartists 0:6b68dac0d986 209 while (written < len) {
embeddedartists 0:6b68dac0d986 210 memcpy(_addrConflictBuff, src + written, opers.length);
embeddedartists 0:6b68dac0d986 211 int rc = _spifi->spifi_program(_romData, _addrConflictBuff, &opers);
embeddedartists 0:6b68dac0d986 212 if (rc)
embeddedartists 0:6b68dac0d986 213 {
embeddedartists 0:6b68dac0d986 214 // got an error
embeddedartists 0:6b68dac0d986 215 return translateError(rc, verify);
embeddedartists 0:6b68dac0d986 216 }
embeddedartists 0:6b68dac0d986 217 written += opers.length;
embeddedartists 0:6b68dac0d986 218 opers.dest += opers.length;
embeddedartists 0:6b68dac0d986 219 opers.length = SPIFI_MIN(len - written, PROG_SIZE);
embeddedartists 0:6b68dac0d986 220 }
embeddedartists 0:6b68dac0d986 221 }
embeddedartists 0:6b68dac0d986 222 else
embeddedartists 0:6b68dac0d986 223 {
embeddedartists 0:6b68dac0d986 224 while (written < len) {
embeddedartists 0:6b68dac0d986 225 int rc = _spifi->spifi_program(_romData, src + written, &opers);
embeddedartists 0:6b68dac0d986 226 if (rc)
embeddedartists 0:6b68dac0d986 227 {
embeddedartists 0:6b68dac0d986 228 // got an error
embeddedartists 0:6b68dac0d986 229 return translateError(rc, verify);
embeddedartists 0:6b68dac0d986 230 }
embeddedartists 0:6b68dac0d986 231 written += opers.length;
embeddedartists 0:6b68dac0d986 232 opers.dest += opers.length;
embeddedartists 0:6b68dac0d986 233 opers.length = SPIFI_MIN(len - written, PROG_SIZE);
embeddedartists 0:6b68dac0d986 234 }
embeddedartists 0:6b68dac0d986 235 }
embeddedartists 0:6b68dac0d986 236
embeddedartists 0:6b68dac0d986 237 return Ok;
embeddedartists 0:6b68dac0d986 238 }
embeddedartists 0:6b68dac0d986 239
embeddedartists 0:6b68dac0d986 240 SPIFI::SpifiError SPIFI::erase(uint32_t dest, unsigned len, char* src, bool verify, char* scratch)
embeddedartists 0:6b68dac0d986 241 {
embeddedartists 0:6b68dac0d986 242 SPIFIopers opers;
embeddedartists 0:6b68dac0d986 243 opers.dest = (char *)dest;
embeddedartists 0:6b68dac0d986 244 opers.length = len;
embeddedartists 0:6b68dac0d986 245 opers.scratch = scratch;
embeddedartists 0:6b68dac0d986 246 opers.protect = 0;
embeddedartists 0:6b68dac0d986 247 if (verify) {
embeddedartists 0:6b68dac0d986 248 opers.options = S_VERIFY_ERASE;
embeddedartists 0:6b68dac0d986 249 } else {
embeddedartists 0:6b68dac0d986 250 opers.options = S_NO_VERIFY;
embeddedartists 0:6b68dac0d986 251 }
embeddedartists 0:6b68dac0d986 252 int rc = _spifi->spifi_erase(_romData, &opers);
embeddedartists 0:6b68dac0d986 253 return translateError(rc);
embeddedartists 0:6b68dac0d986 254 }
embeddedartists 0:6b68dac0d986 255
embeddedartists 0:6b68dac0d986 256