norflash.c
Go to the documentation of this file.00001
00020 #include "em_common.h"
00021 #include "em_ebi.h"
00022 #include "norflash.h"
00023
00026 static volatile uint16_t *flashBase;
00027 static bool flashInitialized = false;
00028 static NORFLASH_Info_TypeDef flashInfo;
00029
00030 static int flashInterrogate(void);
00031 static int flashPoll(uint32_t addr, uint16_t data);
00032 static void flashReset(void);
00033 static void flashUnlockCmd(void);
00034 static int flashWriteBuffer(uint32_t sectorAddr, uint32_t addr,
00035 uint16_t *data, uint32_t count);
00036
00039
00049 bool NORFLASH_AddressValid(uint32_t addr)
00050 {
00051 if (!flashInitialized)
00052 {
00053 if (flashInterrogate() != NORFLASH_STATUS_OK)
00054 return false;
00055 }
00056
00057 if ((addr >= flashInfo.baseAddress) &&
00058 (addr < (flashInfo.baseAddress + flashInfo.deviceSize)))
00059 return true;
00060
00061 return false;
00062 }
00063
00064
00074 NORFLASH_Info_TypeDef *NORFLASH_DeviceInfo(void)
00075 {
00076 if (!flashInitialized)
00077 {
00078 if (flashInterrogate() != NORFLASH_STATUS_OK)
00079 return NULL;
00080 }
00081
00082 return &flashInfo;
00083 }
00084
00085
00093 int NORFLASH_EraseDevice(void)
00094 {
00095 int status;
00096
00097 if (!flashInitialized)
00098 {
00099 status = flashInterrogate();
00100
00101 if (status != NORFLASH_STATUS_OK)
00102 return status;
00103 }
00104
00105 flashUnlockCmd();
00106
00107 flashBase[0x555] = 0x80;
00108 flashBase[0x555] = 0xAA;
00109 flashBase[0x2AA] = 0x55;
00110 flashBase[0x555] = 0x10;
00111
00112 return flashPoll(flashInfo.baseAddress, 0xFFFF);
00113 }
00114
00115
00126 int NORFLASH_EraseSector(uint32_t addr)
00127 {
00128 int status;
00129
00130 if (!flashInitialized)
00131 {
00132 status = flashInterrogate();
00133
00134 if (status != NORFLASH_STATUS_OK)
00135 return status;
00136 }
00137
00138 if (!NORFLASH_AddressValid(addr))
00139 {
00140 EFM_ASSERT(false);
00141 return NORFLASH_INVALID_ADDRESS;
00142 }
00143
00144
00145 addr = addr & ~(flashInfo.sectorSize - 1);
00146
00147 flashUnlockCmd();
00148
00149 flashBase[0x555] = 0x80;
00150 flashBase[0x555] = 0xAA;
00151 flashBase[0x2AA] = 0x55;
00152
00153 *(volatile uint16_t*) addr = 0x30;
00154
00155 return flashPoll(addr, 0xFFFF);
00156 }
00157
00158
00170 int NORFLASH_Init(void)
00171 {
00172 return flashInterrogate();
00173 }
00174
00175
00195 int NORFLASH_Program(uint32_t addr, uint8_t *data, uint32_t count)
00196 {
00197 int status;
00198 uint32_t sectorAddress, burst;
00199
00200 if (!flashInitialized)
00201 {
00202 status = flashInterrogate();
00203
00204 if (status != NORFLASH_STATUS_OK)
00205 return status;
00206 }
00207
00208 if (!NORFLASH_AddressValid(addr) ||
00209 !NORFLASH_AddressValid(addr + count - 1))
00210 {
00211 EFM_ASSERT(false);
00212 return NORFLASH_INVALID_ADDRESS;
00213 }
00214
00215
00216 if (addr & 1)
00217 {
00218 status = NORFLASH_ProgramByte(addr, *data);
00219
00220 if (status != NORFLASH_STATUS_OK)
00221 return status;
00222
00223 addr++;
00224 data++;
00225 count--;
00226 }
00227
00228 while (count >= 2)
00229 {
00230 #if 0
00231 status = NORFLASH_ProgramWord16(addr, (*(data + 1) << 8) | *data);
00232
00233 if (status != NORFLASH_STATUS_OK)
00234 return status;
00235
00236 addr += 2;
00237 data += 2;
00238 count -= 2;
00239
00240 #else
00241 sectorAddress = addr & ~(flashInfo.sectorSize - 1);
00242
00243
00244 burst = EFM32_MIN(64U, sectorAddress + flashInfo.sectorSize - addr);
00245 burst = EFM32_MIN(burst, count & 0xFFFFFFFE);
00246
00247 status = flashWriteBuffer(sectorAddress, addr, (uint16_t*) data, burst);
00248
00249 if (status != NORFLASH_STATUS_OK)
00250 return status;
00251
00252 addr += burst;
00253 data += burst;
00254 count -= burst;
00255 #endif
00256
00257 }
00258
00259
00260 if (count)
00261 {
00262 status = NORFLASH_ProgramByte(addr, *data);
00263 }
00264
00265 return status;
00266 }
00267
00268
00285 int NORFLASH_ProgramByte(uint32_t addr, uint8_t data)
00286 {
00287 uint16_t tmp;
00288
00289 tmp = *(volatile uint16_t*)(addr & 0xFFFFFFFE);
00290 if (addr & 1)
00291 {
00292 tmp = (tmp & 0xFF) | (data << 8);
00293 }
00294 else
00295 {
00296 tmp = (tmp & 0xFF00) | data;
00297 }
00298
00299 return NORFLASH_ProgramWord16(addr & 0xFFFFFFFE, tmp);
00300 }
00301
00302
00319 int NORFLASH_ProgramWord16(uint32_t addr, uint16_t data)
00320 {
00321 int status;
00322
00323 if (!flashInitialized)
00324 {
00325 status = flashInterrogate();
00326
00327 if (status != NORFLASH_STATUS_OK)
00328 return status;
00329 }
00330
00331 if (!NORFLASH_AddressValid(addr) ||
00332 !NORFLASH_AddressValid(addr + 1))
00333 {
00334 EFM_ASSERT(false);
00335 return NORFLASH_INVALID_ADDRESS;
00336 }
00337
00338 if (addr & 1)
00339 return NORFLASH_MISALIGNED_ADDRESS;
00340
00341 flashUnlockCmd();
00342 flashBase[0x555] = 0xA0;
00343
00344 *(volatile uint16_t*) addr = data;
00345
00346 return flashPoll(addr, data);
00347 }
00348
00349
00366 int NORFLASH_ProgramWord32(uint32_t addr, uint32_t data)
00367 {
00368 int status;
00369
00370 if (addr & 3)
00371 return NORFLASH_MISALIGNED_ADDRESS;
00372
00373 status = NORFLASH_ProgramWord16(addr, data & 0xFFFF);
00374
00375 if (status == NORFLASH_STATUS_OK)
00376 {
00377 addr += 2;
00378 status = NORFLASH_ProgramWord16(addr, data >> 16);
00379 }
00380
00381 return status;
00382 }
00383
00386
00395 static int flashInterrogate(void)
00396 {
00397 flashInfo.baseAddress = EBI_BankAddress(EBI_BANK3);
00398 flashBase = (volatile uint16_t*) flashInfo.baseAddress;
00399
00400 flashReset();
00401
00402 flashUnlockCmd();
00403 flashBase[0x555] = 0x90;
00404
00405
00406 flashInfo.manufacturerId = flashBase[0x00];
00407 flashInfo.deviceId = (flashBase[0x01] & 0xFF) << 16;
00408 flashInfo.deviceId |= (flashBase[0x0E] & 0xFF) << 8;
00409 flashInfo.deviceId |= flashBase[0x0F] & 0xFF;
00410
00411 flashReset();
00412
00413 flashBase[0x55] = 0x98;
00414
00415
00416 if ((flashBase[0x10] != 'Q') ||
00417 (flashBase[0x11] != 'R') ||
00418 (flashBase[0x12] != 'Y'))
00419 {
00420 flashReset();
00421 return NORFLASH_NOT_CFI_DEVICE;
00422 }
00423
00424
00425 if (flashBase[0x2C] != 1)
00426 {
00427 flashReset();
00428 return NORFLASH_NONUNIFORM_GEOMETRY;
00429 }
00430
00431 flashInfo.deviceSize = flashBase[0x27];
00432 flashInfo.deviceSize = 1 << flashInfo.deviceSize;
00433 flashInfo.sectorCount = flashBase[0x2D];
00434 flashInfo.sectorCount |= (flashBase[0x2E] << 8) & 0xFF00;
00435 flashInfo.sectorSize = flashBase[0x2F];
00436 flashInfo.sectorSize |= (flashBase[0x30] << 8) & 0xFF00;
00437
00438 flashInfo.sectorCount += 1;
00439 flashInfo.sectorSize *= 256;
00440
00441 flashReset();
00442
00443 flashInitialized = true;
00444
00445 return NORFLASH_STATUS_OK;
00446 }
00447
00448
00469 static int flashPoll(uint32_t addr, uint16_t data)
00470 {
00471 #define TOGGLE_BIT 0x40
00472 #define TIMEOUT_BIT 0x20
00473
00474 int i = 0;
00475 uint16_t flashData1, flashData2, flashData3;
00476
00477 if ((flashData1 = *(volatile uint16_t*) addr) == data)
00478 return NORFLASH_STATUS_OK;
00479
00480 if ((flashData2 = *(volatile uint16_t*) addr) == data)
00481 return NORFLASH_STATUS_OK;
00482
00483 while (1)
00484 {
00485 if ((flashData3 = *(volatile uint16_t*) addr) == data)
00486 return NORFLASH_STATUS_OK;
00487
00488 if ((((flashData1 ^ flashData2) & TOGGLE_BIT) == TOGGLE_BIT) &&
00489 (((flashData2 ^ flashData3) & TOGGLE_BIT) == TOGGLE_BIT) &&
00490 ((flashData1 & TIMEOUT_BIT) == TIMEOUT_BIT))
00491 {
00492
00493 flashReset();
00494 return NORFLASH_WRITE_TIMEOUT;
00495 }
00496
00497 if ((((flashData1 ^ flashData2) & TOGGLE_BIT) != TOGGLE_BIT) ||
00498 (((flashData2 ^ flashData3) & TOGGLE_BIT) != TOGGLE_BIT))
00499 {
00500
00501 if (*(volatile uint16_t*) addr == data)
00502 return NORFLASH_STATUS_OK;
00503
00504
00505 flashReset();
00506 return NORFLASH_WRITE_FAILURE;
00507 }
00508
00509 flashData1 = flashData2;
00510 flashData2 = flashData3;
00511 i++;
00512 }
00513 #undef TOGGLE_BIT
00514 #undef TIMEOUT_BIT
00515 }
00516
00517
00521 static void flashReset(void)
00522 {
00523 flashBase[0] = 0xF0;
00524 }
00525
00526
00530 static void flashUnlockCmd(void)
00531 {
00532 flashBase[0x555] = 0xAA;
00533 flashBase[0x2AA] = 0x55;
00534 }
00535
00536
00556 static int flashWriteBuffer(uint32_t sectorAddr,
00557 uint32_t addr,
00558 uint16_t *data,
00559 uint32_t count)
00560 {
00561 uint32_t i;
00562 volatile uint16_t *pDst;
00563
00564 pDst = (volatile uint16_t*) addr;
00565 count = (count / 2) - 1;
00566
00567 flashUnlockCmd();
00568 *(volatile uint16_t*) sectorAddr = 0x25;
00569 *(volatile uint16_t*) sectorAddr = count;
00570 for (i = 0; i <= count; i++)
00571 {
00572 *pDst++ = *data++;
00573 }
00574 *(volatile uint16_t*) sectorAddr = 0x29;
00575
00576 pDst--;
00577 data--;
00578 return flashPoll((uint32_t) pDst, *data);
00579 }
00580