norflash.c
Go to the documentation of this file.00001
00038 #include "em_common.h"
00039 #include "em_ebi.h"
00040 #include "norflash.h"
00041
00044 static volatile uint16_t *flashBase;
00045 static bool flashInitialized = false;
00046 static NORFLASH_Info_TypeDef flashInfo;
00047
00048 static int flashInterrogate(void);
00049 static int flashPoll(uint32_t addr, uint16_t data);
00050 static void flashReset(void);
00051 static void flashUnlockCmd(void);
00052 static int flashWriteBuffer(uint32_t sectorAddr, uint32_t addr,
00053 uint16_t *data, uint32_t count);
00054
00057
00067 bool NORFLASH_AddressValid(uint32_t addr)
00068 {
00069 if (!flashInitialized)
00070 {
00071 if (flashInterrogate() != NORFLASH_STATUS_OK)
00072 return false;
00073 }
00074
00075 if ((addr >= flashInfo.baseAddress) &&
00076 (addr < (flashInfo.baseAddress + flashInfo.deviceSize)))
00077 return true;
00078
00079 return false;
00080 }
00081
00082
00092 NORFLASH_Info_TypeDef *NORFLASH_DeviceInfo(void)
00093 {
00094 if (!flashInitialized)
00095 {
00096 if (flashInterrogate() != NORFLASH_STATUS_OK)
00097 return NULL;
00098 }
00099
00100 return &flashInfo;
00101 }
00102
00103
00111 int NORFLASH_EraseDevice(void)
00112 {
00113 int status;
00114
00115 if (!flashInitialized)
00116 {
00117 status = flashInterrogate();
00118
00119 if (status != NORFLASH_STATUS_OK)
00120 return status;
00121 }
00122
00123 flashUnlockCmd();
00124
00125 flashBase[0x555] = 0x80;
00126 flashBase[0x555] = 0xAA;
00127 flashBase[0x2AA] = 0x55;
00128 flashBase[0x555] = 0x10;
00129
00130 return flashPoll(flashInfo.baseAddress, 0xFFFF);
00131 }
00132
00133
00144 int NORFLASH_EraseSector(uint32_t addr)
00145 {
00146 int status;
00147
00148 if (!flashInitialized)
00149 {
00150 status = flashInterrogate();
00151
00152 if (status != NORFLASH_STATUS_OK)
00153 return status;
00154 }
00155
00156 if (!NORFLASH_AddressValid(addr))
00157 {
00158 EFM_ASSERT(false);
00159 return NORFLASH_INVALID_ADDRESS;
00160 }
00161
00162
00163 addr = addr & ~(flashInfo.sectorSize - 1);
00164
00165 flashUnlockCmd();
00166
00167 flashBase[0x555] = 0x80;
00168 flashBase[0x555] = 0xAA;
00169 flashBase[0x2AA] = 0x55;
00170
00171 *(volatile uint16_t*) addr = 0x30;
00172
00173 return flashPoll(addr, 0xFFFF);
00174 }
00175
00176
00188 int NORFLASH_Init(void)
00189 {
00190 return flashInterrogate();
00191 }
00192
00193
00213 int NORFLASH_Program(uint32_t addr, uint8_t *data, uint32_t count)
00214 {
00215 int status;
00216 uint32_t sectorAddress, burst;
00217
00218 if (!flashInitialized)
00219 {
00220 status = flashInterrogate();
00221
00222 if (status != NORFLASH_STATUS_OK)
00223 return status;
00224 }
00225
00226 if (!NORFLASH_AddressValid(addr) ||
00227 !NORFLASH_AddressValid(addr + count - 1))
00228 {
00229 EFM_ASSERT(false);
00230 return NORFLASH_INVALID_ADDRESS;
00231 }
00232
00233
00234 if (addr & 1)
00235 {
00236 status = NORFLASH_ProgramByte(addr, *data);
00237
00238 if (status != NORFLASH_STATUS_OK)
00239 return status;
00240
00241 addr++;
00242 data++;
00243 count--;
00244 }
00245
00246 while (count >= 2)
00247 {
00248 #if 0
00249 status = NORFLASH_ProgramWord16(addr, (*(data + 1) << 8) | *data);
00250
00251 if (status != NORFLASH_STATUS_OK)
00252 return status;
00253
00254 addr += 2;
00255 data += 2;
00256 count -= 2;
00257
00258 #else
00259 sectorAddress = addr & ~(flashInfo.sectorSize - 1);
00260
00261
00262 burst = EFM32_MIN(64U, sectorAddress + flashInfo.sectorSize - addr);
00263 burst = EFM32_MIN(burst, count & 0xFFFFFFFE);
00264
00265 status = flashWriteBuffer(sectorAddress, addr, (uint16_t*) data, burst);
00266
00267 if (status != NORFLASH_STATUS_OK)
00268 return status;
00269
00270 addr += burst;
00271 data += burst;
00272 count -= burst;
00273 #endif
00274
00275 }
00276
00277
00278 if (count)
00279 {
00280 status = NORFLASH_ProgramByte(addr, *data);
00281 }
00282
00283 return status;
00284 }
00285
00286
00303 int NORFLASH_ProgramByte(uint32_t addr, uint8_t data)
00304 {
00305 uint16_t tmp;
00306
00307 tmp = *(volatile uint16_t*)(addr & 0xFFFFFFFE);
00308 if (addr & 1)
00309 {
00310 tmp = (tmp & 0xFF) | (data << 8);
00311 }
00312 else
00313 {
00314 tmp = (tmp & 0xFF00) | data;
00315 }
00316
00317 return NORFLASH_ProgramWord16(addr & 0xFFFFFFFE, tmp);
00318 }
00319
00320
00337 int NORFLASH_ProgramWord16(uint32_t addr, uint16_t data)
00338 {
00339 int status;
00340
00341 if (!flashInitialized)
00342 {
00343 status = flashInterrogate();
00344
00345 if (status != NORFLASH_STATUS_OK)
00346 return status;
00347 }
00348
00349 if (!NORFLASH_AddressValid(addr) ||
00350 !NORFLASH_AddressValid(addr + 1))
00351 {
00352 EFM_ASSERT(false);
00353 return NORFLASH_INVALID_ADDRESS;
00354 }
00355
00356 if (addr & 1)
00357 return NORFLASH_MISALIGNED_ADDRESS;
00358
00359 flashUnlockCmd();
00360 flashBase[0x555] = 0xA0;
00361
00362 *(volatile uint16_t*) addr = data;
00363
00364 return flashPoll(addr, data);
00365 }
00366
00367
00384 int NORFLASH_ProgramWord32(uint32_t addr, uint32_t data)
00385 {
00386 int status;
00387
00388 if (addr & 3)
00389 return NORFLASH_MISALIGNED_ADDRESS;
00390
00391 status = NORFLASH_ProgramWord16(addr, data & 0xFFFF);
00392
00393 if (status == NORFLASH_STATUS_OK)
00394 {
00395 addr += 2;
00396 status = NORFLASH_ProgramWord16(addr, data >> 16);
00397 }
00398
00399 return status;
00400 }
00401
00404
00413 static int flashInterrogate(void)
00414 {
00415 flashInfo.baseAddress = EBI_BankAddress(EBI_BANK3);
00416 flashBase = (volatile uint16_t*) flashInfo.baseAddress;
00417
00418 flashReset();
00419
00420 flashUnlockCmd();
00421 flashBase[0x555] = 0x90;
00422
00423
00424 flashInfo.manufacturerId = flashBase[0x00];
00425 flashInfo.deviceId = (flashBase[0x01] & 0xFF) << 16;
00426 flashInfo.deviceId |= (flashBase[0x0E] & 0xFF) << 8;
00427 flashInfo.deviceId |= flashBase[0x0F] & 0xFF;
00428
00429 flashReset();
00430
00431 flashBase[0x55] = 0x98;
00432
00433
00434 if ((flashBase[0x10] != 'Q') ||
00435 (flashBase[0x11] != 'R') ||
00436 (flashBase[0x12] != 'Y'))
00437 {
00438 flashReset();
00439 return NORFLASH_NOT_CFI_DEVICE;
00440 }
00441
00442
00443 if (flashBase[0x2C] != 1)
00444 {
00445 flashReset();
00446 return NORFLASH_NONUNIFORM_GEOMETRY;
00447 }
00448
00449 flashInfo.deviceSize = flashBase[0x27];
00450 flashInfo.deviceSize = 1 << flashInfo.deviceSize;
00451 flashInfo.sectorCount = flashBase[0x2D];
00452 flashInfo.sectorCount |= (flashBase[0x2E] << 8) & 0xFF00;
00453 flashInfo.sectorSize = flashBase[0x2F];
00454 flashInfo.sectorSize |= (flashBase[0x30] << 8) & 0xFF00;
00455
00456 flashInfo.sectorCount += 1;
00457 flashInfo.sectorSize *= 256;
00458
00459 flashReset();
00460
00461 flashInitialized = true;
00462
00463 return NORFLASH_STATUS_OK;
00464 }
00465
00466
00487 static int flashPoll(uint32_t addr, uint16_t data)
00488 {
00489 #define TOGGLE_BIT 0x40
00490 #define TIMEOUT_BIT 0x20
00491
00492 int i = 0;
00493 uint16_t flashData1, flashData2, flashData3;
00494
00495 if ((flashData1 = *(volatile uint16_t*) addr) == data)
00496 return NORFLASH_STATUS_OK;
00497
00498 if ((flashData2 = *(volatile uint16_t*) addr) == data)
00499 return NORFLASH_STATUS_OK;
00500
00501 while (1)
00502 {
00503 if ((flashData3 = *(volatile uint16_t*) addr) == data)
00504 return NORFLASH_STATUS_OK;
00505
00506 if ((((flashData1 ^ flashData2) & TOGGLE_BIT) == TOGGLE_BIT) &&
00507 (((flashData2 ^ flashData3) & TOGGLE_BIT) == TOGGLE_BIT) &&
00508 ((flashData1 & TIMEOUT_BIT) == TIMEOUT_BIT))
00509 {
00510
00511 flashReset();
00512 return NORFLASH_WRITE_TIMEOUT;
00513 }
00514
00515 if ((((flashData1 ^ flashData2) & TOGGLE_BIT) != TOGGLE_BIT) ||
00516 (((flashData2 ^ flashData3) & TOGGLE_BIT) != TOGGLE_BIT))
00517 {
00518
00519 if (*(volatile uint16_t*) addr == data)
00520 return NORFLASH_STATUS_OK;
00521
00522
00523 flashReset();
00524 return NORFLASH_WRITE_FAILURE;
00525 }
00526
00527 flashData1 = flashData2;
00528 flashData2 = flashData3;
00529 i++;
00530 }
00531 #undef TOGGLE_BIT
00532 #undef TIMEOUT_BIT
00533 }
00534
00535
00539 static void flashReset(void)
00540 {
00541 flashBase[0] = 0xF0;
00542 }
00543
00544
00548 static void flashUnlockCmd(void)
00549 {
00550 flashBase[0x555] = 0xAA;
00551 flashBase[0x2AA] = 0x55;
00552 }
00553
00554
00574 static int flashWriteBuffer(uint32_t sectorAddr,
00575 uint32_t addr,
00576 uint16_t *data,
00577 uint32_t count)
00578 {
00579 uint32_t i;
00580 volatile uint16_t *pDst;
00581
00582 pDst = (volatile uint16_t*) addr;
00583 count = (count / 2) - 1;
00584
00585 flashUnlockCmd();
00586 *(volatile uint16_t*) sectorAddr = 0x25;
00587 *(volatile uint16_t*) sectorAddr = count;
00588 for (i = 0; i <= count; i++)
00589 {
00590 *pDst++ = *data++;
00591 }
00592 *(volatile uint16_t*) sectorAddr = 0x29;
00593
00594 pDst--;
00595 data--;
00596 return flashPoll((uint32_t) pDst, *data);
00597 }
00598