mbed support for LPC4088 Display Module

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos mbed-src

Dependents:   emptyProgram

Fork of DMSupport by Embedded Artists

Committer:
redbird
Date:
Sat Mar 26 22:50:45 2016 +0000
Revision:
48:2f574ffa8b96
Parent:
37:07659b5d90ce
changed pin names to make more sense

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