NVProperty generic key value store using the MCU flash area.
Dependents: Turtle_RadioShuttle
NVProperty_MBEDFlash.cpp
00001 /* 00002 * This is an unpublished work copyright 00003 * (c) 2019 Helmut Tschemernjak 00004 * 30826 Garbsen (Hannover) Germany 00005 * 00006 * 00007 * Use is granted to registered RadioShuttle licensees only. 00008 * Licensees must own a valid serial number and product code. 00009 * Details see: www.radioshuttle.de 00010 */ 00011 00012 #ifdef __MBED__ 00013 00014 #include <mbed.h> 00015 #include "main.h" 00016 #include "arch.h" 00017 #include <algorithm> 00018 #include <NVPropertyProviderInterface.h> 00019 #include <NVProperty_MBEDFlash.h> 00020 #include <NVProperty.h> 00021 00022 00023 #if 0 // sample test code for a main app. 00024 { 00025 NVProperty p; 00026 p.OpenPropertyStore(true); 00027 00028 dprintf("LORA_REMOTE_ID: %d", p.GetProperty(p.LORA_REMOTE_ID, 0)); 00029 p.SetProperty(p.LORA_REMOTE_ID, p.T_32BIT, 123); 00030 dprintf("LORA_REMOTE_ID: %d", p.GetProperty(p.LORA_REMOTE_ID, 0)); 00031 dprintf("Host: %s", p.GetProperty(p.HOSTNAME, "MyHost")); 00032 p.SetProperty(p.HOSTNAME, p.T_STR, "Wunstorf", p.S_FLASH); 00033 dprintf("Host: %s", p.GetProperty(p.HOSTNAME, "MyHost")); 00034 p.SetProperty(p.LORA_REMOTE_ID, p.T_32BIT, 456); 00035 dprintf("LORA_REMOTE_ID: %d", p.GetProperty(p.LORA_REMOTE_ID, 0)); 00036 dprintf("Host: %s", p.GetProperty(p.HOSTNAME, "MyHost")); 00037 } 00038 #endif 00039 00040 00041 00042 NVProperty_MBEDFlash::NVProperty_MBEDFlash(int propSizekB, bool erase) 00043 { 00044 _flashIAP = new FlashIAP(); 00045 _flashIAP->init(); 00046 00047 // a min page size > 8 looks strange 00048 MBED_ASSERT(_flashIAP->get_page_size() <= sizeof(int64_t)); 00049 00050 00051 _debug = false; 00052 _propSizekB = propSizekB; 00053 _pageSize = _flashIAP->get_page_size(); 00054 _numPages = _flashIAP->get_flash_size() / _pageSize; 00055 _rowSize = _flashIAP->get_sector_size(_flashIAP->get_flash_start()); 00056 MBED_ASSERT(((propSizekB *1024) % _rowSize) == 0); 00057 _startAddress = (uint8_t*)_flashIAP->get_flash_start() + ((_numPages-(_propSizekB * 1024)/_pageSize) * _pageSize); 00058 _endAddress = _startAddress + (_propSizekB * 1024); 00059 // _flashErasedValue = _flashIAP->get_erase_value(); 00060 _flashErasedValue = 0xff; // until the new mbed flashIAP->get_erase_value() is available 00061 #ifdef TARGET_STM32L0 00062 _flashErasedValue = 0x00; 00063 #endif 00064 _lastEntry = NULL; 00065 00066 if (_debug) { 00067 dprintf("_propSizekB: %d kB", _propSizekB); 00068 dprintf("_pageSize: %d", _pageSize); 00069 dprintf("_numPages: %d", _numPages); 00070 dprintf("_rowSize: %d", _rowSize); 00071 dprintf("PageOffset: %d", _numPages-((_propSizekB * 1024)/_pageSize)); 00072 dprintf("total: %d", _pageSize * _numPages); 00073 dprintf("_startAddress: %d", (int)_startAddress); 00074 } 00075 00076 _FlashInititalize(erase); 00077 _GetFlashEntry(0); // inits the _lastEntry record 00078 } 00079 00080 00081 NVProperty_MBEDFlash::~NVProperty_MBEDFlash() 00082 { 00083 _flashIAP->deinit(); 00084 delete _flashIAP; 00085 #if 0 00086 _debug = true; 00087 wait_ms(100); 00088 _DumpAllEntires(); 00089 wait_ms(100); 00090 dump("buffer: ", _startAddress, 100); 00091 wait_ms(100); 00092 #endif 00093 } 00094 00095 00096 void 00097 NVProperty_MBEDFlash::_FlashInititalize(bool force) 00098 { 00099 _flash_header *fh = (_flash_header *)_startAddress; 00100 if (fh->magic == FLASH_PROP_MAGIC && fh->version == FLASH_PROP_VERSION && fh->sizeKB == _propSizekB) { 00101 if (_debug) 00102 dprintf("Flash OK"); 00103 if (!force) 00104 return; 00105 } 00106 00107 if (_debug) 00108 dprintf("Formatting Flash"); 00109 00110 _flash_header f; 00111 memset(&f, 0, sizeof(f)); 00112 f.magic = FLASH_PROP_MAGIC; 00113 f.version = FLASH_PROP_VERSION; 00114 f.sizeKB = _propSizekB; 00115 00116 int count = (_propSizekB * 1024) / _rowSize; 00117 int startRow = (int)_startAddress / _rowSize; 00118 _FlashEraseRow(startRow, count); 00119 _FlashWrite(_startAddress, &f, sizeof(f)); 00120 } 00121 00122 00123 void 00124 NVProperty_MBEDFlash::_FlashEraseRow(int startRow, int count) 00125 { 00126 // dprintf("_FlashEraseRow: startRow=%d, count=%d", startRow, count); 00127 00128 for(int i = 0; i < count; i++) { 00129 uint32_t *startAddr = (uint32_t *)((startRow + i) * _rowSize); 00130 uint32_t *addr = startAddr; 00131 bool foundData = false; 00132 uint32_t emtpyValue = _flashErasedValue << 24 | _flashErasedValue << 16 | _flashErasedValue << 8 | _flashErasedValue; 00133 for (int offset = 0; offset < _rowSize; offset += sizeof(uint32_t)) { 00134 if (*addr++ != emtpyValue) { 00135 foundData = true; 00136 break; 00137 } 00138 } 00139 if (_debug) 00140 dprintf("_FlashEraseRow: addr=0x%x, count=%d (%s)", (unsigned int)startAddr, i, 00141 foundData ? "erased" : "skipped"); 00142 if (!foundData) 00143 continue; 00144 00145 _flashIAP->erase((startRow + i) * _rowSize, _rowSize); 00146 } 00147 } 00148 00149 00150 /* 00151 * Find out start page, number of pages 00152 * Check if the page contins FF's than write, otherwise erase first 00153 */ 00154 void 00155 NVProperty_MBEDFlash::_FlashWrite(uint8_t *address, const void *d, size_t length) 00156 { 00157 uint8_t *data = (uint8_t *)d; 00158 00159 if (address < _startAddress || address > _startAddress + (_pageSize * _numPages)) 00160 return; 00161 00162 int done = 0; 00163 00164 do { 00165 uint32_t startPage = (uint32_t)(address + done) / _pageSize; 00166 int pageOffset = (uint32_t)(address + done) % _pageSize; 00167 int pageWriteSize = _pageSize - pageOffset; 00168 00169 if (_FlashIsCleared((uint8_t *)(startPage * _pageSize) + pageOffset, pageWriteSize)) { 00170 // single page write 00171 int writeLength = std::min(pageWriteSize, (int)length); 00172 _FlashWritePage(startPage, pageOffset, data, writeLength); 00173 length -= writeLength; 00174 done += writeLength; 00175 data += writeLength; 00176 } else { 00177 // row write 00178 // load row copy 00179 // erase row 00180 // merge in new data 00181 // write row in page copies 00182 uint32_t startRow = (uint32_t)(address + done) / _rowSize; 00183 int rowOffset = (uint32_t)(address + done) - (startRow * _rowSize); 00184 int cplen = std::min((int)length, _rowSize - rowOffset); 00185 uint8_t *saveddata = new uint8_t[_rowSize]; 00186 if (!saveddata) 00187 return; 00188 00189 memcpy(saveddata, (uint8_t *)(startRow * _rowSize), _rowSize); 00190 // dprintf("startRow=%d rowOffset=%d, cplen=%d", startRow, rowOffset, cplen); 00191 00192 memcpy(saveddata + rowOffset, data, cplen); 00193 00194 _FlashEraseRow(startRow); 00195 for (int i = 0; i < _rowSize/_pageSize; i++) { 00196 _FlashWritePage(((startRow * _rowSize) / _pageSize) + i, 0, saveddata + (i * _pageSize), _pageSize); 00197 } 00198 length -= cplen; 00199 done += cplen; 00200 data += cplen; 00201 00202 delete[] saveddata; 00203 } 00204 } while(length > 0); 00205 } 00206 00207 00208 bool 00209 NVProperty_MBEDFlash::_FlashIsCleared(uint8_t *address, int len) 00210 { 00211 while (len-- > 0) { 00212 if (*address++ != _flashErasedValue) { 00213 return false; 00214 } 00215 } 00216 return true; 00217 } 00218 00219 00220 void 00221 NVProperty_MBEDFlash::_FlashWritePage(int page, int offset, uint8_t *data, int length) 00222 { 00223 uint8_t *addr = (uint8_t *)(page * _pageSize) + offset; 00224 if (length < 1) 00225 return; 00226 00227 _flashIAP->program(data, (uint32_t)addr, length); 00228 } 00229 00230 00231 00232 int 00233 NVProperty_MBEDFlash::GetProperty(int key) 00234 { 00235 return GetProperty64(key); 00236 } 00237 00238 00239 int64_t 00240 NVProperty_MBEDFlash::GetProperty64(int key) 00241 { 00242 _flashEntry *p = _GetFlashEntry(key); 00243 if (!p) 00244 return NVProperty::NVP_ENOENT; 00245 00246 int64_t value = 0; 00247 00248 switch(p->t.type) { 00249 case NVProperty::T_BIT: 00250 if (p->t.t_bit) 00251 value = 1; 00252 else 00253 value = 0; 00254 break; 00255 case NVProperty::T_8BIT: 00256 value = p->u.v_8bit; 00257 break; 00258 case NVProperty::T_16BIT: 00259 { 00260 int16_t v; 00261 memcpy(&v, &p->u.v_16bit, sizeof(p->u.v_16bit)); 00262 value = v; 00263 } 00264 break; 00265 case NVProperty::T_32BIT: 00266 { 00267 int32_t v; 00268 memcpy(&v, &p->data.v_32bit, sizeof(p->data.v_32bit)); 00269 value = v; 00270 } 00271 break; 00272 case NVProperty::T_64BIT: 00273 memcpy(&value, p->data.v_64bit, sizeof(p->data.v_64bit)); 00274 break; 00275 case NVProperty::T_STR: 00276 case NVProperty::T_BLOB: 00277 value = p->u.option.d_len; 00278 break; 00279 } 00280 return value; 00281 } 00282 00283 const char * 00284 NVProperty_MBEDFlash::GetPropertyStr(int key) 00285 { 00286 _flashEntry *p = _GetFlashEntry(key); 00287 if (!p || p->t.type != NVProperty::T_STR) 00288 return NULL; 00289 return strdup(p->data.v_str); 00290 } 00291 00292 int 00293 NVProperty_MBEDFlash::GetPropertyBlob(int key, const void *blob, int *size) 00294 { 00295 _flashEntry *p = _GetFlashEntry(key); 00296 if (!p || p->t.type != NVProperty::T_BLOB) 00297 return NVProperty::NVP_ENOENT; 00298 00299 int cplen = std::min(*size, (int)p->u.option.d_len); 00300 if (blob) 00301 memcpy((void *)blob, p->data.v_blob, cplen); 00302 *size = cplen; 00303 00304 return NVProperty::NVP_OK; 00305 } 00306 00307 00308 int 00309 NVProperty_MBEDFlash::SetProperty(int key, int64_t value, int type) 00310 { 00311 UNUSED(type); 00312 uint8_t valbuf[16]; 00313 _flashEntry *p = (_flashEntry *) valbuf; 00314 int storeType; 00315 00316 if (GetProperty64(key) == value) // no need to save it again. 00317 return NVProperty::NVP_OK; 00318 00319 memset(valbuf, 0, sizeof(valbuf)); 00320 00321 if (value == 0 || value == 1) 00322 storeType = NVProperty::T_BIT; 00323 else if (value >= -128 && value < 128) 00324 storeType = NVProperty::T_8BIT; 00325 else if (value >= -32768 && value < 32768) 00326 storeType = NVProperty::T_16BIT; 00327 else if (value > -2147483647LL && value < 2147483648LL) 00328 storeType = NVProperty::T_32BIT; 00329 else 00330 storeType = NVProperty::T_64BIT; 00331 00332 p->key = key; 00333 p->t.type = storeType; 00334 00335 00336 switch(storeType) { 00337 case NVProperty::T_BIT: 00338 p->t.t_bit = value; 00339 break; 00340 case NVProperty::T_8BIT: 00341 p->u.v_8bit = value; 00342 break; 00343 case NVProperty::T_16BIT: 00344 p->u.v_16bit = value; 00345 break; 00346 case NVProperty::T_32BIT: 00347 p->u.option.d_len = sizeof(p->data.v_32bit); 00348 { 00349 int32_t v = value; 00350 memcpy(&p->data.v_32bit, &v, sizeof(p->data.v_32bit)); 00351 } 00352 break; 00353 case NVProperty::T_64BIT: 00354 p->u.option.d_len = sizeof(p->data.v_64bit); 00355 memcpy(p->data.v_64bit, &value, sizeof(p->data.v_64bit)); 00356 break; 00357 } 00358 int len; 00359 if (storeType == NVProperty::T_BIT) 00360 len = FLASH_ENTRY_HEADER_SHORT; 00361 else if (storeType == NVProperty::T_8BIT || storeType == NVProperty::T_16BIT) 00362 len = FLASH_ENTRY_HEADER; 00363 else // 32/64/STR/BLOB 00364 len = FLASH_ENTRY_HEADER + p->u.option.d_len; 00365 len += _GetFlashPaddingSize(len); 00366 if ((uint8_t *)_lastEntry + len >= _endAddress) { 00367 if (!_FlashReorgEntries(len)) 00368 return NVProperty::NVP_ERR_NOSPACE; 00369 } 00370 00371 _FlashWrite((uint8_t *)_lastEntry, p, len); 00372 _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len); 00373 00374 // _DumpAllEntires(); 00375 return NVProperty::NVP_OK; 00376 } 00377 00378 00379 int 00380 NVProperty_MBEDFlash::SetPropertyStr(int key, const char *value, int type) 00381 { 00382 if (type != NVProperty::T_STR) 00383 return NVProperty::NVP_INVALD_PARM; 00384 00385 _flashEntry *p = _GetFlashEntry(key); 00386 if (p && p->t.type == NVProperty::T_STR && strcmp(p->data.v_str, value) == 0) { 00387 return NVProperty::NVP_OK; 00388 } 00389 00390 int err = NVProperty::NVP_OK; 00391 00392 p = new _flashEntry(); 00393 if (!p) 00394 return NVProperty::NVP_ERR_NOSPACE; 00395 00396 p->key = key; 00397 p->t.type = NVProperty::T_STR; 00398 int cplen = std::min(strlen(value), sizeof(p->data.v_str)-1); 00399 memcpy(p->data.v_str, value, cplen); 00400 p->u.option.d_len = cplen + 1; // zero term 00401 00402 int len = FLASH_ENTRY_HEADER + p->u.option.d_len; 00403 len += _GetFlashPaddingSize(len); 00404 00405 if ((uint8_t *)_lastEntry + len >= _endAddress) { 00406 if (!_FlashReorgEntries(len)) { 00407 err = NVProperty::NVP_ERR_NOSPACE; 00408 goto done; 00409 } 00410 } 00411 00412 _FlashWrite((uint8_t *)_lastEntry, p, len); 00413 _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len); 00414 00415 done: 00416 delete[] p; 00417 // _DumpAllEntires(); 00418 return err; 00419 } 00420 00421 int 00422 NVProperty_MBEDFlash::SetPropertyBlob(int key, const void *blob, int size, int type) 00423 { 00424 if (type != NVProperty::T_BLOB) 00425 return NVProperty::NVP_INVALD_PARM; 00426 00427 _flashEntry *p = _GetFlashEntry(key); 00428 if (p && p->t.type == NVProperty::T_BLOB && size == p->u.option.d_len) { // check for duplicate 00429 if (memcmp(blob, p->data.v_blob, size) == 0) 00430 return NVProperty::NVP_OK; 00431 } 00432 int err = NVProperty::NVP_OK; 00433 00434 p = new _flashEntry(); 00435 if (!p) 00436 return NVProperty::NVP_ERR_NOSPACE; 00437 00438 p->key = key; 00439 p->t.type = NVProperty::T_BLOB; 00440 int cplen = std::min(size, (int)sizeof(p->data.v_blob)); 00441 p->u.option.d_len = cplen; 00442 memcpy(p->data.v_blob, blob, cplen); 00443 00444 int len = FLASH_ENTRY_HEADER + p->u.option.d_len; 00445 len += _GetFlashPaddingSize(len); 00446 00447 if ((uint8_t *)_lastEntry + len >= _endAddress) { 00448 if (!_FlashReorgEntries(len)) { 00449 err = NVProperty::NVP_ERR_NOSPACE; 00450 goto done; 00451 } 00452 } 00453 00454 _FlashWrite((uint8_t *)_lastEntry, p, len); 00455 _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len); 00456 00457 done: 00458 delete[] p; 00459 // _DumpAllEntires(); 00460 return err; 00461 } 00462 00463 int 00464 NVProperty_MBEDFlash::EraseProperty(int key) 00465 { 00466 uint8_t valbuf[16]; 00467 _flashEntry *p = (_flashEntry *) valbuf; 00468 00469 _flashEntry *op = _GetFlashEntry(key); 00470 if (!op) 00471 return NVProperty::NVP_ENOENT; 00472 if (op->t.deleted) 00473 return NVProperty::NVP_OK; 00474 00475 memset(valbuf, 0, sizeof(valbuf)); 00476 p->key = key; 00477 p->t.type = op->t.type; 00478 p->t.deleted = true; 00479 00480 int len = FLASH_ENTRY_HEADER_SHORT; 00481 len += _GetFlashPaddingSize(len); 00482 00483 if ((uint8_t *)_lastEntry + len > _endAddress) { 00484 if (!_FlashReorgEntries(len)) 00485 return NVProperty::NVP_ERR_NOSPACE; 00486 } 00487 00488 _FlashWrite((uint8_t *)_lastEntry, p, len); 00489 _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len); 00490 00491 // _DumpAllEntires(); 00492 return NVProperty::NVP_OK; 00493 } 00494 00495 int 00496 NVProperty_MBEDFlash::ReorgProperties(void) 00497 { 00498 if (_FlashReorgEntries(FLASH_ENTRY_HEADER)) 00499 return NVProperty::NVP_OK; 00500 return NVProperty::NVP_ERR_NOSPACE; 00501 } 00502 00503 00504 int 00505 NVProperty_MBEDFlash::OpenPropertyStore(bool forWrite) 00506 { 00507 UNUSED(forWrite); 00508 return NVProperty::NVP_OK; 00509 } 00510 00511 int 00512 NVProperty_MBEDFlash::ClosePropertyStore(bool flush) 00513 { 00514 return NVProperty::NVP_OK; 00515 } 00516 00517 #if 1 00518 void 00519 NVProperty_MBEDFlash::_DumpAllEntires(void) 00520 { 00521 if (!_debug) 00522 return; 00523 00524 dprintf("------------- DumpAllEntires -------- "); 00525 00526 int index = 0; 00527 _flashEntry *p = (_flashEntry *)(_startAddress + sizeof(_flash_header)); 00528 while((uint8_t *)p < _endAddress && p->key != _flashErasedValue) { 00529 00530 int64_t value = 0; 00531 switch(p->t.type) { 00532 case NVProperty::T_BIT: 00533 if (p->t.t_bit) 00534 value = 1; 00535 else 00536 value = 0; 00537 break; 00538 case NVProperty::T_8BIT: 00539 value = p->u.v_8bit; 00540 break; 00541 case NVProperty::T_16BIT: 00542 { 00543 int16_t v; 00544 memcpy(&v, &p->u.v_16bit, sizeof(p->u.v_16bit)); 00545 value = v; 00546 } 00547 break; 00548 case NVProperty::T_32BIT: 00549 { 00550 int32_t v; 00551 memcpy(&v, &p->data.v_32bit, sizeof(p->data.v_32bit)); 00552 value = v; 00553 } 00554 break; 00555 case NVProperty::T_64BIT: 00556 memcpy(&value, p->data.v_64bit, sizeof(p->data.v_64bit)); 00557 break; 00558 case NVProperty::T_STR: 00559 case NVProperty::T_BLOB: 00560 value = p->u.option.d_len; 00561 break; 00562 } 00563 index++; 00564 if (p->t.deleted) { 00565 dprintf("Dump[%.2d] Key: %d Type: %d deleted(%d)", index, p->key, p->t.type, p->t.deleted); 00566 00567 } else if (p->t.type == NVProperty::T_STR) { 00568 dprintf("Dump[%.2d] Key: %d Type: %d value: %s", index, p->key, p->t.type, p->data.v_str); 00569 } else if (p->t.type == NVProperty::T_BLOB) { 00570 dprintf("Dump[%.2d] Key: %d Type: %d len: %d", index, p->key, p->t.type, p->u.option.d_len); 00571 dump("Blob", p->data.v_str, p->u.option.d_len); 00572 } else { 00573 if (p->t.type == NVProperty::T_64BIT) { 00574 dprintf("Dump[%.2d] Key: %d Type: %d value: %lld (0x%llx)", index, p->key, p->t.type, value, value); 00575 } else { 00576 dprintf("Dump[%.2d] Key: %d Type: %d value: %ld (0x%x)", index, p->key, p->t.type, (int32_t)value, (unsigned int)value); 00577 } 00578 } 00579 00580 p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p)); 00581 } 00582 int freebytes = _endAddress -(uint8_t *)_lastEntry; 00583 if (_lastEntry) 00584 dprintf("------ %d bytes free -------", freebytes); 00585 } 00586 #endif 00587 00588 NVProperty_MBEDFlash::_flashEntry * 00589 NVProperty_MBEDFlash::_GetFlashEntry(int key, uint8_t *start) 00590 { 00591 _flashEntry *p; 00592 00593 if (start) 00594 p = (_flashEntry *)start; 00595 else 00596 p = (_flashEntry *)(_startAddress + sizeof(_flash_header)); 00597 _flashEntry *lastP = NULL; 00598 while(true) { 00599 if ((uint8_t*)p >= _endAddress || p->key == _flashErasedValue) { 00600 if ((uint8_t*)p <= _endAddress) 00601 _lastEntry = p; 00602 if (!lastP || lastP->t.deleted) 00603 return NULL; 00604 break; 00605 } 00606 if (p->key == key) 00607 lastP = p; 00608 00609 p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p)); 00610 } 00611 return lastP; 00612 } 00613 00614 00615 int 00616 NVProperty_MBEDFlash::_GetFlashEntryLen(_flashEntry *p) 00617 { 00618 int len = 0; 00619 00620 if (p->t.type == NVProperty::T_BIT || p->t.deleted) 00621 len = FLASH_ENTRY_HEADER_SHORT; 00622 else if (p->t.type == NVProperty::T_8BIT || p->t.type == NVProperty::T_16BIT) 00623 len = FLASH_ENTRY_HEADER; 00624 else 00625 len = FLASH_ENTRY_HEADER + p->u.option.d_len; 00626 00627 len += _GetFlashPaddingSize(len); 00628 00629 return len; 00630 } 00631 00632 int 00633 NVProperty_MBEDFlash::_GetFlashPaddingSize(int len) 00634 { 00635 int remain = len % _pageSize; 00636 00637 if (remain == 0) 00638 return 0; 00639 00640 return (len + _pageSize - remain) - len; 00641 } 00642 00643 00644 int 00645 NVProperty_MBEDFlash::_FlashReorgEntries(int minRequiredSpace) 00646 { 00647 if (_debug) { 00648 dprintf("_FlashReorgEntries: start"); 00649 // _DumpAllEntires(); 00650 } 00651 00652 int totalLen = 0; 00653 int freeSpace = 0; 00654 00655 _flashEntry *p = (_flashEntry *)(_startAddress + sizeof(_flash_header)); 00656 while((uint8_t *)p < _endAddress && p->key != _flashErasedValue) { 00657 _flashEntry *k = _GetFlashEntry(p->key); 00658 if (k == p) { // current entry is the lastest one. 00659 totalLen += _GetFlashEntryLen(k); 00660 } 00661 p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p)); 00662 } 00663 00664 if (_startAddress + sizeof(_flash_header) + totalLen + minRequiredSpace >= _endAddress) 00665 return 0; 00666 00667 freeSpace = _endAddress - (_startAddress + sizeof(_flash_header) + totalLen); 00668 if (_debug) 00669 dprintf("freeSpace: %d, totalLen: %d", freeSpace, totalLen); 00670 00671 /* 00672 * Copy header 00673 * while (content { 00674 * - scan until tmp page is full 00675 * - write page 00676 * } 00677 * Erase remaining pages. 00678 * 00679 */ 00680 00681 p = (_flashEntry *)(_startAddress + sizeof(_flash_header)); 00682 uint8_t *saveddata = new uint8_t[_rowSize+sizeof(struct _flashEntry)]; 00683 if (!saveddata) 00684 return 0; 00685 uint8_t *t = saveddata; 00686 int currentRow = (uint32_t)_startAddress / _rowSize; 00687 int totalCopied = 0; 00688 00689 t = saveddata; 00690 memcpy(t, _startAddress, sizeof(_flash_header)); 00691 t += sizeof(_flash_header); 00692 00693 while((uint8_t *)p < _endAddress && p->key != _flashErasedValue) { 00694 _flashEntry *k = _GetFlashEntry(p->key, (uint8_t *)p); 00695 if (k == p) { // current entry is the lastest one. 00696 if (!p->t.deleted) { 00697 int plen = _GetFlashEntryLen(p); 00698 memcpy(t, p, plen); 00699 t += plen; 00700 totalCopied += plen; 00701 if (t - saveddata >= _rowSize) { // copy page 00702 _FlashEraseRow(currentRow); 00703 _FlashWrite((uint8_t *)(currentRow++ * _rowSize), saveddata, _rowSize); 00704 int remainLen = (t - saveddata) - _rowSize; 00705 if (remainLen) { 00706 memcpy(saveddata, t - remainLen, remainLen); 00707 } 00708 t = saveddata + remainLen; 00709 } 00710 } 00711 } 00712 p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p)); 00713 } 00714 00715 if (t > saveddata) { // copy remaining 00716 _FlashEraseRow(currentRow); 00717 _FlashWrite((uint8_t *)(currentRow++ * _rowSize), saveddata, t - saveddata); 00718 } 00719 00720 while((uint32_t)0 + currentRow * _rowSize < (uint32_t)_endAddress) { 00721 _FlashEraseRow(currentRow++); 00722 } 00723 delete[] saveddata; 00724 _GetFlashEntry(0); // inits the _lastEntry record 00725 00726 if (_debug) { 00727 dprintf("_FlashReorgEntries: end"); 00728 _DumpAllEntires(); 00729 } 00730 00731 return _endAddress - _startAddress - (sizeof(_flash_header) + totalCopied); 00732 } 00733 00734 00735 #endif // __MBED__
Generated on Tue Jul 12 2022 20:44:07 by 1.7.2