NVProperty generic key value store using the MCU flash area.
Dependents: Turtle_RadioShuttle
Revision 4:eb6850e3bc21, committed 2019-01-31
- Comitter:
- Helmut Tschemernjak
- Date:
- Thu Jan 31 21:31:29 2019 +0100
- Parent:
- 3:968b84113ef3
- Child:
- 5:2560e615ccd5
- Commit message:
- Updated Properties for MBED
Changed in this revision
--- a/NVProperty.cpp Thu Jan 24 15:38:20 2019 +0100
+++ b/NVProperty.cpp Thu Jan 31 21:31:29 2019 +0100
@@ -25,10 +25,12 @@
#include <NVProperty_ESP32efuse.h>
#elif defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_ARCH_SAMD)
#include <NVProperty_D21Flash.h>
-#elif defined(__MBED__) && defined(TARGET_STM32L4)
+#elif __MBED__
#include <mbed.h>
- #include <NVProperty_L4OTP.h>
- #include <NVProperty_L4Flash.h>
+ #include <NVProperty_MBEDFlash.h>
+ #ifdef TARGET_STM32L4
+ #include <NVProperty_L4OTP.h>
+ #endif
#else
#error "Unkown implementation"
#endif
@@ -45,8 +47,8 @@
_flash = new NVProperty_ESP32NVS();
#elif defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_ARCH_SAMD)
_flash = new NVProperty_D21Flash(propSizekB, erase);
-#elif TARGET_STM32L4
- // TODO _flash = new NVProperty_L4Flash(propSizekB, erase);
+#elif __MBED__
+ _flash = new NVProperty_MBEDFlash(propSizekB, erase);
#else
#error "unkown platform"
#endif
--- a/NVProperty_L4Flash.cpp Thu Jan 24 15:38:20 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,523 +0,0 @@
-/*
- * This is an unpublished work copyright
- * (c) 2019 Helmut Tschemernjak
- * 30826 Garbsen (Hannover) Germany
- *
- *
- * Use is granted to registered RadioShuttle licensees only.
- * Licensees must own a valid serial number and product code.
- * Details see: www.radioshuttle.de
- */
-
-#ifdef TARGET_STM32L4
-
-#include <mbed.h>
-#include "main.h"
-#include <NVPropertyProviderInterface.h>
-#include <NVProperty_L4Flash.h>
-#include <NVProperty.h>
-
-#if 0
-#define OTP_TEST_IN_RAM // test OTP in RAM
-
-
-NVProperty_L4OTP::NVProperty_L4OTP()
-{
- _debug = false;
- _propSize = 1 * 1024; // no define in HAL laye
- _startAddress = (uint8_t *) 0x1FFF7000; // no define in HAL layer
-
-#ifdef OTP_TEST_IN_RAM
- static uint8_t *savedStart;
- if (!savedStart) {
- _startAddress = (uint8_t *) malloc(512);
- memset(_startAddress, 0xff, 512);
- savedStart = _startAddress;
- } else {
- _startAddress = savedStart;
- }
-#endif
-
- _endAddress = _startAddress + (_propSize);
- _lastEntry = NULL;
-
- _FlashInititalize();
-}
-
-
-NVProperty_L4OTP::~NVProperty_L4OTP()
-{
- _debug = true;
- _DumpAllEntires();
-}
-
-
-void
-NVProperty_L4OTP::_FlashInititalize(void)
-{
- _flash_header *fh = (_flash_header *)_startAddress;
- if (fh->magic == FLASH_PROP_MAGIC && fh->version == FLASH_PROP_VERSION && fh->size == _propSize) {
- return;
- }
-
- uint8_t *p = _startAddress;
- for (int i = 0; i < (int)sizeof(_flash_header); i++) {
- if (*p++ != 0xff)
- return; // invalid data
- }
-
- _flash_header f;
- memset(&f, 0, sizeof(f));
- f.magic = FLASH_PROP_MAGIC;
- f.version = FLASH_PROP_VERSION;
- f.size = _propSize;
-
- _OTPWrite(_startAddress, &f, sizeof(f));
-}
-
-
-int
-NVProperty_L4OTP::GetProperty(int key)
-{
- return GetProperty64(key);
-}
-
-
-int64_t
-NVProperty_L4OTP::GetProperty64(int key)
-{
- _flashEntry *p = _GetFlashEntry(key);
- if (!p)
- return NVProperty::NVP_ENOENT;
-
- int64_t value = 0;
-
- switch(p->t.type) {
- case NVProperty::T_BIT:
- if (p->t.t_bit)
- value = 1;
- else
- value = 0;
- break;
- case NVProperty::T_8BIT:
- value = p->u.v_8bit;
- break;
- case NVProperty::T_16BIT:
- {
- int16_t v;
- memcpy(&v, &p->u.v_16bit, sizeof(p->u.v_16bit));
- value = v;
- }
- break;
- case NVProperty::T_32BIT:
- {
- int32_t v;
- memcpy(&v, &p->data.v_32bit, sizeof(p->data.v_32bit));
- value =v;
- }
- break;
- case NVProperty::T_64BIT:
- memcpy(&value, p->data.v_64bit, sizeof(p->data.v_64bit));
- break;
- case NVProperty::T_STR:
- case NVProperty::T_BLOB:
- value = p->u.option.d_len;
- break;
- }
- return value;
-}
-
-const char *
-NVProperty_L4OTP::GetPropertyStr(int key)
-{
- _flashEntry *p = _GetFlashEntry(key);
- if (!p || p->t.type != NVProperty::T_STR)
- return NULL;
- return strdup(p->data.v_str);
-}
-
-int
-NVProperty_L4OTP::GetPropertyBlob(int key, const void *blob, int *size)
-{
- _flashEntry *p = _GetFlashEntry(key);
- if (!p || p->t.type != NVProperty::T_BLOB)
- return NVProperty::NVP_ENOENT;
-
- int cplen = std::min(*size, (int)p->u.option.d_len);
- if (blob)
- memcpy((void *)blob, p->data.v_blob, cplen);
- *size = cplen;
-
- return NVProperty::NVP_OK;
-}
-
-
-int
-NVProperty_L4OTP::SetProperty(int key, int64_t value, int type)
-{
- UNUSED(type);
- uint8_t valbuf[FLASH_ENTRY_MIN_SIZE + sizeof(int64_t)];
- _flashEntry *p = (_flashEntry *) valbuf;
- int storeType;
-
- if (GetProperty64(key) == value) // no need to save it again.
- return NVProperty::NVP_OK;
-
-
- memset(valbuf, 0, sizeof(valbuf));
-
- if (value == 0 || value == 1)
- storeType = NVProperty::T_BIT;
- else if (value >= -128 && value < 128)
- storeType = NVProperty::T_8BIT;
- else if (value >= -32768 && value < 32768)
- storeType = NVProperty::T_16BIT;
- else if (value > -2147483647 && value < 2147483648)
- storeType = NVProperty::T_32BIT;
- else
- storeType = NVProperty::T_64BIT;
-
- p->key = key;
- p->t.type = storeType;
-
-
- switch(storeType) {
- case NVProperty::T_BIT:
- p->t.t_bit = value;
- break;
- case NVProperty::T_8BIT:
- p->u.v_8bit = value;
- break;
- case NVProperty::T_16BIT:
- p->u.v_16bit = value;
- break;
- case NVProperty::T_32BIT:
- p->u.option.d_len = sizeof(p->data.v_32bit);
- {
- int32_t v = value;
- memcpy(&p->data.v_32bit, &v, sizeof(p->data.v_32bit));
- }
- break;
- case NVProperty::T_64BIT:
- p->u.option.d_len = sizeof(p->data.v_64bit);
- memcpy(p->data.v_64bit, &value, sizeof(p->data.v_64bit));
- break;
- }
- int len;
- if (storeType == NVProperty::T_BIT || storeType == NVProperty::T_8BIT || storeType == NVProperty::T_16BIT || storeType == NVProperty::T_32BIT) {
- len = FLASH_ENTRY_MIN_SIZE;
- } else { // 64/STR/BLOB
- len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
- len += _GetFlashPaddingSize(len);
- }
- if ((uint8_t *)_lastEntry + len >= _endAddress) {
- if (!_FlashReorgEntries(len))
- return NVProperty::NVP_ERR_NOSPACE;
- }
-
- _OTPWrite((uint8_t *)_lastEntry, p, len);
- _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len);
-
- // _DumpAllEntires();
- return NVProperty::NVP_OK;
-}
-
-
-int
-NVProperty_L4OTP::SetPropertyStr(int key, const char *value, int type)
-{
- if (type != NVProperty::T_STR)
- return NVProperty::NVP_INVALD_PARM;
-
- _flashEntry *p = _GetFlashEntry(key);
- if (p && p->t.type == NVProperty::T_STR && strcmp(p->data.v_str, value) == 0) {
- return NVProperty::NVP_OK;
- }
-
- int err = NVProperty::NVP_OK;
-
- p = new _flashEntry();
- if (!p)
- return NVProperty::NVP_ERR_NOSPACE;
-
- p->key = key;
- p->t.type = NVProperty::T_STR;
- int cplen = std::min(strlen(value), sizeof(p->data.v_str)-1);
- memcpy(p->data.v_str, value, cplen);
- p->u.option.d_len = cplen + 1; // zero term
-
- int len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
- len += _GetFlashPaddingSize(len);
-
- if ((uint8_t *)_lastEntry + len >= _endAddress) {
- if (!_FlashReorgEntries(len)) {
- err = NVProperty::NVP_ERR_NOSPACE;
- goto done;
- }
- }
-
- _OTPWrite((uint8_t *)_lastEntry, p, len);
- _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len);
-
-done:
- delete[] p;
- // _DumpAllEntires();
- return err;
-}
-
-int
-NVProperty_L4OTP::SetPropertyBlob(int key, const void *blob, int size, int type)
-{
- if (type != NVProperty::T_BLOB)
- return NVProperty::NVP_INVALD_PARM;
-
- _flashEntry *p = _GetFlashEntry(key);
- if (p && p->t.type == NVProperty::T_BLOB && size == p->u.option.d_len) { // check for duplicate
- if (memcmp(blob, p->data.v_blob, size) == 0)
- return NVProperty::NVP_OK;
- }
- int err = NVProperty::NVP_OK;
-
- p = new _flashEntry();
- if (!p)
- return NVProperty::NVP_ERR_NOSPACE;
-
- p->key = key;
- p->t.type = NVProperty::T_BLOB;
- int cplen = std::min(size, (int)sizeof(p->data.v_blob));
- p->u.option.d_len = cplen;
- memcpy(p->data.v_blob, blob, cplen);
-
- int len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
- len += _GetFlashPaddingSize(len);
-
- if ((uint8_t *)_lastEntry + len >= _endAddress) {
- if (!_FlashReorgEntries(len)) {
- err = NVProperty::NVP_ERR_NOSPACE;
- goto done;
- }
- }
-
- _OTPWrite((uint8_t *)_lastEntry, p, len);
- _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len);
-
-done:
- delete[] p;
- // _DumpAllEntires();
- return err;
-}
-
-int
-NVProperty_L4OTP::EraseProperty(int key)
-{
- uint8_t valbuf[FLASH_ENTRY_MIN_SIZE];
- _flashEntry *p = (_flashEntry *) valbuf;
-
- _flashEntry *op = _GetFlashEntry(key);
- if (!op)
- return NVProperty::NVP_ENOENT;
- if (op->t.deleted)
- return NVProperty::NVP_OK;
-
- memset(valbuf, 0, sizeof(valbuf));
- p->key = key;
- p->t.type = op->t.type;
- p->t.deleted = true;
-
- if ((uint8_t *)_lastEntry + FLASH_ENTRY_MIN_SIZE > _endAddress) {
- if (!_FlashReorgEntries(FLASH_ENTRY_MIN_SIZE))
- return NVProperty::NVP_ERR_NOSPACE;
- }
-
- _OTPWrite((uint8_t *)_lastEntry, p, FLASH_ENTRY_MIN_SIZE);
- _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + FLASH_ENTRY_MIN_SIZE);
-
- // _DumpAllEntires();
- return NVProperty::NVP_OK;
-}
-
-int
-NVProperty_L4OTP::ReorgProperties(void)
-{
- return NVProperty::NVP_OK;
-}
-
-
-int
-NVProperty_L4OTP::OpenPropertyStore(bool forWrite)
-{
- UNUSED(forWrite);
- return NVProperty::NVP_OK;
-}
-
-int
-NVProperty_L4OTP::ClosePropertyStore(bool flush)
-{
- return NVProperty::NVP_OK;
-}
-
-#if 1
-void
-NVProperty_L4OTP::_DumpAllEntires(void)
-{
- if (!_debug)
- return;
-
- dprintf("------------- DumpAllEntires -------- ");
-
- int index = 0;
- _flashEntry *p = (_flashEntry *)(_startAddress + sizeof(_flash_header));
- while((uint8_t *)p < _endAddress && p->key != NVProperty::PROPERTIES_EOF) {
-
- int64_t value = 0;
- switch(p->t.type) {
- case NVProperty::T_BIT:
- if (p->t.t_bit)
- value = 1;
- else
- value = 0;
- break;
- case NVProperty::T_8BIT:
- value = p->u.v_8bit;
- break;
- case NVProperty::T_16BIT:
- {
- int16_t v;
- memcpy(&v, &p->u.v_16bit, sizeof(p->u.v_16bit));
- value = v;
- }
- break;
- case NVProperty::T_32BIT:
- {
- int32_t v;
- memcpy(&v, &p->data.v_32bit, sizeof(p->data.v_32bit));
- value = v;
- }
- break;
- case NVProperty::T_64BIT:
- memcpy(&value, p->data.v_64bit, sizeof(p->data.v_64bit));
- break;
- case NVProperty::T_STR:
- case NVProperty::T_BLOB:
- value = p->u.option.d_len;
- break;
- }
- index++;
- if (p->t.deleted) {
- dprintf("Dump[%.2d] Key: %d Type: %d deleted(%d)", index, p->key, p->t.type, p->t.deleted);
-
- } else if (p->t.type == NVProperty::T_STR) {
- dprintf("Dump[%.2d] Key: %d Type: %d value: %s", index, p->key, p->t.type, p->data.v_str);
- } else if (p->t.type == NVProperty::T_BLOB) {
- dprintf("Dump[%.2d] Key: %d Type: %d len: %d", index, p->key, p->t.type, p->u.option.d_len);
- dump("Blob", p->data.v_str, p->u.option.d_len);
- } else {
- if (p->t.type == NVProperty::T_64BIT) {
- dprintf("Dump[%.2d] Key: %d Type: %d value: %lld (0x%llx)", index, p->key, p->t.type, value, value);
- } else {
- dprintf("Dump[%.2d] Key: %d Type: %d value: %ld (0x%x)", index, p->key, p->t.type, (int32_t)value, (unsigned int)value);
- }
- }
-
- p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p));
- }
- int freebytes = _endAddress -(uint8_t *)_lastEntry;
- if (_lastEntry)
- dprintf("------ %d bytes free -------", freebytes);
-}
-#endif
-
-NVProperty_L4OTP::_flashEntry *
-NVProperty_L4OTP::_GetFlashEntry(int key, uint8_t *start)
-{
- _flashEntry *p;
-
- if (start)
- p = (_flashEntry *)start;
- else
- p = (_flashEntry *)(_startAddress + sizeof(_flash_header));
- _flashEntry *lastP = NULL;
- while(true) {
- if ((uint8_t*)p >= _endAddress || p->key == NVProperty::PROPERTIES_EOF) {
- if ((uint8_t*)p <= _endAddress)
- _lastEntry = p;
- if (!lastP || lastP->t.deleted)
- return NULL;
- break;
- }
- if (p->key == key)
- lastP = p;
-
- p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p));
- }
- return lastP;
-}
-
-
-int
-NVProperty_L4OTP::_GetFlashEntryLen(_flashEntry *p)
-{
- int len = 0;
-
- switch(p->t.type) {
- case NVProperty::T_64BIT:
- case NVProperty::T_STR:
- case NVProperty::T_BLOB:
- len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
- len += _GetFlashPaddingSize(len);
- break;
- default:
- len = FLASH_ENTRY_MIN_SIZE;
- }
- return len;
-}
-
-int
-NVProperty_L4OTP::_GetFlashPaddingSize(int len)
-{
- int remain = len % FLASH_PADDING_SIZE;
-
- if (remain == 0)
- return 0;
-
- return (len + FLASH_PADDING_SIZE - remain) - len;
-}
-
-
-int
-NVProperty_L4OTP::_FlashReorgEntries(int minRequiredSpace)
-{
- return 0; // no reorg on OTP
-}
-
-
-void
-NVProperty_L4OTP::_OTPWrite(uint8_t *address, const void *d, size_t length)
-{
- //FlashIAP f;
- //f.init();
-#ifdef OTP_TEST_IN_RAM
- memcpy(address, d, length);
-#else
- uint8_t *data = (uint8_t *)d;
- uint32_t addr = (uint32_t)address;
- volatile uint64_t data64;
-
- HAL_FLASH_Unlock();
- while (length > 0) {
- for (uint8_t i = 0; i < 8; i++) {
- *(((uint8_t *) &data64) + i) = *(data + i);
- }
- int err = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, data64);
- addr += 8;
- data += 8;
- length -= 8;
- }
- HAL_FLASH_Lock();
-#endif
-}
-
-#endif
-
-
-#endif // TARGET_STM32L4
--- a/NVProperty_L4Flash.h Thu Jan 24 15:38:20 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * This is an unpublished work copyright
- * (c) 2019 Helmut Tschemernjak
- * 30826 Garbsen (Hannover) Germany
- *
- *
- * Use is granted to registered RadioShuttle licensees only.
- * Licensees must own a valid serial number and product code.
- * Details see: www.radioshuttle.de
- */
-
-#ifndef __NVPROPERTY_L4FLASH__
-#define __NVPROPERTY_L4FLASH__
-
-class NVProperty_L4Flash : public NVPropertyProviderInterface {
-public:
- NVProperty_L4Flash(int propSizekB, bool erase);
- ~NVProperty_L4Flash();
-
- virtual int GetProperty(int key);
- virtual int64_t GetProperty64(int key);
- virtual int GetPropertyBlob(int key, const void *blob, int *size);
- virtual const char *GetPropertyStr(int key);
- virtual int SetProperty(int key, int64_t value, int type);
- virtual int SetPropertyStr(int key, const char *value, int type);
- virtual int SetPropertyBlob(int key, const void *blob, int size, int type);
- virtual int EraseProperty(int key);
- virtual int ReorgProperties(void);
- virtual int OpenPropertyStore(bool forWrite = false);
- virtual int ClosePropertyStore(bool flush = false);
-
-private:
- void _FlashInititalize(bool force = false);
- void _FlashEraseRow(int startRow, int count = 1);
- void _FlashWrite(uint8_t *address, const void *data, size_t length);
- bool _FlashIsCleared(uint8_t *address, int len);
- void _FlashWritePage(int page, int offset, uint8_t *data, int length);
-
- struct _flash_header {
- uint32_t magic;
- uint16_t version;
- uint16_t sizeKB;
- };
-
- static const int FLASH_ENTRY_HEADER = 4;
- static const int FLASH_ENTRY_HEADER_SHORT = 2;
- static const int MAX_DATA_ENTRY = 256;
-
- struct _flashEntry {
- uint8_t key; // Property key
- struct {
- uint8_t deleted : 1; // this key has been deleted
- uint8_t t_bit : 1; // contains the bool value
- uint8_t reserv1 : 1; //
- uint8_t reserv2 : 1; //
- uint8_t type : 4; // NVPType
- } t;
- union {
- int16_t v_16bit;
- int8_t v_8bit;
- struct {
- uint8_t d_len; // data length
- uint8_t f_reserv1 : 8;
- } option;
- } u;
- union {
- int32_t v_32bit;
- int32_t v_64bit[2]; // use use 2 x 32-bit to avoid 64-bit struct padding
- char v_str[MAX_DATA_ENTRY];
- uint8_t v_blob[MAX_DATA_ENTRY];
- } data;
- };
-
- _flashEntry * _GetFlashEntry(int key, uint8_t *start = NULL);
- int _GetFlashEntryLen(_flashEntry *k);
- int _GetFlashPaddingSize(int len);
- _flashEntry *_lastEntry;
- void _DumpAllEntires(void);
- int _FlashReorgEntries(int minRequiredSpace);
- bool _debug;
- int _propSizekB;
- int _pageSize;
- int _numPages;
- int _rowSize;
- uint8_t *_startAddress;
- uint8_t *_endAddress;
-
- static const int FLASH_PROP_MAGIC = 0x4c6f5261; // "LORA"
- static const int FLASH_PROP_VERSION = 3;
- static const int _bootlLoaderSize = 8192;
- static const int _lockRegions = 16; // d21 lock regions are always 16 for the entire ram
-
-
-};
-
-#endif // __NVPROPERTY_L4FLASH__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/NVProperty_MBEDFlash.cpp Thu Jan 31 21:31:29 2019 +0100
@@ -0,0 +1,722 @@
+/*
+ * This is an unpublished work copyright
+ * (c) 2019 Helmut Tschemernjak
+ * 30826 Garbsen (Hannover) Germany
+ *
+ *
+ * Use is granted to registered RadioShuttle licensees only.
+ * Licensees must own a valid serial number and product code.
+ * Details see: www.radioshuttle.de
+ */
+
+#ifdef __MBED__
+
+#include <mbed.h>
+#include "main.h"
+#include "arch.h"
+#include <algorithm>
+#include <NVPropertyProviderInterface.h>
+#include <NVProperty_MBEDFlash.h>
+#include <NVProperty.h>
+
+
+#if 0 // sample test code for a man app.
+ {
+ NVProperty p;
+
+ p.OpenPropertyStore(true);
+ dprintf("OTP--1: %d", p.GetProperty(p.CPUID, -1));
+ p.SetProperty(p.CPUID, p.T_32BIT, 123, p.S_OTP);
+ dprintf("OTP123: %d", p.GetProperty(p.CPUID, 0));
+ p.SetProperty(p.CPUID, p.T_32BIT, 0x12345678, p.S_OTP);
+ dprintf("OTP0x12345678: %x", p.GetProperty(p.CPUID, 0));
+ p.EraseProperty(p.CPUID, p.S_OTP);
+ dprintf("OTP:-2 %d", p.GetProperty(p.CPUID, -2));
+ dprintf("OTP: Host %s", p.GetProperty(p.HOSTNAME, "MyHost"));
+ p.SetProperty(p.HOSTNAME, p.T_STR, "Wunstorf", p.S_OTP);
+ dprintf("OTP: Host %s", p.GetProperty(p.HOSTNAME, "MyHost"));
+ p.SetProperty(p.CPUID, p.T_32BIT, 9876, p.S_OTP);
+ dprintf("OTP9876: %d", p.GetProperty(p.CPUID, 0));
+ dprintf("OTP: Host %s", p.GetProperty(p.HOSTNAME, "MyHost"));
+
+ }
+#endif
+
+
+
+NVProperty_MBEDFlash::NVProperty_MBEDFlash(int propSizekB, bool erase)
+{
+ _flashIAP = new FlashIAP();
+ _flashIAP->init();
+
+ _debug = false;
+ _propSizekB = propSizekB;
+ _pageSize = _flashIAP->get_page_size();
+ _numPages = _flashIAP->get_flash_size() / _pageSize;
+ _rowSize = _flashIAP->get_sector_size(_flashIAP->get_flash_start()); // pageSize * 4;
+ _startAddress = (uint8_t*)_flashIAP->get_flash_start() + ((_numPages-(_propSizekB * 1024)/_pageSize) * _pageSize);
+ _endAddress = _startAddress + (_propSizekB * 1024);
+ _lastEntry = NULL;
+
+ if (_debug) {
+ dprintf("_propSizekB: %d kB", _propSizekB);
+ dprintf("_pageSize: %d", _pageSize);
+ dprintf("_numPages: %d", _numPages);
+ dprintf("_rowSize: %d", _rowSize);
+ dprintf("PageOffset: %d", _numPages-((_propSizekB * 1024)/_pageSize));
+ dprintf("total: %d", _pageSize * _numPages);
+ dprintf("_startAddress: %d", (int)_startAddress);
+ }
+
+ _FlashInititalize(erase);
+}
+
+
+NVProperty_MBEDFlash::~NVProperty_MBEDFlash()
+{
+ _flashIAP->deinit();
+ delete _flashIAP;
+ _debug = true;
+ wait_ms(100);
+ _DumpAllEntires();
+ wait_ms(100);
+}
+
+
+void
+NVProperty_MBEDFlash::_FlashInititalize(bool force)
+{
+ _flash_header *fh = (_flash_header *)_startAddress;
+ if (fh->magic == FLASH_PROP_MAGIC && fh->version == FLASH_PROP_VERSION && fh->sizeKB == _propSizekB) {
+ if (_debug)
+ dprintf("Flash OK");
+ if (!force)
+ return;
+ }
+
+ if (_debug)
+ dprintf("Formatting Flash");
+
+ _flash_header f;
+ memset(&f, 0, sizeof(f));
+ f.magic = FLASH_PROP_MAGIC;
+ f.version = FLASH_PROP_VERSION;
+ f.sizeKB = _propSizekB;
+
+ int count = (_propSizekB * 1024) / _rowSize;
+ int startRow = (int)_startAddress / _rowSize;
+ _FlashEraseRow(startRow, count);
+ _FlashWrite(_startAddress, &f, sizeof(f));
+}
+
+
+void
+NVProperty_MBEDFlash::_FlashEraseRow(int startRow, int count)
+{
+ // dprintf("_FlashEraseRow: startRow=%d, count=%d", startRow, count);
+
+ for(int i = 0; i < count; i++) {
+ uint32_t *startAddr = (uint32_t *)((startRow + i) * _rowSize);
+ uint32_t *addr = startAddr;
+ bool foundData = false;
+ for (int offset = 0; offset < _rowSize; offset += sizeof(uint32_t)) {
+ if (*addr++ != 0xffffffff) {
+ foundData = true;
+ break;
+ }
+ }
+ if (_debug)
+ dprintf("_FlashEraseRow: addr=0x%x, count=%d (%s)", (unsigned int)startAddr, i,
+ foundData ? "erased" : "skipped");
+ if (!foundData)
+ continue;
+
+ _flashIAP->erase((startRow + i) * _rowSize, _rowSize);
+ }
+}
+
+
+/*
+ * Find out start page, number of pages
+ * Check if the page contins FF's than write, otherwise erase first
+ */
+void
+NVProperty_MBEDFlash::_FlashWrite(uint8_t *address, const void *d, size_t length)
+{
+ uint8_t *data = (uint8_t *)d;
+
+ if (address < _startAddress || address > _startAddress + (_pageSize * _numPages))
+ return;
+
+ int done = 0;
+
+ do {
+ uint32_t startPage = (uint32_t)(address + done) / _pageSize;
+ int pageOffset = (uint32_t)(address + done) % _pageSize;
+ int pageWriteSize = _pageSize - pageOffset;
+
+ if (_FlashIsCleared((uint8_t *)(startPage * _pageSize) + pageOffset, pageWriteSize)) {
+ // single page write
+ int writeLength = std::min(pageWriteSize, (int)length);
+ _FlashWritePage(startPage, pageOffset, data, writeLength);
+ length -= writeLength;
+ done += writeLength;
+ data += writeLength;
+ } else {
+ // row write
+ // load row copy
+ // erase row
+ // merge in new data
+ // write row in page copies
+ uint32_t startRow = (uint32_t)(address + done) / _rowSize;
+ int rowOffset = (uint32_t)(address + done) - (startRow * _rowSize);
+ int cplen = std::min((int)length, _rowSize - rowOffset);
+ uint8_t *saveddata = new uint8_t[_rowSize];
+ if (!saveddata)
+ return;
+
+ memcpy(saveddata, (uint8_t *)(startRow * _rowSize), _rowSize);
+ // dprintf("startRow=%d rowOffset=%d, cplen=%d", startRow, rowOffset, cplen);
+
+ memcpy(saveddata + rowOffset, data, cplen);
+
+ _FlashEraseRow(startRow);
+ for (int i = 0; i < _rowSize/_pageSize; i++) {
+ _FlashWritePage(((startRow * _rowSize) / _pageSize) + i, 0, saveddata + (i * _pageSize), _pageSize);
+ }
+ length -= cplen;
+ done += cplen;
+ data += cplen;
+
+ delete[] saveddata;
+ }
+ } while(length > 0);
+}
+
+
+bool
+NVProperty_MBEDFlash::_FlashIsCleared(uint8_t *address, int len)
+{
+ while (len > 0) {
+ if (*address++ != NVProperty::PROPERTIES_EOF) {
+ return false;
+ }
+ len--;
+ }
+ return true;
+}
+
+
+void
+NVProperty_MBEDFlash::_FlashWritePage(int page, int offset, uint8_t *data, int length)
+{
+ uint8_t *addr = (uint8_t *)(page * _pageSize) + offset;
+ if (length < 1)
+ return;
+
+ _flashIAP->program(data, (uint32_t)addr, length);
+}
+
+
+
+int
+NVProperty_MBEDFlash::GetProperty(int key)
+{
+ return GetProperty64(key);
+}
+
+
+int64_t
+NVProperty_MBEDFlash::GetProperty64(int key)
+{
+ _flashEntry *p = _GetFlashEntry(key);
+ if (!p)
+ return NVProperty::NVP_ENOENT;
+
+ int64_t value = 0;
+
+ switch(p->t.type) {
+ case NVProperty::T_BIT:
+ if (p->t.t_bit)
+ value = 1;
+ else
+ value = 0;
+ break;
+ case NVProperty::T_8BIT:
+ value = p->u.v_8bit;
+ break;
+ case NVProperty::T_16BIT:
+ {
+ int16_t v;
+ memcpy(&v, &p->u.v_16bit, sizeof(p->u.v_16bit));
+ value = v;
+ }
+ break;
+ case NVProperty::T_32BIT:
+ {
+ int32_t v;
+ memcpy(&v, &p->data.v_32bit, sizeof(p->data.v_32bit));
+ value = v;
+ }
+ break;
+ case NVProperty::T_64BIT:
+ memcpy(&value, p->data.v_64bit, sizeof(p->data.v_64bit));
+ break;
+ case NVProperty::T_STR:
+ case NVProperty::T_BLOB:
+ value = p->u.option.d_len;
+ break;
+ }
+ return value;
+}
+
+const char *
+NVProperty_MBEDFlash::GetPropertyStr(int key)
+{
+ _flashEntry *p = _GetFlashEntry(key);
+ if (!p || p->t.type != NVProperty::T_STR)
+ return NULL;
+ return strdup(p->data.v_str);
+}
+
+int
+NVProperty_MBEDFlash::GetPropertyBlob(int key, const void *blob, int *size)
+{
+ _flashEntry *p = _GetFlashEntry(key);
+ if (!p || p->t.type != NVProperty::T_BLOB)
+ return NVProperty::NVP_ENOENT;
+
+ int cplen = std::min(*size, (int)p->u.option.d_len);
+ if (blob)
+ memcpy((void *)blob, p->data.v_blob, cplen);
+ *size = cplen;
+
+ return NVProperty::NVP_OK;
+}
+
+
+int
+NVProperty_MBEDFlash::SetProperty(int key, int64_t value, int type)
+{
+ UNUSED(type);
+ uint8_t valbuf[FLASH_ENTRY_MIN_SIZE + sizeof(int64_t)];
+ _flashEntry *p = (_flashEntry *) valbuf;
+ int storeType;
+
+ if (GetProperty64(key) == value) // no need to save it again.
+ return NVProperty::NVP_OK;
+
+ memset(valbuf, 0, sizeof(valbuf));
+
+ if (value == 0 || value == 1)
+ storeType = NVProperty::T_BIT;
+ else if (value >= -128 && value < 128)
+ storeType = NVProperty::T_8BIT;
+ else if (value >= -32768 && value < 32768)
+ storeType = NVProperty::T_16BIT;
+ else if (value > -2147483647LL && value < 2147483648LL)
+ storeType = NVProperty::T_32BIT;
+ else
+ storeType = NVProperty::T_64BIT;
+
+ p->key = key;
+ p->t.type = storeType;
+
+
+ switch(storeType) {
+ case NVProperty::T_BIT:
+ p->t.t_bit = value;
+ break;
+ case NVProperty::T_8BIT:
+ p->u.v_8bit = value;
+ break;
+ case NVProperty::T_16BIT:
+ p->u.v_16bit = value;
+ break;
+ case NVProperty::T_32BIT:
+ p->u.option.d_len = sizeof(p->data.v_32bit);
+ {
+ int32_t v = value;
+ memcpy(&p->data.v_32bit, &v, sizeof(p->data.v_32bit));
+ }
+ break;
+ case NVProperty::T_64BIT:
+ p->u.option.d_len = sizeof(p->data.v_64bit);
+ memcpy(p->data.v_64bit, &value, sizeof(p->data.v_64bit));
+ break;
+ }
+ int len;
+ if (storeType == NVProperty::T_BIT || storeType == NVProperty::T_8BIT || storeType == NVProperty::T_16BIT || storeType == NVProperty::T_32BIT) {
+ len = FLASH_ENTRY_MIN_SIZE;
+ } else { // 64/STR/BLOB
+ len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
+ len += _GetFlashPaddingSize(len);
+ }
+ if ((uint8_t *)_lastEntry + len >= _endAddress) {
+ if (!_FlashReorgEntries(len))
+ return NVProperty::NVP_ERR_NOSPACE;
+ }
+
+ _FlashWrite((uint8_t *)_lastEntry, p, len);
+ _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len);
+
+ // _DumpAllEntires();
+ return NVProperty::NVP_OK;
+}
+
+
+int
+NVProperty_MBEDFlash::SetPropertyStr(int key, const char *value, int type)
+{
+ if (type != NVProperty::T_STR)
+ return NVProperty::NVP_INVALD_PARM;
+
+ _flashEntry *p = _GetFlashEntry(key);
+ if (p && p->t.type == NVProperty::T_STR && strcmp(p->data.v_str, value) == 0) {
+ return NVProperty::NVP_OK;
+ }
+
+ int err = NVProperty::NVP_OK;
+
+ p = new _flashEntry();
+ if (!p)
+ return NVProperty::NVP_ERR_NOSPACE;
+
+ p->key = key;
+ p->t.type = NVProperty::T_STR;
+ int cplen = std::min(strlen(value), sizeof(p->data.v_str)-1);
+ memcpy(p->data.v_str, value, cplen);
+ p->u.option.d_len = cplen + 1; // zero term
+
+ int len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
+ len += _GetFlashPaddingSize(len);
+
+ if ((uint8_t *)_lastEntry + len >= _endAddress) {
+ if (!_FlashReorgEntries(len)) {
+ err = NVProperty::NVP_ERR_NOSPACE;
+ goto done;
+ }
+ }
+
+ _FlashWrite((uint8_t *)_lastEntry, p, len);
+ _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len);
+
+done:
+ delete[] p;
+ // _DumpAllEntires();
+ return err;
+}
+
+int
+NVProperty_MBEDFlash::SetPropertyBlob(int key, const void *blob, int size, int type)
+{
+ if (type != NVProperty::T_BLOB)
+ return NVProperty::NVP_INVALD_PARM;
+
+ _flashEntry *p = _GetFlashEntry(key);
+ if (p && p->t.type == NVProperty::T_BLOB && size == p->u.option.d_len) { // check for duplicate
+ if (memcmp(blob, p->data.v_blob, size) == 0)
+ return NVProperty::NVP_OK;
+ }
+ int err = NVProperty::NVP_OK;
+
+ p = new _flashEntry();
+ if (!p)
+ return NVProperty::NVP_ERR_NOSPACE;
+
+ p->key = key;
+ p->t.type = NVProperty::T_BLOB;
+ int cplen = std::min(size, (int)sizeof(p->data.v_blob));
+ p->u.option.d_len = cplen;
+ memcpy(p->data.v_blob, blob, cplen);
+
+ int len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
+ len += _GetFlashPaddingSize(len);
+
+ if ((uint8_t *)_lastEntry + len >= _endAddress) {
+ if (!_FlashReorgEntries(len)) {
+ err = NVProperty::NVP_ERR_NOSPACE;
+ goto done;
+ }
+ }
+
+ _FlashWrite((uint8_t *)_lastEntry, p, len);
+ _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + len);
+
+done:
+ delete[] p;
+ // _DumpAllEntires();
+ return err;
+}
+
+int
+NVProperty_MBEDFlash::EraseProperty(int key)
+{
+ uint8_t valbuf[FLASH_ENTRY_MIN_SIZE];
+ _flashEntry *p = (_flashEntry *) valbuf;
+
+ _flashEntry *op = _GetFlashEntry(key);
+ if (!op)
+ return NVProperty::NVP_ENOENT;
+ if (op->t.deleted)
+ return NVProperty::NVP_OK;
+
+ memset(valbuf, 0, sizeof(valbuf));
+ p->key = key;
+ p->t.type = op->t.type;
+ p->t.deleted = true;
+
+ if ((uint8_t *)_lastEntry + FLASH_ENTRY_MIN_SIZE > _endAddress) {
+ if (!_FlashReorgEntries(FLASH_ENTRY_MIN_SIZE))
+ return NVProperty::NVP_ERR_NOSPACE;
+ }
+
+ _FlashWrite((uint8_t *)_lastEntry, p, FLASH_ENTRY_MIN_SIZE);
+ _lastEntry = (_flashEntry *)((uint8_t *)_lastEntry + FLASH_ENTRY_MIN_SIZE);
+
+ // _DumpAllEntires();
+ return NVProperty::NVP_OK;
+}
+
+int
+NVProperty_MBEDFlash::ReorgProperties(void)
+{
+ if (_FlashReorgEntries(FLASH_ENTRY_MIN_SIZE))
+ return NVProperty::NVP_OK;
+ return NVProperty::NVP_ERR_NOSPACE;
+}
+
+
+int
+NVProperty_MBEDFlash::OpenPropertyStore(bool forWrite)
+{
+ UNUSED(forWrite);
+ return NVProperty::NVP_OK;
+}
+
+int
+NVProperty_MBEDFlash::ClosePropertyStore(bool flush)
+{
+ return NVProperty::NVP_OK;
+}
+
+#if 1
+void
+NVProperty_MBEDFlash::_DumpAllEntires(void)
+{
+ if (!_debug)
+ return;
+
+ dprintf("------------- DumpAllEntires -------- ");
+
+ int index = 0;
+ _flashEntry *p = (_flashEntry *)(_startAddress + sizeof(_flash_header));
+ while((uint8_t *)p < _endAddress && p->key != NVProperty::PROPERTIES_EOF) {
+
+ int64_t value = 0;
+ switch(p->t.type) {
+ case NVProperty::T_BIT:
+ if (p->t.t_bit)
+ value = 1;
+ else
+ value = 0;
+ break;
+ case NVProperty::T_8BIT:
+ value = p->u.v_8bit;
+ break;
+ case NVProperty::T_16BIT:
+ {
+ int16_t v;
+ memcpy(&v, &p->u.v_16bit, sizeof(p->u.v_16bit));
+ value = v;
+ }
+ break;
+ case NVProperty::T_32BIT:
+ {
+ int32_t v;
+ memcpy(&v, &p->data.v_32bit, sizeof(p->data.v_32bit));
+ value = v;
+ }
+ break;
+ case NVProperty::T_64BIT:
+ memcpy(&value, p->data.v_64bit, sizeof(p->data.v_64bit));
+ break;
+ case NVProperty::T_STR:
+ case NVProperty::T_BLOB:
+ value = p->u.option.d_len;
+ break;
+ }
+ index++;
+ if (p->t.deleted) {
+ dprintf("Dump[%.2d] Key: %d Type: %d deleted(%d)", index, p->key, p->t.type, p->t.deleted);
+
+ } else if (p->t.type == NVProperty::T_STR) {
+ dprintf("Dump[%.2d] Key: %d Type: %d value: %s", index, p->key, p->t.type, p->data.v_str);
+ } else if (p->t.type == NVProperty::T_BLOB) {
+ dprintf("Dump[%.2d] Key: %d Type: %d len: %d", index, p->key, p->t.type, p->u.option.d_len);
+ dump("Blob", p->data.v_str, p->u.option.d_len);
+ } else {
+ if (p->t.type == NVProperty::T_64BIT) {
+ dprintf("Dump[%.2d] Key: %d Type: %d value: %lld (0x%llx)", index, p->key, p->t.type, value, value);
+ } else {
+ dprintf("Dump[%.2d] Key: %d Type: %d value: %ld (0x%x)", index, p->key, p->t.type, (int32_t)value, (unsigned int)value);
+ }
+ }
+
+ p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p));
+ }
+ int freebytes = _endAddress -(uint8_t *)_lastEntry;
+ if (_lastEntry)
+ dprintf("------ %d bytes free -------", freebytes);
+}
+#endif
+
+NVProperty_MBEDFlash::_flashEntry *
+NVProperty_MBEDFlash::_GetFlashEntry(int key, uint8_t *start)
+{
+ _flashEntry *p;
+
+ if (start)
+ p = (_flashEntry *)start;
+ else
+ p = (_flashEntry *)(_startAddress + sizeof(_flash_header));
+ _flashEntry *lastP = NULL;
+ while(true) {
+ if ((uint8_t*)p >= _endAddress || p->key == NVProperty::PROPERTIES_EOF) {
+ if ((uint8_t*)p <= _endAddress)
+ _lastEntry = p;
+ if (!lastP || lastP->t.deleted)
+ return NULL;
+ break;
+ }
+ if (p->key == key)
+ lastP = p;
+
+ p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p));
+ }
+ return lastP;
+}
+
+
+int
+NVProperty_MBEDFlash::_GetFlashEntryLen(_flashEntry *p)
+{
+ int len = 0;
+
+ switch(p->t.type) {
+ case NVProperty::T_64BIT:
+ case NVProperty::T_STR:
+ case NVProperty::T_BLOB:
+ len = (FLASH_ENTRY_MIN_SIZE - 4) + p->u.option.d_len;
+ len += _GetFlashPaddingSize(len);
+ break;
+ default:
+ len = FLASH_ENTRY_MIN_SIZE;
+ }
+ return len;
+}
+
+int
+NVProperty_MBEDFlash::_GetFlashPaddingSize(int len)
+{
+ int remain = len % FLASH_PADDING_SIZE;
+
+ if (remain == 0)
+ return 0;
+
+ return (len + FLASH_PADDING_SIZE - remain) - len;
+}
+
+
+int
+NVProperty_MBEDFlash::_FlashReorgEntries(int minRequiredSpace)
+{
+ if (_debug) {
+ dprintf("_FlashReorgEntries: start");
+ // _DumpAllEntires();
+ }
+
+ int totalLen = 0;
+ int freeSpace = 0;
+
+ _flashEntry *p = (_flashEntry *)(_startAddress + sizeof(_flash_header));
+ while((uint8_t *)p < _endAddress && p->key != NVProperty::PROPERTIES_EOF) {
+ _flashEntry *k = _GetFlashEntry(p->key);
+ if (k == p) { // current entry is the lastest one.
+ totalLen += _GetFlashEntryLen(k);
+ }
+ p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p));
+ }
+
+ if (_startAddress + sizeof(_flash_header) + totalLen + minRequiredSpace >= _endAddress)
+ return 0;
+
+ freeSpace = _endAddress - (_startAddress + sizeof(_flash_header) + totalLen);
+ if (_debug)
+ dprintf("freeSpace: %d, totalLen: %d", freeSpace, totalLen);
+
+ /*
+ * Copy header
+ * while (content {
+ * - scan until tmp page is full
+ * - write page
+ * }
+ * Erase remaining pages.
+ *
+ */
+
+ p = (_flashEntry *)(_startAddress + sizeof(_flash_header));
+ uint8_t *saveddata = new uint8_t[_rowSize+sizeof(struct _flashEntry)];
+ if (!saveddata)
+ return 0;
+ uint8_t *t = saveddata;
+ int currentRow = (uint32_t)_startAddress / _rowSize;
+ int totalCopied = 0;
+
+ t = saveddata;
+ memcpy(t, _startAddress, sizeof(_flash_header));
+ t += sizeof(_flash_header);
+
+ while((uint8_t *)p < _endAddress && p->key != NVProperty::PROPERTIES_EOF) {
+ _flashEntry *k = _GetFlashEntry(p->key, (uint8_t *)p);
+ if (k == p) { // current entry is the lastest one.
+ if (!p->t.deleted) {
+ int plen = _GetFlashEntryLen(p);
+ memcpy(t, p, plen);
+ t += plen;
+ totalCopied += plen;
+ if (t - saveddata >= _rowSize) { // copy page
+ _FlashEraseRow(currentRow);
+ _FlashWrite((uint8_t *)(currentRow++ * _rowSize), saveddata, _rowSize);
+ int remainLen = (t - saveddata) - _rowSize;
+ if (remainLen) {
+ memcpy(saveddata, t - remainLen, remainLen);
+ }
+ t = saveddata + remainLen;
+ }
+ }
+ }
+ p = (_flashEntry *)((uint8_t *)p + _GetFlashEntryLen(p));
+ }
+
+ if (t > saveddata) { // copy remaining
+ _FlashEraseRow(currentRow);
+ _FlashWrite((uint8_t *)(currentRow++ * _rowSize), saveddata, t - saveddata);
+ }
+
+ while((uint32_t)0 + currentRow * _rowSize < (uint32_t)_endAddress) {
+ _FlashEraseRow(currentRow++);
+ }
+ delete[] saveddata;
+ _GetFlashEntry(0); // inits the _lastEntry record
+
+ if (_debug) {
+ dprintf("_FlashReorgEntries: end");
+ _DumpAllEntires();
+ }
+
+ return _endAddress - _startAddress - (sizeof(_flash_header) + totalCopied);
+}
+
+
+#endif // __MBED__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/NVProperty_MBEDFlash.h Thu Jan 31 21:31:29 2019 +0100
@@ -0,0 +1,97 @@
+/*
+ * This is an unpublished work copyright
+ * (c) 2019 Helmut Tschemernjak
+ * 30826 Garbsen (Hannover) Germany
+ *
+ *
+ * Use is granted to registered RadioShuttle licensees only.
+ * Licensees must own a valid serial number and product code.
+ * Details see: www.radioshuttle.de
+ */
+
+#ifndef __NVPROPERTY_MBEDFLASH__
+#define __NVPROPERTY_MBEDFLASH__
+
+class NVProperty_MBEDFlash : public NVPropertyProviderInterface {
+public:
+ NVProperty_MBEDFlash(int propSizekB, bool erase);
+ ~NVProperty_MBEDFlash();
+
+ virtual int GetProperty(int key);
+ virtual int64_t GetProperty64(int key);
+ virtual int GetPropertyBlob(int key, const void *blob, int *size);
+ virtual const char *GetPropertyStr(int key);
+ virtual int SetProperty(int key, int64_t value, int type);
+ virtual int SetPropertyStr(int key, const char *value, int type);
+ virtual int SetPropertyBlob(int key, const void *blob, int size, int type);
+ virtual int EraseProperty(int key);
+ virtual int ReorgProperties(void);
+ virtual int OpenPropertyStore(bool forWrite = false);
+ virtual int ClosePropertyStore(bool flush = false);
+
+private:
+ void _FlashInititalize(bool force = false);
+ void _FlashEraseRow(int startRow, int count = 1);
+ void _FlashWrite(uint8_t *address, const void *data, size_t length);
+ bool _FlashIsCleared(uint8_t *address, int len);
+ void _FlashWritePage(int page, int offset, uint8_t *data, int length);
+
+ struct _flash_header {
+ uint32_t magic;
+ uint16_t version;
+ uint16_t sizeKB;
+ };
+
+ static const int FLASH_ENTRY_MIN_SIZE = 8;
+ static const int MAX_DATA_ENTRY = 256-FLASH_ENTRY_MIN_SIZE;
+ static const int FLASH_PADDING_SIZE = 8; // writes sizes and alignment must be multiple of 64-bit,
+
+ struct _flashEntry {
+ uint8_t key; // Property key
+ struct {
+ uint8_t deleted : 1; // this key has been deleted
+ uint8_t t_bit : 1; // contains the bool value
+ uint8_t reserv1 : 1; //
+ uint8_t reserv2 : 1; //
+ uint8_t type : 4; // NVPType
+ } t;
+ union {
+ int16_t v_16bit;
+ int8_t v_8bit;
+ struct {
+ uint8_t d_len; // data length
+ uint8_t f_reserv1 : 8;
+ } option;
+ } u;
+ union {
+ int32_t v_32bit;
+ int32_t v_64bit[2]; // use use 2 x 32-bit to avoid 64-bit struct padding
+ char v_str[MAX_DATA_ENTRY];
+ uint8_t v_blob[MAX_DATA_ENTRY];
+ } data;
+ };
+
+ _flashEntry * _GetFlashEntry(int key, uint8_t *start = NULL);
+ int _GetFlashEntryLen(_flashEntry *k);
+ int _GetFlashPaddingSize(int len);
+ _flashEntry *_lastEntry;
+ void _DumpAllEntires(void);
+ int _FlashReorgEntries(int minRequiredSpace);
+ bool _debug;
+ int _propSizekB;
+ int _pageSize;
+ int _numPages;
+ int _rowSize;
+ FlashIAP *_flashIAP;
+ uint8_t *_startAddress;
+ uint8_t *_endAddress;
+
+ static const int FLASH_PROP_MAGIC = 0x4c6f5261; // "LORA"
+ static const int FLASH_PROP_VERSION = 3;
+ static const int _bootlLoaderSize = 8192;
+ static const int _lockRegions = 16; // d21 lock regions are always 16 for the entire ram
+
+
+};
+
+#endif // __NVPROPERTY_MBEDLASH__
--- a/NVProperty_SRAM.cpp Thu Jan 24 15:38:20 2019 +0100
+++ b/NVProperty_SRAM.cpp Thu Jan 31 21:31:29 2019 +0100
@@ -43,10 +43,8 @@
switch (it->second.type) {
case NVProperty::T_STR:
return NVProperty::NVP_ENOENT;
- break;
case NVProperty::T_BLOB:
return NVProperty::NVP_ENOENT;
- break;
default:
return it->second.val32;
}
@@ -63,10 +61,8 @@
switch (it->second.type) {
case NVProperty::T_STR:
return NVProperty::NVP_ENOENT;
- break;
case NVProperty::T_BLOB:
return NVProperty::NVP_ENOENT;
- break;
default:
return it->second.val64;
}
@@ -101,7 +97,6 @@
if (blob)
memcpy((void *)blob, it->second.data, *size);
return *size;
- break;
default:
break;
}
Helmut Tschemernjak