Dependencies:   DM_FATFileSystem EthernetInterface HTTPClient mbed-rtos mbed-src

Fork of DMSupport by Embedded Artists

Committer:
embeddedartists
Date:
Wed Dec 03 16:17:10 2014 +0000
Revision:
3:2fa7755f2cef
Parent:
0:6b68dac0d986
Child:
9:a33326afd686
Corrected the SPIFI initialization so that it can run at max speed (i.e. 60MHz). Updated used libraries including the Keyboard, Mouse and Hub changes for USB Host.

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 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 0:6b68dac0d986 166 _device = Macronix_MX25L6435EM2I;
embeddedartists 0:6b68dac0d986 167 _memorySize = _romData->memSize;
embeddedartists 0:6b68dac0d986 168 _eraseBlockSize = 4*1024;
embeddedartists 0:6b68dac0d986 169 }
embeddedartists 0:6b68dac0d986 170 else
embeddedartists 0:6b68dac0d986 171 {
embeddedartists 0:6b68dac0d986 172 debug("SPIFI::init(): Memory is unknown and may not work as expected\n");
embeddedartists 0:6b68dac0d986 173
embeddedartists 0:6b68dac0d986 174 // Asuming it has 64Kb erase blocks (i.e. same setup as the Spansion S25FL032
embeddedartists 0:6b68dac0d986 175 _device = UnknownDevice;
embeddedartists 0:6b68dac0d986 176 _memorySize = _romData->memSize;
embeddedartists 0:6b68dac0d986 177 _eraseBlockSize = 64*1024;
embeddedartists 0:6b68dac0d986 178
embeddedartists 0:6b68dac0d986 179 /*
embeddedartists 0:6b68dac0d986 180 * If this happens, check the manufacturer and device information
embeddedartists 0:6b68dac0d986 181 * and compare with the data sheet for your chip. Also make sure
embeddedartists 0:6b68dac0d986 182 * that the sector sizes are the same (i.e. 64KB) for your chip.
embeddedartists 0:6b68dac0d986 183 * If everything is the same then add an exception for your chip.
embeddedartists 0:6b68dac0d986 184 */
embeddedartists 0:6b68dac0d986 185 }
embeddedartists 0:6b68dac0d986 186
embeddedartists 0:6b68dac0d986 187 _initialized = true;
embeddedartists 0:6b68dac0d986 188 }
embeddedartists 0:6b68dac0d986 189 return Ok;
embeddedartists 0:6b68dac0d986 190 }
embeddedartists 0:6b68dac0d986 191
embeddedartists 0:6b68dac0d986 192 SPIFI::SpifiError SPIFI::program(uint32_t dest, unsigned len, char* src, Options options, bool verify, char* scratch)
embeddedartists 0:6b68dac0d986 193 {
embeddedartists 0:6b68dac0d986 194 unsigned written = 0;
embeddedartists 0:6b68dac0d986 195 SPIFIopers opers;
embeddedartists 0:6b68dac0d986 196 opers.dest = (char *)dest;
embeddedartists 0:6b68dac0d986 197 opers.length = SPIFI_MIN(len, PROG_SIZE);
embeddedartists 0:6b68dac0d986 198 opers.scratch = scratch;
embeddedartists 0:6b68dac0d986 199 opers.protect = 0;
embeddedartists 0:6b68dac0d986 200 opers.options = options;
embeddedartists 0:6b68dac0d986 201 if (verify) {
embeddedartists 0:6b68dac0d986 202 opers.options |= S_VERIFY_PROG;
embeddedartists 0:6b68dac0d986 203 }
embeddedartists 0:6b68dac0d986 204
embeddedartists 0:6b68dac0d986 205 if (IS_ADDR_IN_SPIFI(src))
embeddedartists 0:6b68dac0d986 206 {
embeddedartists 0:6b68dac0d986 207 // The SPIFI ROM driver cannot write data from SPIFI into
embeddedartists 0:6b68dac0d986 208 // SPIFI (i.e. cannot read and write at the same time).
embeddedartists 0:6b68dac0d986 209 // The workaround is to copy the source data into a buffer
embeddedartists 0:6b68dac0d986 210 // in local memory and use that as source for the write
embeddedartists 0:6b68dac0d986 211 // instead.
embeddedartists 0:6b68dac0d986 212 while (written < len) {
embeddedartists 0:6b68dac0d986 213 memcpy(_addrConflictBuff, src + written, opers.length);
embeddedartists 0:6b68dac0d986 214 int rc = _spifi->spifi_program(_romData, _addrConflictBuff, &opers);
embeddedartists 0:6b68dac0d986 215 if (rc)
embeddedartists 0:6b68dac0d986 216 {
embeddedartists 0:6b68dac0d986 217 // got an error
embeddedartists 0:6b68dac0d986 218 return translateError(rc, verify);
embeddedartists 0:6b68dac0d986 219 }
embeddedartists 0:6b68dac0d986 220 written += opers.length;
embeddedartists 0:6b68dac0d986 221 opers.dest += opers.length;
embeddedartists 0:6b68dac0d986 222 opers.length = SPIFI_MIN(len - written, PROG_SIZE);
embeddedartists 0:6b68dac0d986 223 }
embeddedartists 0:6b68dac0d986 224 }
embeddedartists 0:6b68dac0d986 225 else
embeddedartists 0:6b68dac0d986 226 {
embeddedartists 0:6b68dac0d986 227 while (written < len) {
embeddedartists 0:6b68dac0d986 228 int rc = _spifi->spifi_program(_romData, src + written, &opers);
embeddedartists 0:6b68dac0d986 229 if (rc)
embeddedartists 0:6b68dac0d986 230 {
embeddedartists 0:6b68dac0d986 231 // got an error
embeddedartists 0:6b68dac0d986 232 return translateError(rc, verify);
embeddedartists 0:6b68dac0d986 233 }
embeddedartists 0:6b68dac0d986 234 written += opers.length;
embeddedartists 0:6b68dac0d986 235 opers.dest += opers.length;
embeddedartists 0:6b68dac0d986 236 opers.length = SPIFI_MIN(len - written, PROG_SIZE);
embeddedartists 0:6b68dac0d986 237 }
embeddedartists 0:6b68dac0d986 238 }
embeddedartists 0:6b68dac0d986 239
embeddedartists 0:6b68dac0d986 240 return Ok;
embeddedartists 0:6b68dac0d986 241 }
embeddedartists 0:6b68dac0d986 242
embeddedartists 0:6b68dac0d986 243 SPIFI::SpifiError SPIFI::erase(uint32_t dest, unsigned len, char* src, bool verify, char* scratch)
embeddedartists 0:6b68dac0d986 244 {
embeddedartists 0:6b68dac0d986 245 SPIFIopers opers;
embeddedartists 0:6b68dac0d986 246 opers.dest = (char *)dest;
embeddedartists 0:6b68dac0d986 247 opers.length = len;
embeddedartists 0:6b68dac0d986 248 opers.scratch = scratch;
embeddedartists 0:6b68dac0d986 249 opers.protect = 0;
embeddedartists 0:6b68dac0d986 250 if (verify) {
embeddedartists 0:6b68dac0d986 251 opers.options = S_VERIFY_ERASE;
embeddedartists 0:6b68dac0d986 252 } else {
embeddedartists 0:6b68dac0d986 253 opers.options = S_NO_VERIFY;
embeddedartists 0:6b68dac0d986 254 }
embeddedartists 0:6b68dac0d986 255 int rc = _spifi->spifi_erase(_romData, &opers);
embeddedartists 0:6b68dac0d986 256 return translateError(rc);
embeddedartists 0:6b68dac0d986 257 }
embeddedartists 0:6b68dac0d986 258
embeddedartists 0:6b68dac0d986 259