00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #include "chip.h"
00085
00086 #include <string.h>
00087 #include <assert.h>
00088
00089
00090
00091
00092
00093 #define GPNVM_NUM_MAX 9
00094
00095
00096
00097
00098
00099 static uint32_t _pdwPageBuffer[IFLASH_PAGE_SIZE / sizeof(uint32_t)];
00100 static uint32_t _dwUseIAP = 1;
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 static void ComputeLockRange(uint32_t dwStart, uint32_t dwEnd,
00117 uint32_t *pdwActualStart, uint32_t *pdwActualEnd)
00118 {
00119 Efc *pStartEfc;
00120 Efc *pEndEfc;
00121 uint16_t wStartPage;
00122 uint16_t wEndPage;
00123 uint16_t wNumPagesInRegion;
00124 uint16_t wActualStartPage;
00125 uint16_t wActualEndPage;
00126
00127
00128 EFC_TranslateAddress(&pStartEfc, dwStart, &wStartPage, 0);
00129 EFC_TranslateAddress(&pEndEfc, dwEnd, &wEndPage, 0);
00130
00131
00132 wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00133 wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion);
00134 wActualEndPage = wEndPage;
00135
00136 if ((wEndPage % wNumPagesInRegion) != 0)
00137 wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion);
00138
00139
00140 EFC_ComputeAddress(pStartEfc, wActualStartPage, 0, pdwActualStart);
00141 EFC_ComputeAddress(pEndEfc, wActualEndPage, 0, pdwActualEnd);
00142 TRACE_DEBUG("Actual lock range is 0x%06X - 0x%06X\n\r",
00143 (unsigned int)*pdwActualStart, (unsigned int)*pdwActualEnd);
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 extern void FLASHD_Initialize(uint32_t dwMCk, uint32_t dwUseIAP)
00160 {
00161 dwMCk = dwMCk;
00162
00163 EFC_DisableFrdyIt(EFC);
00164 _dwUseIAP = dwUseIAP;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 extern uint32_t FLASHD_Erase(uint32_t dwAddress)
00174 {
00175 Efc *pEfc;
00176 uint16_t wPage;
00177 uint16_t wOffset;
00178 uint32_t dwError;
00179
00180 assert((dwAddress >= IFLASH_ADDR)
00181 || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)));
00182
00183
00184 EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset);
00185 dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EA, 0, _dwUseIAP);
00186
00187 return dwError;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197 extern uint32_t FLASHD_EraseSector(uint32_t dwAddress)
00198 {
00199 Efc *pEfc;
00200 uint16_t wPage;
00201 uint16_t wOffset;
00202 uint32_t dwError;
00203
00204 assert((dwAddress >= IFLASH_ADDR)
00205 || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)));
00206
00207
00208 EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset);
00209 dwError = EFC_PerformCommand(pEfc, EFC_FCMD_ES, wPage, _dwUseIAP);
00210
00211 return dwError;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 extern uint32_t FLASHD_ErasePages(uint32_t dwAddress, uint32_t dwPageNum)
00223 {
00224 Efc *pEfc;
00225 uint16_t wPage;
00226 uint16_t wOffset;
00227 uint32_t dwError;
00228 static uint32_t dwFarg;
00229
00230 assert((dwAddress >= IFLASH_ADDR)
00231 || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)));
00232
00233
00234 EFC_TranslateAddress(&pEfc, dwAddress, &wPage, &wOffset);
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 if (dwPageNum == 32) {
00245 wPage &= ~(32u - 1u);
00246 dwFarg = (wPage) | 3;
00247 } else if (dwPageNum == 16) {
00248 wPage &= ~(16u - 1u);
00249 dwFarg = (wPage) | 2;
00250 } else if (dwPageNum == 8) {
00251 wPage &= ~(8u - 1u);
00252 dwFarg = (wPage) | 1;
00253 } else {
00254 wPage &= ~(4u - 1u);
00255 dwFarg = (wPage) | 0;
00256 }
00257
00258 dwError = EFC_PerformCommand(pEfc, EFC_FCMD_EPA, dwFarg, _dwUseIAP);
00259
00260 return dwError;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 extern uint32_t FLASHD_Write(uint32_t dwAddress,
00275 const void *pvBuffer, uint32_t dwSize)
00276 {
00277 Efc *pEfc;
00278 uint16_t page;
00279 uint16_t offset;
00280 uint32_t writeSize;
00281 uint32_t pageAddress;
00282 uint16_t padding;
00283 uint32_t dwError;
00284 uint32_t dwIdx;
00285 uint32_t *pAlignedDestination;
00286 uint8_t *pucPageBuffer = (uint8_t *)_pdwPageBuffer;
00287
00288 assert(pvBuffer);
00289 assert(dwAddress >= IFLASH_ADDR);
00290 assert((dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE));
00291
00292
00293 EFC_TranslateAddress(&pEfc, dwAddress, &page, &offset);
00294
00295
00296 while (dwSize > 0) {
00297
00298 writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize);
00299 EFC_ComputeAddress(pEfc, page, 0, &pageAddress);
00300 padding = IFLASH_PAGE_SIZE - offset - writeSize;
00301
00302
00303 memcpy(pucPageBuffer, (void *) pageAddress, offset);
00304
00305
00306 memcpy(pucPageBuffer + offset, pvBuffer, writeSize);
00307
00308
00309 memcpy(pucPageBuffer + offset + writeSize,
00310 (void *) (pageAddress + offset + writeSize), padding);
00311
00312
00313
00314
00315
00316 pAlignedDestination = (uint32_t *)pageAddress;
00317
00318 for (dwIdx = 0; dwIdx < (IFLASH_PAGE_SIZE / sizeof(uint32_t)); ++ dwIdx) {
00319 *pAlignedDestination++ = _pdwPageBuffer[dwIdx];
00320 memory_barrier()
00321 }
00322
00323
00324 SCB_CleanDCache_by_Addr((uint32_t *)pageAddress, IFLASH_PAGE_SIZE);
00325
00326
00327
00328
00329
00330
00331 dwError = EFC_PerformCommand(pEfc, EFC_FCMD_WP, page, _dwUseIAP);
00332
00333 if (dwError)
00334 return dwError;
00335
00336
00337 pvBuffer = (void *)((uint32_t) pvBuffer + writeSize);
00338 dwSize -= writeSize;
00339 page++;
00340 offset = 0;
00341 }
00342
00343 return 0;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 extern uint32_t FLASHD_Lock(uint32_t start, uint32_t end,
00357 uint32_t *pActualStart, uint32_t *pActualEnd)
00358 {
00359 Efc *pEfc;
00360 uint32_t actualStart, actualEnd;
00361 uint16_t startPage, endPage;
00362 uint32_t dwError;
00363 uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00364
00365
00366 ComputeLockRange(start, end, &actualStart, &actualEnd);
00367
00368 if (pActualStart != NULL)
00369 *pActualStart = actualStart;
00370
00371 if (pActualEnd != NULL)
00372 *pActualEnd = actualEnd;
00373
00374
00375 EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0);
00376 EFC_TranslateAddress(0, actualEnd, &endPage, 0);
00377
00378
00379 while (startPage < endPage) {
00380 dwError = EFC_PerformCommand(pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP);
00381
00382 if (dwError)
00383 return dwError;
00384
00385 startPage += numPagesInRegion;
00386 }
00387
00388 return 0;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 extern uint32_t FLASHD_Unlock(uint32_t start, uint32_t end,
00401 uint32_t *pActualStart, uint32_t *pActualEnd)
00402 {
00403 Efc *pEfc;
00404 uint32_t actualStart, actualEnd;
00405 uint16_t startPage, endPage;
00406 uint32_t dwError;
00407 uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00408
00409
00410 ComputeLockRange(start, end, &actualStart, &actualEnd);
00411
00412 if (pActualStart != NULL)
00413 *pActualStart = actualStart;
00414
00415 if (pActualEnd != NULL)
00416 *pActualEnd = actualEnd;
00417
00418
00419 EFC_TranslateAddress(&pEfc, actualStart, &startPage, 0);
00420 EFC_TranslateAddress(0, actualEnd, &endPage, 0);
00421
00422
00423 while (startPage < endPage) {
00424 dwError = EFC_PerformCommand(pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP);
00425
00426 if (dwError)
00427 return dwError;
00428
00429 startPage += numPagesInRegion;
00430 }
00431
00432 return 0;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441 extern uint32_t FLASHD_IsLocked(uint32_t start, uint32_t end)
00442 {
00443 uint32_t i, j;
00444 Efc *pEfc;
00445 uint16_t startPage, endPage;
00446 uint8_t startRegion, endRegion;
00447 uint32_t numPagesInRegion;
00448 uint32_t status[IFLASH_NB_OF_LOCK_BITS / 32u];
00449 uint32_t numLockedRegions = 0;
00450
00451 assert(end >= start);
00452 assert((start >= IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE));
00453
00454
00455 EFC_TranslateAddress(&pEfc, start, &startPage, 0);
00456 EFC_TranslateAddress(0, end, &endPage, 0);
00457
00458
00459 numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE;
00460 startRegion = startPage / numPagesInRegion;
00461 endRegion = endPage / numPagesInRegion;
00462
00463 if ((endPage % numPagesInRegion) != 0)
00464 endRegion++;
00465
00466
00467 EFC_PerformCommand(pEfc, EFC_FCMD_GLB, 0, _dwUseIAP);
00468
00469 for (i = 0; i < (IFLASH_NB_OF_LOCK_BITS / 32u); i++)
00470 status[i] = EFC_GetResult(pEfc);
00471
00472
00473 while (startRegion < endRegion) {
00474 i = startRegion / 32u;
00475 j = startRegion % 32u;
00476
00477 if ((status[i] & (1 << j)) != 0)
00478 numLockedRegions++;
00479
00480 startRegion++;
00481 }
00482
00483 return numLockedRegions;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492 extern uint32_t FLASHD_IsGPNVMSet(uint8_t ucGPNVM)
00493 {
00494 uint32_t dwStatus;
00495
00496 assert(ucGPNVM < GPNVM_NUM_MAX);
00497
00498
00499 EFC_PerformCommand(EFC, EFC_FCMD_GFB, 0, _dwUseIAP);
00500 dwStatus = EFC_GetResult(EFC);
00501
00502
00503 if ((dwStatus & (1 << ucGPNVM)) != 0)
00504 return 1;
00505 else
00506 return 0;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 extern uint32_t FLASHD_SetGPNVM(uint8_t ucGPNVM)
00516 {
00517 assert(ucGPNVM < GPNVM_NUM_MAX);
00518
00519 if (!FLASHD_IsGPNVMSet(ucGPNVM))
00520 return EFC_PerformCommand(EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP);
00521 else
00522 return 0;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531 extern uint32_t FLASHD_ClearGPNVM(uint8_t ucGPNVM)
00532 {
00533 assert(ucGPNVM < GPNVM_NUM_MAX);
00534
00535 if (FLASHD_IsGPNVMSet(ucGPNVM))
00536 return EFC_PerformCommand(EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP);
00537 else
00538 return 0;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547 #ifdef __ICCARM__
00548 extern __ramfunc uint32_t FLASHD_ReadUniqueID(uint32_t *pdwUniqueID)
00549 #else
00550 __attribute__ ((section (".ramfunc")))
00551 uint32_t FLASHD_ReadUniqueID(uint32_t *pdwUniqueID)
00552 #endif
00553 {
00554 uint32_t status;
00555
00556 if (pdwUniqueID == NULL)
00557 return 1;
00558
00559 pdwUniqueID[0] = 0;
00560 pdwUniqueID[1] = 0;
00561 pdwUniqueID[2] = 0;
00562 pdwUniqueID[3] = 0;
00563
00564
00565
00566 EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EFC_FCMD_STUI;
00567
00568
00569
00570 do {
00571 status = EFC->EEFC_FSR;
00572 } while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
00573
00574
00575
00576 pdwUniqueID[0] = *(uint32_t *)IFLASH_ADDR;
00577 pdwUniqueID[1] = *(uint32_t *)(IFLASH_ADDR + 4);
00578 pdwUniqueID[2] = *(uint32_t *)(IFLASH_ADDR + 8);
00579 pdwUniqueID[3] = *(uint32_t *)(IFLASH_ADDR + 12);
00580
00581
00582
00583
00584 EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EFC_FCMD_SPUI;
00585
00586
00587
00588
00589 do {
00590 status = EFC->EEFC_FSR;
00591 } while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
00592
00593 return 0;
00594 }
00595