28 #define NVM_VERSION 0x3U
31 #define NVM_CONTENT_SIZE (NVM_PAGE_SIZE - (NVM_HEADER_SIZE + NVM_FOOTER_SIZE))
32 #define NVM_WEAR_CONTENT_SIZE (NVM_PAGE_SIZE - NVM_HEADER_SIZE)
34 #define NVM_PAGE_EMPTY_VALUE 0xffffU
35 #define NVM_NO_PAGE_RETURNED 0xffffffffUL
36 #define NVM_NO_WRITE_16BIT 0xffffU
37 #define NVM_NO_WRITE_32BIT 0xffffffffUL
38 #define NVM_HIGHEST_32BIT 0xffffffffUL
39 #define NVM_FLIP_FIRST_BIT_OF_32_WHEN_WRITE 0xffff7fffUL
40 #define NVM_FIRST_BIT_ONE 0x8000U
41 #define NVM_FIRST_BIT_ZERO 0x7fffU
42 #define NVM_LAST_BIT_ZERO 0xfffeU
44 #define NVM_CHECKSUM_INITIAL 0xffffU
45 #define NVM_CHECKSUM_LENGTH 0x2U
47 #define NVM_PAGES_PER_WEAR_HISTORY 0x8U
52 #ifndef NVM_ACQUIRE_WRITE_LOCK
53 #define NVM_ACQUIRE_WRITE_LOCK
56 #ifndef NVM_RELEASE_WRITE_LOCK
57 #define NVM_RELEASE_WRITE_LOCK
70 nvmValidateResultOk = 0,
71 nvmValidateResultOkMarked = 1,
72 nvmValidateResultOld = 2,
73 nvmValidateResultError = 3
74 } NVM_ValidateResult_t;
86 #define NVM_HEADER_SIZE (sizeof(NVM_Page_Header_t))
97 #define NVM_FOOTER_SIZE (sizeof(NVM_Page_Footer_t))
108 static NVM_Config_t
const *nvmConfig;
110 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
115 static uint8_t nvmStaticWearWriteHistory[(NVM_MAX_NUMBER_OF_PAGES + (NVM_PAGES_PER_WEAR_HISTORY - 1)) / NVM_PAGES_PER_WEAR_HISTORY];
118 static uint16_t nvmStaticWearWritesInHistory;
121 static uint16_t nvmStaticWearErasesSinceReset;
124 static bool nvmStaticWearWorking =
false;
135 static uint8_t* NVM_PagePhysicalAddressGet(uint16_t pageId);
136 static uint8_t* NVM_ScratchPageFindBest(
void);
137 static Ecode_t NVM_PageErase(uint8_t *pPhysicalAddress);
138 static NVM_Page_Descriptor_t NVM_PageDescriptorGet(uint16_t pageId);
139 static NVM_ValidateResult_t NVM_PageValidate(uint8_t *pPhysicalAddress);
141 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
142 static uint16_t NVM_WearIndex(uint8_t *pPhysicalAddress, NVM_Page_Descriptor_t *pPageDesc);
143 static bool NVM_WearReadIndex(uint8_t *pPhysicalAddress, NVM_Page_Descriptor_t *pPageDesc, uint16_t *pIndex);
146 static void NVM_ChecksumAdditive(uint16_t *pChecksum,
void *pBuffer, uint16_t len);
148 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
149 static void NVM_StaticWearReset(
void);
150 static void NVM_StaticWearUpdate(uint16_t address);
151 static Ecode_t NVM_StaticWearCheck(
void);
192 uint8_t *pPhysicalAddress = (uint8_t *)(config->nvmArea);
194 uint8_t *pDuplicatePhysicalAddress;
197 uint16_t logicalAddress;
199 uint16_t duplicateLogicalAddress;
202 NVM_ValidateResult_t validationResult;
207 if( (config->pages <= config->userPages)
208 || (config->pages > NVM_MAX_NUMBER_OF_PAGES) )
215 uint16_t pageIdx = 0, obj = 0, sum = 0;
216 const NVM_Page_Descriptor_t *currentPage;
218 for(pageIdx = 0; pageIdx < config->userPages; pageIdx++)
222 currentPage = &((*(config->nvmPages))[pageIdx]);
224 while( (*(currentPage->page))[obj].location != 0)
226 sum += (*(currentPage->page))[obj++].size;
229 if(currentPage->pageType == nvmPageTypeNormal)
231 if( sum > NVM_CONTENT_SIZE )
238 if(currentPage->pageType == nvmPageTypeWear)
240 if( (sum+NVM_CHECKSUM_LENGTH) > NVM_WEAR_CONTENT_SIZE )
255 NVM_ACQUIRE_WRITE_LOCK
260 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
262 NVM_StaticWearReset();
266 for (page = 0; page < nvmConfig->pages; ++page)
270 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, watermark),
272 sizeof(logicalAddress));
273 if (NVM_PAGE_EMPTY_VALUE != logicalAddress)
276 validationResult = NVM_PageValidate(pPhysicalAddress);
279 if (nvmValidateResultOk == validationResult)
288 else if (nvmValidateResultOkMarked == validationResult)
295 pDuplicatePhysicalAddress = (uint8_t *)(nvmConfig->nvmArea)
296 + offsetof(NVM_Page_Header_t, watermark);
297 for (page = 0; (NVM_PAGE_EMPTY_VALUE != logicalAddress) && (page < nvmConfig->pages);
300 NVMHAL_Read(pDuplicatePhysicalAddress + offsetof(NVM_Page_Header_t, watermark), &
301 duplicateLogicalAddress,
302 sizeof(duplicateLogicalAddress));
304 if ((pDuplicatePhysicalAddress != pPhysicalAddress)
305 && ((logicalAddress | NVM_FIRST_BIT_ONE) == duplicateLogicalAddress))
309 validationResult = NVM_PageValidate(pDuplicatePhysicalAddress);
311 if (nvmValidateResultOk == validationResult)
314 eraseResult = NVM_PageErase(pPhysicalAddress);
319 eraseResult = NVM_PageErase(pDuplicatePhysicalAddress);
330 pDuplicatePhysicalAddress += NVM_PAGE_SIZE;
348 pPhysicalAddress += NVM_PAGE_SIZE;
358 NVM_RELEASE_WRITE_LOCK
389 uint8_t *pPhysicalAddress = (uint8_t *)(nvmConfig->nvmArea);
392 uint32_t tempEraseCount = eraseCount;
395 NVM_ACQUIRE_WRITE_LOCK
399 (page < nvmConfig->pages)
408 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
410 sizeof(tempEraseCount));
419 result =
NVMHAL_Write(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
421 sizeof(tempEraseCount));
425 pPhysicalAddress += NVM_PAGE_SIZE;
429 NVM_RELEASE_WRITE_LOCK
466 uint16_t watermark = pageId | NVM_FIRST_BIT_ONE;
468 const uint32_t flipWatermark = NVM_FLIP_FIRST_BIT_OF_32_WHEN_WRITE;
471 NVM_Page_Descriptor_t pageDesc;
475 NVM_Page_Header_t header;
478 uint16_t checksum = NVM_CHECKSUM_INITIAL;
481 uint8_t *pOldPhysicalAddress = (uint8_t *) NVM_NO_PAGE_RETURNED;
482 uint8_t *pNewPhysicalAddress = (uint8_t *) NVM_NO_PAGE_RETURNED;
485 uint16_t offsetAddress;
495 bool wearWrite =
false;
497 #if (NVM_FEATURE_WRITE_NECESSARY_CHECK_ENABLED)
502 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
504 uint16_t wearChecksum;
506 uint16_t wearObjectSize;
510 #if (NVM_FEATURE_WRITE_VALIDATION_ENABLED)
512 uint16_t wearIndexNew;
517 NVM_ACQUIRE_WRITE_LOCK
520 pOldPhysicalAddress = NVM_PagePhysicalAddressGet(pageId);
523 pageDesc = NVM_PageDescriptorGet(pageId);
525 #if (NVM_FEATURE_WRITE_NECESSARY_CHECK_ENABLED)
530 if (((uint8_t *) NVM_NO_PAGE_RETURNED != pOldPhysicalAddress)
531 && (nvmPageTypeNormal == pageDesc.pageType)
532 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
533 && !nvmStaticWearWorking
538 rewriteNeeded =
false;
544 while (((*pageDesc.page)[objectIndex].size != 0) && !rewriteNeeded)
549 ((*pageDesc.page)[objectIndex].objectId == objectId))
553 copyLength = (*pageDesc.page)[objectIndex].size;
556 while (copyLength != 0)
559 NVMHAL_Read(pOldPhysicalAddress + offsetAddress + NVM_HEADER_SIZE,
564 if (*(uint8_t *)((*pageDesc.page)[objectIndex].location + offsetAddress) != copyBuffer)
566 rewriteNeeded =
true;
571 offsetAddress +=
sizeof(copyBuffer);
572 copyLength -=
sizeof(copyBuffer);
578 offsetAddress += (*pageDesc.page)[objectIndex].size;
588 NVM_RELEASE_WRITE_LOCK
597 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
602 if (nvmPageTypeWear == pageDesc.pageType)
608 wearChecksum = NVM_CHECKSUM_INITIAL;
609 NVM_ChecksumAdditive(&wearChecksum,
610 (*pageDesc.page)[0].location,
611 (*pageDesc.page)[0].size);
612 wearChecksum &= NVM_LAST_BIT_ZERO;
615 if ((uint8_t *) NVM_NO_PAGE_RETURNED != pOldPhysicalAddress)
618 wearIndex = NVM_WearIndex(pOldPhysicalAddress, &pageDesc);
619 wearObjectSize = (*pageDesc.page)[0].size + NVM_CHECKSUM_LENGTH;
622 if (wearIndex < ((uint16_t) NVM_WEAR_CONTENT_SIZE) / wearObjectSize)
626 + (wearIndex * wearObjectSize),
627 (*pageDesc.page)[0].location,
628 (*pageDesc.page)[0].size);
631 + (wearIndex * wearObjectSize)
632 + (*pageDesc.page)[0].size,
634 sizeof(wearChecksum));
639 #if (NVM_FEATURE_WRITE_VALIDATION_ENABLED)
642 if ((!NVM_WearReadIndex(pOldPhysicalAddress, &pageDesc, &wearIndexNew)) ||
643 (wearIndexNew != wearIndex))
653 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
659 if ((uint8_t *) NVM_NO_PAGE_RETURNED != pOldPhysicalAddress)
661 result =
NVMHAL_Write(pOldPhysicalAddress, &flipWatermark, 4);
666 NVM_RELEASE_WRITE_LOCK
672 pNewPhysicalAddress = NVM_ScratchPageFindBest();
674 if ((uint8_t*) NVM_NO_PAGE_RETURNED == pNewPhysicalAddress)
677 NVM_RELEASE_WRITE_LOCK
682 header.watermark = watermark;
683 header.eraseCount = NVM_NO_WRITE_32BIT;
684 header.version = NVM_VERSION;
687 NVMHAL_Write(pNewPhysicalAddress + offsetof(NVM_Page_Header_t, watermark),
689 sizeof(header.watermark));
690 NVMHAL_Write(pNewPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
691 &header.eraseCount,
sizeof(header.eraseCount));
693 NVMHAL_Write(pNewPhysicalAddress + offsetof(NVM_Page_Header_t, version),
694 &header.version,
sizeof(header.version));
708 ((*pageDesc.page)[objectIndex].objectId == objectId))
711 result =
NVMHAL_Write(pNewPhysicalAddress + NVM_HEADER_SIZE + offsetAddress,
712 (*pageDesc.page)[objectIndex].location,
713 (*pageDesc.page)[objectIndex].size);
714 offsetAddress += (*pageDesc.page)[objectIndex].size;
716 NVM_ChecksumAdditive(&checksum,
717 (*pageDesc.page)[objectIndex].location,
718 (*pageDesc.page)[objectIndex].size);
723 if ((uint8_t *) NVM_NO_PAGE_RETURNED != pOldPhysicalAddress)
725 NVM_ChecksumAdditive(&checksum,
726 pOldPhysicalAddress + offsetAddress + NVM_HEADER_SIZE,
727 (*pageDesc.page)[objectIndex].size);
729 copyLength = (*pageDesc.page)[objectIndex].size;
734 NVMHAL_Read(pOldPhysicalAddress + offsetAddress + NVM_HEADER_SIZE,
737 result =
NVMHAL_Write(pNewPhysicalAddress + NVM_HEADER_SIZE + offsetAddress,
741 offsetAddress +=
sizeof(copyBuffer);
742 copyLength -=
sizeof(copyBuffer);
751 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
752 if (nvmPageTypeWear == pageDesc.pageType)
754 result =
NVMHAL_Write(pNewPhysicalAddress + NVM_HEADER_SIZE + offsetAddress,
756 sizeof(wearChecksum));
766 (NVM_PAGE_SIZE - NVM_FOOTER_SIZE) +
767 offsetof(NVM_Page_Footer_t, checksum),
771 (NVM_PAGE_SIZE - NVM_FOOTER_SIZE) +
772 offsetof(NVM_Page_Footer_t, watermark),
777 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
781 #if (NVM_FEATURE_WRITE_VALIDATION_ENABLED)
783 if (nvmValidateResultOk != NVM_PageValidate(pNewPhysicalAddress))
789 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
795 ((uint8_t *) NVM_NO_PAGE_RETURNED != pOldPhysicalAddress))
799 result = NVM_PageErase(pOldPhysicalAddress);
803 NVM_PageErase(pNewPhysicalAddress);
808 NVM_RELEASE_WRITE_LOCK
836 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
842 uint8_t *pPhysicalAddress;
845 NVM_Page_Descriptor_t pageDesc;
850 uint16_t offsetAddress;
854 NVM_ACQUIRE_WRITE_LOCK
857 pPhysicalAddress = NVM_PagePhysicalAddressGet(pageId);
860 if ((uint8_t*) NVM_NO_PAGE_RETURNED == pPhysicalAddress)
863 NVM_RELEASE_WRITE_LOCK
868 pageDesc = NVM_PageDescriptorGet(pageId);
870 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
873 if (nvmPageTypeWear == pageDesc.pageType)
876 if (NVM_WearReadIndex(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
877 &pageDesc, &wearIndex))
880 wearIndex * ((*pageDesc.page)[0].size + NVM_CHECKSUM_LENGTH),
881 (*pageDesc.page)[0].location,
882 (*pageDesc.page)[0].size);
888 NVM_RELEASE_WRITE_LOCK
899 #if (NVM_FEATURE_READ_VALIDATION_ENABLED)
900 if (nvmValidateResultError == NVM_PageValidate(pPhysicalAddress))
903 NVM_RELEASE_WRITE_LOCK
910 while ((*pageDesc.page)[objectIndex].size != 0)
914 || ((*pageDesc.page)[objectIndex].objectId == objectId))
916 NVMHAL_Read(pPhysicalAddress + offsetAddress + NVM_HEADER_SIZE,
917 (*pageDesc.page)[objectIndex].location,
918 (*pageDesc.page)[objectIndex].size);
921 offsetAddress += (*pageDesc.page)[objectIndex].size;
927 NVM_RELEASE_WRITE_LOCK
932 #if (NVM_FEATURE_WEARLEVELGET_ENABLED)
944 uint32_t NVM_WearLevelGet(
void)
950 uint32_t hiEraseCount = 0;
953 uint8_t *pPhysicalAddress = (uint8_t *)(nvmConfig->nvmArea);
956 for (page = 0; page < nvmConfig->pages; ++page)
959 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
962 if (eraseCount > hiEraseCount)
964 hiEraseCount = eraseCount;
968 pPhysicalAddress += NVM_PAGE_SIZE;
996 static uint8_t* NVM_PagePhysicalAddressGet(uint16_t pageId)
1000 uint8_t *pPhysicalAddress = (uint8_t *)(nvmConfig->nvmArea);
1002 uint16_t logicalAddress;
1005 for (page = 0; page < nvmConfig->pages; ++page)
1009 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, watermark),
1011 sizeof(logicalAddress));
1012 if (((pageId | NVM_FIRST_BIT_ONE) == logicalAddress) || (pageId == logicalAddress))
1014 return pPhysicalAddress;
1018 pPhysicalAddress += NVM_PAGE_SIZE;
1022 return (uint8_t *) NVM_NO_PAGE_RETURNED;
1038 static uint8_t* NVM_ScratchPageFindBest(
void)
1042 uint8_t *pPhysicalPage = (uint8_t *) NVM_NO_PAGE_RETURNED;
1045 uint32_t eraseCount = NVM_HIGHEST_32BIT;
1047 uint32_t loEraseCount = NVM_HIGHEST_32BIT;
1050 uint8_t *pPhysicalAddress = (uint8_t *)(nvmConfig->nvmArea);
1052 uint16_t logicalAddress;
1055 for (page = 0; page < nvmConfig->pages; ++page)
1058 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, watermark),
1060 sizeof(logicalAddress));
1061 if ((uint16_t) NVM_PAGE_EMPTY_VALUE == logicalAddress)
1064 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
1066 sizeof(eraseCount));
1067 if (eraseCount < loEraseCount)
1069 loEraseCount = eraseCount;
1070 pPhysicalPage = pPhysicalAddress;
1075 pPhysicalAddress += NVM_PAGE_SIZE;
1079 return pPhysicalPage;
1097 static Ecode_t NVM_PageErase(uint8_t *pPhysicalAddress)
1099 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
1101 uint16_t logicalAddress;
1105 uint32_t eraseCount;
1106 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
1108 sizeof(eraseCount));
1110 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
1112 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, watermark),
1114 sizeof(logicalAddress));
1117 if (logicalAddress != NVM_PAGE_EMPTY_VALUE)
1120 logicalAddress = logicalAddress & NVM_FIRST_BIT_ZERO;
1121 NVM_StaticWearUpdate(logicalAddress);
1132 return NVMHAL_Write(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
1134 sizeof(eraseCount));
1157 static NVM_Page_Descriptor_t NVM_PageDescriptorGet(uint16_t pageId)
1160 static const NVM_Page_Descriptor_t nullPage = { (uint8_t) 0, 0, (NVM_Page_Type_t) 0 };
1163 for (pageIndex = 0; pageIndex < nvmConfig->userPages; ++pageIndex)
1166 if ( (*(nvmConfig->nvmPages))[pageIndex].pageId == pageId)
1168 return (*(nvmConfig->nvmPages))[pageIndex];
1198 static NVM_ValidateResult_t NVM_PageValidate(uint8_t *pPhysicalAddress)
1201 NVM_ValidateResult_t result;
1204 NVM_Page_Header_t header;
1205 NVM_Page_Footer_t footer;
1208 NVM_Page_Descriptor_t pageDesc;
1214 uint8_t objectIndex;
1216 uint16_t offsetAddress;
1218 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
1224 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, watermark),
1226 sizeof(header.watermark));
1227 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, eraseCount),
1229 sizeof(header.eraseCount));
1230 NVMHAL_Read(pPhysicalAddress + offsetof(NVM_Page_Header_t, version),
1232 sizeof(header.version));
1235 if (NVM_VERSION != header.version)
1237 return nvmValidateResultOld;
1241 pageDesc = NVM_PageDescriptorGet((header.watermark & NVM_FIRST_BIT_ZERO));
1244 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
1245 if (nvmPageTypeWear == pageDesc.pageType)
1250 if ((header.watermark & NVM_FIRST_BIT_ZERO) == header.watermark)
1252 result = nvmValidateResultOkMarked;
1257 result = nvmValidateResultOk;
1261 if (!NVM_WearReadIndex(pPhysicalAddress, &pageDesc, &index))
1263 result = nvmValidateResultError;
1270 NVMHAL_Read(pPhysicalAddress + (NVM_PAGE_SIZE - NVM_FOOTER_SIZE) +
1271 offsetof(NVM_Page_Footer_t, checksum),
1273 sizeof(footer.checksum));
1274 NVMHAL_Read(pPhysicalAddress + (NVM_PAGE_SIZE - NVM_FOOTER_SIZE) +
1275 offsetof(NVM_Page_Footer_t, watermark),
1277 sizeof(footer.watermark));
1279 if (header.watermark == footer.watermark)
1281 result = nvmValidateResultOk;
1283 else if ((header.watermark | NVM_FIRST_BIT_ONE) == footer.watermark)
1285 result = nvmValidateResultOkMarked;
1289 result = nvmValidateResultError;
1295 checksum = NVM_CHECKSUM_INITIAL;
1300 while ((*pageDesc.page)[objectIndex].size != 0)
1303 (uint8_t *) pPhysicalAddress
1304 + NVM_HEADER_SIZE + offsetAddress,
1305 (*pageDesc.page)[objectIndex].size);
1306 offsetAddress += (*pageDesc.page)[objectIndex].size;
1310 if (checksum != footer.checksum)
1312 result = nvmValidateResultError;
1319 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
1338 static uint16_t NVM_WearIndex(uint8_t *pPhysicalAddress, NVM_Page_Descriptor_t *pPageDesc)
1341 uint16_t wearIndex = 0;
1347 uint16_t wearObjectSize = ((*pPageDesc->page)[0].size + NVM_CHECKSUM_LENGTH);
1351 while (wearIndex < NVM_WEAR_CONTENT_SIZE / wearObjectSize)
1353 NVMHAL_Read((uint8_t *)(pPhysicalAddress + NVM_HEADER_SIZE
1354 + (wearIndex * wearObjectSize)
1355 + (*pPageDesc->page)[0].size
1362 if ((checksum & NVM_LAST_BIT_ZERO) != checksum)
1377 #if (NVM_FEATURE_WEAR_PAGES_ENABLED)
1399 static bool NVM_WearReadIndex(uint8_t *pPhysicalAddress,
1400 NVM_Page_Descriptor_t *pPageDesc,
1403 #if (NVM_FEATURE_READ_VALIDATION_ENABLED)
1405 uint16_t checksum = NVM_CHECKSUM_INITIAL;
1409 const uint16_t wearObjectSize = ((*pPageDesc->page)[0].size + NVM_CHECKSUM_LENGTH);
1412 bool validObjectFound =
false;
1415 uint16_t readBuffer;
1418 *pIndex = (((uint16_t) NVM_WEAR_CONTENT_SIZE) / wearObjectSize);
1421 while ((*pIndex > 0) && (!validObjectFound))
1426 uint8_t *temp = pPhysicalAddress
1428 + (*pIndex) * wearObjectSize
1429 + (*pPageDesc->page)[0].size;
1430 NVMHAL_Read((uint8_t *) temp, &readBuffer,
sizeof(readBuffer));
1432 #if (NVM_FEATURE_READ_VALIDATION_ENABLED)
1434 checksum = NVM_CHECKSUM_INITIAL;
1435 NVMHAL_Checksum(&checksum, pPhysicalAddress + NVM_HEADER_SIZE + (*pIndex) * wearObjectSize, (*pPageDesc->page)[0].size);
1438 if ((uint16_t)(checksum & NVM_LAST_BIT_ZERO) == readBuffer)
1440 if (NVM_NO_WRITE_16BIT != readBuffer)
1443 validObjectFound =
true;
1446 return validObjectFound;
1470 static void NVM_ChecksumAdditive(uint16_t *pChecksum,
void *pBuffer, uint16_t len)
1472 uint8_t *pointer = (uint8_t *) pBuffer;
1473 uint16_t crc = *pChecksum;
1477 crc = (crc >> 8) | (crc << 8);
1479 crc ^= (crc & 0xf0) >> 4;
1480 crc ^= (crc & 0x0f) << 12;
1481 crc ^= (crc & 0xff) << 5;
1488 #if (NVM_FEATURE_STATIC_WEAR_ENABLED)
1498 static void NVM_StaticWearReset(
void)
1501 nvmStaticWearErasesSinceReset = 0;
1502 nvmStaticWearWritesInHistory = 0;
1504 for (i = 0; (NVM_PAGES_PER_WEAR_HISTORY * i) < nvmConfig->userPages; i += 1)
1506 nvmStaticWearWriteHistory[i] = 0;
1521 static void NVM_StaticWearUpdate(uint16_t address)
1523 if (address < nvmConfig->userPages)
1528 uint8_t mask = 1U << (address % NVM_PAGES_PER_WEAR_HISTORY);
1530 if ((nvmStaticWearWriteHistory[address / NVM_PAGES_PER_WEAR_HISTORY] & mask) == 0)
1533 nvmStaticWearWriteHistory[address / NVM_PAGES_PER_WEAR_HISTORY] |= mask;
1535 nvmStaticWearWritesInHistory++;
1539 nvmStaticWearErasesSinceReset++;
1542 NVM_StaticWearCheck();
1556 static Ecode_t NVM_StaticWearCheck(
void)
1559 if (!nvmStaticWearWorking)
1561 nvmStaticWearWorking =
true;
1562 while (nvmStaticWearErasesSinceReset / nvmStaticWearWritesInHistory > NVM_STATIC_WEAR_THRESHOLD)
1565 if (nvmStaticWearWritesInHistory >= nvmConfig->userPages)
1567 NVM_StaticWearReset();
1572 uint16_t address = 0;
1573 uint8_t mask = 1U << (address % NVM_PAGES_PER_WEAR_HISTORY);
1574 while ((nvmStaticWearWriteHistory[address / NVM_PAGES_PER_WEAR_HISTORY] & mask) != 0)
1577 mask = 1U << (address % NVM_PAGES_PER_WEAR_HISTORY);
1581 if (nvmPageTypeWear == NVM_PageDescriptorGet(address).pageType)
1584 nvmStaticWearWriteHistory[address / NVM_PAGES_PER_WEAR_HISTORY] |= mask;
1586 nvmStaticWearWritesInHistory++;
1594 NVM_RELEASE_WRITE_LOCK
1599 NVM_ACQUIRE_WRITE_LOCK
1602 nvmStaticWearWorking =
false;
void NVMHAL_Read(uint8_t *pAddress, void *pObject, uint16_t len)
Read data from NVM.
#define NVM_WRITE_ALL_CMD
void NVMHAL_Checksum(uint16_t *checksum, void *pMemory, uint16_t len)
Calculate checksum according to CCITT CRC16.
Ecode_t NVM_Read(uint16_t pageId, uint8_t objectId)
Read an object or an entire page.
#define NVM_ERASE_RETAINCOUNT
Ecode_t NVMHAL_Write(uint8_t *pAddress, void const *pObject, uint16_t len)
Write data to NVM.
#define ECODE_EMDRV_NVM_NO_PAGES_AVAILABLE
Initialization didn't find any pages available to allocate.
Ecode_t NVMHAL_PageErase(uint8_t *pAddress)
Erase a page in the NVM.
Ecode_t NVM_Erase(uint32_t eraseCount)
Erase the entire allocated NVM area.
Non-Volatile Memory Wear-Leveling driver API.
Ecode_t NVM_Init(NVM_Config_t const *config)
Initialize the NVM manager.
Ecode_t NVM_Write(uint16_t pageId, uint8_t objectId)
Write an object or a page.
#define ECODE_EMDRV_NVM_PAGE_INVALID
Could not find the page specified.
void NVMHAL_Init(void)
Initialize NVM driver.
uint32_t Ecode_t
Typedef for API function error code return values.
#define ECODE_EMDRV_NVM_ERROR
General error.
#define ECODE_EMDRV_NVM_OK
Success return value.
#define NVM_WRITE_NONE_CMD
#define ECODE_EMDRV_NVM_DATA_INVALID
Invalid input data or format.