diff --git a/src/esp32_platform.cpp b/src/esp32_platform.cpp index 728d282..040f0db 100644 --- a/src/esp32_platform.cpp +++ b/src/esp32_platform.cpp @@ -84,34 +84,132 @@ int Esp32Platform::readBytes(uint8_t * buffer, uint16_t maxLen) return len; } -bool Esp32Platform::writeNVMemory(uintptr_t addr,uint8_t data) +bool Esp32Platform::writeNVMemory(uint8_t* addr,uint8_t data) { - *((uint8_t*)addr) = data; + *addr = data; return true; } -uint8_t Esp32Platform::readNVMemory(uintptr_t addr) +uint8_t Esp32Platform::readNVMemory(uint8_t* addr) { - return *((uint8_t*)addr); + return *addr; } -uintptr_t Esp32Platform::allocNVMemory(size_t size,uint32_t ID) +uint8_t* Esp32Platform::allocNVMemory(size_t size,uint32_t ID) { - return (uintptr_t)EEPROM.getDataPtr(); + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + fatalError(); + + + _memoryBlocks[i].data = (uint8_t*)malloc(size); + if(_memoryBlocks[i].data == NULL) + fatalError(); + + _memoryBlocks[i].ID = ID; + _memoryBlocks[i].size = size; + + return _memoryBlocks[i].data; } -uintptr_t Esp32Platform::reloadNVMemory(uint32_t ID) +void Esp32Platform::initNVMemory() { EEPROM.begin(1024); - return (uintptr_t)EEPROM.getDataPtr(); + uint32_t addr = 0; + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++){ + + if (EEPROM.read(addr++) != 0xBA || EEPROM.read(addr++) != 0xAD || EEPROM.read(addr++) != 0xC0 || EEPROM.read(addr++) != 0xDE){ + _memoryBlocks[i].ID = 0; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].data = NULL; + continue; + } + + ((uint8_t*)&_memoryBlocks[i].ID)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[3] = EEPROM.read(addr++); + + ((uint8_t*)&_memoryBlocks[i].size)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[3] = EEPROM.read(addr++); + + _memoryBlocks[i].data = EEPROM.getDataPtr() + addr; + addr += _memoryBlocks[i].size; + } +} + +uint8_t* Esp32Platform::reloadNVMemory(uint32_t ID, bool pointerAccess) +{ + if(!_MemoryInitialized) + initNVMemory(); + + _MemoryInitialized=true; + + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return 0; + + + return _memoryBlocks[i].data; } void Esp32Platform::finishNVMemory() { + uint32_t addr = 0; + + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++) + { + if(_memoryBlocks[i].ID == 0) + continue; + + //write valid mask + EEPROM.write(addr++,0xBA); + EEPROM.write(addr++,0xAD); + EEPROM.write(addr++,0xC0); + EEPROM.write(addr++,0xDE); + + //write ID + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[3]); + + //write size + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[3]); + + //write data + for (uint32_t e=0;e<_memoryBlocks[i].size;e++){ + EEPROM.write(addr++,_memoryBlocks[i].data[e]); + } + } EEPROM.commit(); } void Esp32Platform::freeNVMemory(uint32_t ID) { + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return; + + _memoryBlocks[i].data = NULL; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].ID = 0; } #endif diff --git a/src/esp32_platform.h b/src/esp32_platform.h index 6cc0808..720bbb2 100644 --- a/src/esp32_platform.h +++ b/src/esp32_platform.h @@ -3,6 +3,13 @@ #include #include +#define MAX_MEMORY_BLOCKS 6 + +typedef struct{ + uint32_t ID; + size_t size; + uint8_t* data; +}MemoryBlock_t; class Esp32Platform : public ArduinoPlatform { @@ -28,14 +35,17 @@ public: int readBytes(uint8_t* buffer, uint16_t maxLen) override; //memory - bool writeNVMemory(uintptr_t addr,uint8_t data); - uint8_t readNVMemory(uintptr_t addr); - uintptr_t allocNVMemory(size_t size,uint32_t ID); - uintptr_t reloadNVMemory(uint32_t ID); + bool writeNVMemory(uint8_t* addr,uint8_t data); + uint8_t readNVMemory(uint8_t* addr); + uint8_t* allocNVMemory(size_t size,uint32_t ID); + uint8_t* reloadNVMemory(uint32_t ID, bool pointerAccess); void finishNVMemory(); void freeNVMemory(uint32_t ID); private: WiFiUDP _udp; + void initNVMemory(); + MemoryBlock_t _memoryBlocks[MAX_MEMORY_BLOCKS]; + bool _MemoryInitialized = false; }; #endif diff --git a/src/esp_platform.cpp b/src/esp_platform.cpp index 76fc44d..6299d82 100644 --- a/src/esp_platform.cpp +++ b/src/esp_platform.cpp @@ -85,34 +85,132 @@ int EspPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) return len; } -bool EspPlatform::writeNVMemory(uintptr_t addr,uint8_t data) +bool EspPlatform::writeNVMemory(uint8_t* addr,uint8_t data) { - *((uint8_t*)addr) = data; + *addr = data; return true; } -uint8_t EspPlatform::readNVMemory(uintptr_t addr) +uint8_t EspPlatform::readNVMemory(uint8_t* addr) { - return *((uint8_t*)addr); + return *addr; } -uintptr_t EspPlatform::allocNVMemory(size_t size,uint32_t ID) +uint8_t* EspPlatform::allocNVMemory(size_t size,uint32_t ID) { - return (uintptr_t)EEPROM.getDataPtr(); + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + fatalError(); + + + _memoryBlocks[i].data = (uint8_t*)malloc(size); + if(_memoryBlocks[i].data == NULL) + fatalError(); + + _memoryBlocks[i].ID = ID; + _memoryBlocks[i].size = size; + + return _memoryBlocks[i].data; } -uintptr_t EspPlatform::reloadNVMemory(uint32_t ID) +void EspPlatform::initNVMemory() { EEPROM.begin(1024); - return (uintptr_t)EEPROM.getDataPtr(); + uint32_t addr = 0; + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++){ + + if (EEPROM.read(addr++) != 0xBA || EEPROM.read(addr++) != 0xAD || EEPROM.read(addr++) != 0xC0 || EEPROM.read(addr++) != 0xDE){ + _memoryBlocks[i].ID = 0; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].data = NULL; + continue; + } + + ((uint8_t*)&_memoryBlocks[i].ID)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[3] = EEPROM.read(addr++); + + ((uint8_t*)&_memoryBlocks[i].size)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[3] = EEPROM.read(addr++); + + _memoryBlocks[i].data = EEPROM.getDataPtr() + addr; + addr += _memoryBlocks[i].size; + } +} + +uint8_t* EspPlatform::reloadNVMemory(uint32_t ID, bool pointerAccess) +{ + if(!_MemoryInitialized) + initNVMemory(); + + _MemoryInitialized=true; + + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return 0; + + + return _memoryBlocks[i].data; } void EspPlatform::finishNVMemory() { + uint32_t addr = 0; + + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++) + { + if(_memoryBlocks[i].ID == 0) + continue; + + //write valid mask + EEPROM.write(addr++,0xBA); + EEPROM.write(addr++,0xAD); + EEPROM.write(addr++,0xC0); + EEPROM.write(addr++,0xDE); + + //write ID + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[3]); + + //write size + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[3]); + + //write data + for (uint32_t e=0;e<_memoryBlocks[i].size;e++){ + EEPROM.write(addr++,_memoryBlocks[i].data[e]); + } + } EEPROM.commit(); } void EspPlatform::freeNVMemory(uint32_t ID) { + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return; + + _memoryBlocks[i].data = NULL; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].ID = 0; } #endif diff --git a/src/esp_platform.h b/src/esp_platform.h index 9487fd1..daa1348 100644 --- a/src/esp_platform.h +++ b/src/esp_platform.h @@ -3,6 +3,13 @@ #include #include +#define MAX_MEMORY_BLOCKS 6 + +typedef struct{ + uint32_t ID; + size_t size; + uint8_t* data; +}MemoryBlock_t; class EspPlatform : public ArduinoPlatform { @@ -29,14 +36,17 @@ class EspPlatform : public ArduinoPlatform int readBytes(uint8_t* buffer, uint16_t maxLen) override; //memory - bool writeNVMemory(uintptr_t addr,uint8_t data); - uint8_t readNVMemory(uintptr_t addr); - uintptr_t allocNVMemory(size_t size,uint32_t ID); - uintptr_t reloadNVMemory(uint32_t ID); + bool writeNVMemory(uint8_t* addr,uint8_t data); + uint8_t readNVMemory(uint8_t* addr); + uint8_t* allocNVMemory(size_t size,uint32_t ID); + uint8_t* reloadNVMemory(uint32_t ID, bool pointerAccess); void finishNVMemory(); void freeNVMemory(uint32_t ID); private: WiFiUDP _udp; + void initNVMemory(); + MemoryBlock_t _memoryBlocks[MAX_MEMORY_BLOCKS]; + bool _MemoryInitialized = false; }; #endif diff --git a/src/knx/address_table_object.cpp b/src/knx/address_table_object.cpp index c5ea3ec..c496779 100644 --- a/src/knx/address_table_object.cpp +++ b/src/knx/address_table_object.cpp @@ -51,18 +51,12 @@ uint16_t AddressTableObject::getTsap(uint16_t addr) #pragma region SaveRestore -uint8_t* AddressTableObject::save(uint8_t* buffer) -{ - return TableObject::save(buffer); -} -uint8_t* AddressTableObject::restore(uint8_t* buffer) +void AddressTableObject::restore(uint8_t* startAddr) { - buffer = TableObject::restore(buffer); + TableObject::restore(startAddr); _groupAddresses = (uint16_t*)data(); - - return buffer; } #pragma endregion diff --git a/src/knx/address_table_object.h b/src/knx/address_table_object.h index 28ce2bc..aab37c5 100644 --- a/src/knx/address_table_object.h +++ b/src/knx/address_table_object.h @@ -19,8 +19,7 @@ class AddressTableObject : public TableObject */ AddressTableObject(Platform& platform); void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - uint8_t* save(uint8_t* buffer); - uint8_t* restore(uint8_t* buffer); + void restore(uint8_t* startAddr); /** * returns the number of group addresses of the object. */ diff --git a/src/knx/application_program_object.cpp b/src/knx/application_program_object.cpp index ad37fca..357893c 100644 --- a/src/knx/application_program_object.cpp +++ b/src/knx/application_program_object.cpp @@ -61,17 +61,20 @@ uint8_t * ApplicationProgramObject::data(uint32_t addr) uint8_t ApplicationProgramObject::getByte(uint32_t addr) { - return *(TableObject::data() + addr); + uint8_t* paddr = TableObject::data()+addr; + return _platform.popNVMemoryByte(&paddr); } uint16_t ApplicationProgramObject::getWord(uint32_t addr) { - return ::getWord(TableObject::data() + addr); + uint8_t* paddr = TableObject::data()+addr; + return _platform.popNVMemoryWord(&paddr); } uint32_t ApplicationProgramObject::getInt(uint32_t addr) { - return ::getInt(TableObject::data() + addr); + uint8_t* paddr = TableObject::data()+addr; + return _platform.popNVMemoryInt(&paddr); } uint32_t ApplicationProgramObject::size(){ @@ -79,42 +82,20 @@ uint32_t ApplicationProgramObject::size(){ } -uint8_t* ApplicationProgramObject::save() +void ApplicationProgramObject::save() { if(TableObject::data() == NULL) - return NULL; + return ; - uint8_t* buffer; - uintptr_t addr =(uintptr_t)(TableObject::data() - sizeof(_programVersion) - TableObject::sizeMetadata()); - if(TableObject::_platform.NVMemoryType() == internalFlash) - buffer = new uint8_t[sizeof(_programVersion)]; - else - buffer = (uint8_t*)addr; - - pushByteArray(_programVersion, sizeof(_programVersion), buffer); - - if(TableObject::_platform.NVMemoryType() == internalFlash){ - for(uint32_t i=0;irestore(data); - } } -void Memory::writeFlashMemory() +void Memory::writeMemory() { for (int i = 0; i < _saveCount; i++){ _saveRestores[i]->save(); @@ -73,133 +43,6 @@ void Memory::writeFlashMemory() _modified = false; } -void Memory::readRamMemory() -{ - _data = (uint8_t*)_platform.reloadNVMemory(1); - - if (_data[0] != 0x00 || _data[1] != 0xAD || _data[2] != 0xAF || _data[3] != 0xFE) - return; - - uint8_t* buffer = _data + 4; - int size = _saveCount; - for (int i = 0; i < size; i++) - { - buffer = _saveRestores[i]->restore(buffer); - buffer = (uint8_t*)(((uintptr_t)buffer + 3) / 4 * 4); //allign to 32bit - } -} - -void Memory::writeRamMemory() -{ - uint32_t bytesToSave = 10; - - for (int i = 0; i < _saveCount; i++){ - bytesToSave += _saveRestores[i]->size(); - } - - _data = (uint8_t*)_platform.allocNVMemory(bytesToSave,BASE_ID); - - _data[0] = 0x00; - _data[1] = 0xAD; - _data[2] = 0xAF; - _data[3] = 0xFE; - - uint8_t* buffer = _data + 4; - int size = _saveCount; - for (int i = 0; i < size; i++) - { - buffer = _saveRestores[i]->save(buffer); - buffer = (uint8_t*)(((uintptr_t)buffer + 3) / 4 * 4); //allign to 32bit - } - _platform.finishNVMemory(); - _modified = false; -} - - - - -void Memory::readExternalMemory() -{ - - int size = _saveCount; - volatile uintptr_t addr = _platform.reloadNVMemory(BASE_ID); - volatile uint32_t bytesToRestore; - - if(addr == 0) - return; - - - if (_platform.readNVMemory(addr++) != 0x00 || _platform.readNVMemory(addr++) != 0xAD || _platform.readNVMemory(addr++) != 0xAF || _platform.readNVMemory(addr++) != 0xFE) - return; - - - for (int i = 0; i < size; i++) - { - ((uint8_t*)&bytesToRestore)[0] = _platform.readNVMemory(addr++); - ((uint8_t*)&bytesToRestore)[1] = _platform.readNVMemory(addr++); - ((uint8_t*)&bytesToRestore)[2] = _platform.readNVMemory(addr++); - ((uint8_t*)&bytesToRestore)[3] = _platform.readNVMemory(addr++); - - if(bytesToRestore == 0) - continue; - _data = _platform.allocMemory(bytesToRestore); - if(_data == NULL) - _platform.fatalError(); - - for (uint32_t e=0;erestore(_data); - } -} - -void Memory::writeExternalMemory() -{ - uint32_t bytesToSave = 4; - int size = _saveCount; - - _platform.freeNVMemory(BASE_ID); - - for (int i = 0; i < size; i++){ - bytesToSave += _saveRestores[i]->size() + 4; - } - - uintptr_t addr = _platform.allocNVMemory(bytesToSave,BASE_ID); - - //write valid mask - _platform.writeNVMemory(addr++,0x00); - _platform.writeNVMemory(addr++,0xAD); - _platform.writeNVMemory(addr++,0xAF); - _platform.writeNVMemory(addr++,0xFE); - - for (int i = 0; i < size; i++) - { - _data = _saveRestores[i]->save(); - if(_data == NULL) - bytesToSave = 0; - else - bytesToSave = _saveRestores[i]->size(); - - //write size - _platform.writeNVMemory(addr++,((uint8_t*)&bytesToSave)[0]); - _platform.writeNVMemory(addr++,((uint8_t*)&bytesToSave)[1]); - _platform.writeNVMemory(addr++,((uint8_t*)&bytesToSave)[2]); - _platform.writeNVMemory(addr++,((uint8_t*)&bytesToSave)[3]); - - if(bytesToSave == 0) - continue; - - - for (uint32_t e=0;e= MAXSAVE - 1) diff --git a/src/knx/memory.h b/src/knx/memory.h index 7661c1e..b9831ec 100644 --- a/src/knx/memory.h +++ b/src/knx/memory.h @@ -16,12 +16,6 @@ public: void writeMemory(); void addSaveRestore(SaveRestore* obj); private: - void readFlashMemory(); - void writeFlashMemory(); - void readRamMemory(); - void writeRamMemory(); - void readExternalMemory(); - void writeExternalMemory(); Platform& _platform; bool _modified = false; SaveRestore* _saveRestores[MAXSAVE] = {0}; diff --git a/src/knx/platform.cpp b/src/knx/platform.cpp index fef1c8f..72c4227 100644 --- a/src/knx/platform.cpp +++ b/src/knx/platform.cpp @@ -3,7 +3,7 @@ #include -uint8_t* Platform::memoryReference() +uint8_t* Platform::referenceNVMemory() { return _memoryReference; } @@ -38,3 +38,58 @@ Platform::Platform() free(_memoryReference); _memoryReference -= 1024; } + +uint8_t Platform::popNVMemoryByte(uint8_t** addr) +{ + uint8_t val = readNVMemory(*addr); + (*addr)+=1; + return val; +} + +uint16_t Platform::popNVMemoryWord(uint8_t** addr) +{ + uint16_t val = (readNVMemory(*addr) << 8) + readNVMemory((*addr)+1); + (*addr)+=2; + return val; +} + +uint32_t Platform::popNVMemoryInt(uint8_t** addr) +{ + uint32_t val = (readNVMemory((*addr)) << 24) + (readNVMemory((*addr)+1) << 16) + (readNVMemory((*addr)+2) << 8) + readNVMemory((*addr)+3); + (*addr)+=4; + return val; +} + +void Platform::popNVMemoryArray(uint8_t* dest, uint8_t** addr, size_t size){ + for(size_t i=0;i> 8) & 0xff)); + writeNVMemory((*addr)+1, (val & 0xff)); + (*addr) += 2; +} + +void Platform::pushNVMemoryInt(uint32_t val, uint8_t** addr) +{ + writeNVMemory((*addr), ((val >> 24) & 0xff)); + writeNVMemory((*addr)+1, ((val >> 16) & 0xff)); + writeNVMemory((*addr)+2, ((val >> 8) & 0xff)); + writeNVMemory((*addr)+3, (val & 0xff)); + (*addr) += 4; +} + +void Platform::pushNVMemoryArray(uint8_t* src, uint8_t** addr, size_t size){ + for(size_t i=0;i #include "save_restore.h" -typedef enum{ - notDefined, - internalRam, - internalFlash, - external -}NVMemory_t; - class Platform { public: @@ -36,18 +29,92 @@ class Platform virtual int readUart() = 0; virtual size_t readBytesUart(uint8_t* buffer, size_t length) = 0; - virtual bool writeNVMemory(uintptr_t addr,uint8_t data) = 0; - virtual uint8_t readNVMemory(uintptr_t addr) = 0; - virtual uintptr_t allocNVMemory(size_t size,uint32_t ID) = 0; - virtual uintptr_t reloadNVMemory(uint32_t ID) = 0; + /** + * Provides a memory block for an interface object. + * Hereby, the type of memory is not important, as long as at the latest with finishNVMemory(), the data is written to a non-volatile memory. + * Is called by the stack every time ETS wants to store data (device, application, association, ....) + * The data itself is then written by writeNVMemory() + * + * @param size The number of bytes to allocate + * + * @param ID Unique identifier that represents the new memory block, even after reset + * + * @return The start address of the created memory block + */ + virtual uint8_t* allocNVMemory(size_t size,uint32_t ID) = 0; + + /** + * Write one single byte to previously allocated (allocNVMemory()) or reloaded (reloadNVMemory()) memory block + * Is called by the stack during ETS programming to store interface object data and before reset (save()) to store object status + * + * @param addr The address where to store the data + * + * @param data The value of the data which sould be stored + * + */ + virtual bool writeNVMemory(uint8_t* addr,uint8_t data) = 0; + + /** + * Reads one single byte from previously allocated (allocNVMemory()) or reloaded (reloadNVMemory()) memory block + * Is called by the stack during power up (restore()) and every time the application reads ETS parameter values (knx.paramByte()) + * + * @param addr The address where to read from + * + * @return The value of the data byte which was read + * + */ + virtual uint8_t readNVMemory(uint8_t* addr) = 0; + + /** + * Returns existing memory block identified by the ID, even after reset + * Is called by the stack during power up (restore()) + * + * @param ID Unique identifier that represents a previously allocated memory block + * + * @param pointerAccess TRUE if the memory block must be accessible through pointer dereferencing, otherwise FALSE + * + * @return The start address of the memory block represented by ID or NULL if ID is not available + * + */ + virtual uint8_t* reloadNVMemory(uint32_t ID, bool pointerAccess) = 0; + + /** + * Is called by the stack after every ETS programming cycle (save()) + * This function may be used to write ram buffered memory block to a non-volatile one + * + */ virtual void finishNVMemory() = 0; + + /** + * Frees existing memory block identified by the ID + * Is called by the stack every time ETS wants to store new data and before it allocates new one + * + * @param ID Unique identifier that represents a previously allocated memory block + * + */ virtual void freeNVMemory(uint32_t ID) = 0; - virtual uint8_t* memoryReference(); + /** + * Provides the offset of the NVMemory address to the ETS address space (16bit) + * highest NVMemory address - referenceNVMemory() <= 16bit + * + * @return The offset address if NVMemory address space is >16bit otherwise NULL + * + */ + virtual uint8_t* referenceNVMemory(); + + virtual uint8_t* allocMemory(size_t size); virtual void freeMemory(uint8_t* ptr); - NVMemory_t NVMemoryType(){return _NVMemoryType;} + + uint8_t popNVMemoryByte(uint8_t** addr); + uint16_t popNVMemoryWord(uint8_t** addr); + uint32_t popNVMemoryInt(uint8_t** addr); + void popNVMemoryArray(uint8_t* dest, uint8_t** addr, size_t size); + void pushNVMemoryByte(uint8_t val, uint8_t** addr); + void pushNVMemoryWord(uint16_t val, uint8_t** addr); + void pushNVMemoryInt(uint32_t val, uint8_t** addr); + void pushNVMemoryArray(uint8_t* src, uint8_t** addr, size_t size); protected: uint8_t* _memoryReference = 0; - NVMemory_t _NVMemoryType = notDefined; }; diff --git a/src/knx/save_restore.h b/src/knx/save_restore.h index 74d28e5..37b429a 100644 --- a/src/knx/save_restore.h +++ b/src/knx/save_restore.h @@ -8,26 +8,18 @@ class SaveRestore { public: /** - * This method is called when the object should save its state to the buffer. - * - * @param buffer The buffer the object should save its state to. - * - * @return The buffer plus the size of the object state. The next object will use this value as - * the start of its buffer. + * This method is called when the object should save its state. */ - virtual uint8_t* save(uint8_t* buffer) = 0; - virtual uint8_t* save() = 0; + virtual void save() = 0; /** - * This method is called when the object should restore its state from the buffer. + * This method is called when the object should restore its state from the given address. * - * @param buffer The buffer the object should restore its state from. + * @param startAddr The startAddr the object should restore its state from. * - * @return The buffer plus the size of the object state. The next object will use this value as - * the start of its buffer. */ - virtual uint8_t* restore(uint8_t* buffer) = 0; + virtual void restore(uint8_t* startAddr) = 0; virtual uint32_t size() = 0; void memoryID (uint32_t ID){_ID = ID;} protected: uint32_t _ID; -}; \ No newline at end of file +}; diff --git a/src/knx/table_object.cpp b/src/knx/table_object.cpp index ccfc7ac..9b368eb 100644 --- a/src/knx/table_object.cpp +++ b/src/knx/table_object.cpp @@ -83,83 +83,41 @@ void TableObject::loadState(LoadState newState) _state = newState; } - -uint8_t* TableObject::save(uint8_t* buffer) -{ - buffer = pushByte(_state, buffer); - buffer = pushByte(_errorCode, buffer); - buffer = pushInt(_size, buffer); - buffer = pushByteArray(_data, _size, buffer); - - return buffer; -} - -uint8_t* TableObject::save() +void TableObject::save() { if(_data == NULL) - return NULL; + return; - uintptr_t addr; - uint8_t* buffer; - addr =(uintptr_t)(_data - METADATA_SIZE); - if(_platform.NVMemoryType() == internalFlash) - buffer = new uint8_t[METADATA_SIZE]; - else - buffer = (uint8_t*)addr; + uint8_t* addr =_data - METADATA_SIZE; - buffer = pushByte(_state, buffer); - buffer = pushByte(_errorCode, buffer); - buffer = pushInt(_size, buffer); - buffer -= METADATA_SIZE; - - if(_platform.NVMemoryType() == internalFlash){ - for(uint32_t i=0;i 0) - _data = buffer; - + _data = addr; else _data = 0; - - buffer += _size; - - return buffer; } uint32_t TableObject::tableReference() { - return (uint32_t)(_data - _platform.memoryReference()); + return (uint32_t)(_data - _platform.referenceNVMemory()); } bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte) { - if (_dataComplete) + if (_data) { - if(_platform.NVMemoryType() == internalFlash) - _platform.freeNVMemory(_ID); - else if(_platform.NVMemoryType() == external) - _platform.freeMemory(_dataComplete); - _dataComplete = 0; + _platform.freeNVMemory(_ID); _data = 0; _size = 0; } @@ -167,23 +125,13 @@ bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte) if (size == 0) return true; - if(_platform.NVMemoryType() == internalFlash){ - _dataComplete = (uint8_t*)_platform.allocNVMemory(size+this->size(), _ID); - } - else{ - _dataComplete = _platform.allocMemory(size+this->size()); - } - _data = _dataComplete + this->size(); //skip metadata + _data = _platform.allocNVMemory(size+this->size(), _ID); + _data = _data + this->size(); //skip metadata _size = size; if (doFill){ - if(_platform.NVMemoryType() == internalFlash){ - uintptr_t addr = (uintptr_t)_data; - for(size_t i=0; i<_size;i++) - _platform.writeNVMemory(addr++, fillByte); - } - else{ - memset(_data, fillByte, _size); - } + uint8_t* addr = _data; + for(size_t i=0; i<_size;i++) + _platform.writeNVMemory(addr++, fillByte); } return true; } diff --git a/src/knx/table_object.h b/src/knx/table_object.h index f256451..3d41b78 100644 --- a/src/knx/table_object.h +++ b/src/knx/table_object.h @@ -25,9 +25,8 @@ public: * This method returns the ::LoadState of the interface object. */ LoadState loadState(); - virtual uint8_t* save(uint8_t* buffer); - virtual uint8_t* save(); - virtual uint8_t* restore(uint8_t* buffer); + virtual void save(); + virtual void restore(uint8_t* startAddr); virtual uint32_t size(); protected: /** @@ -53,7 +52,6 @@ protected: void errorCode(ErrorCode errorCode); Platform& _platform; - uint8_t *_dataComplete = 0; private: uint32_t tableReference(); bool allocTable(uint32_t size, bool doFill, uint8_t fillByte); diff --git a/src/knx_facade.h b/src/knx_facade.h index 5144d90..719b692 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -19,7 +19,7 @@ #endif void buttonUp(); -typedef uint8_t* (*saveRestoreCallback)(uint8_t* buffer); +typedef void (*saveRestoreCallback)(uint8_t* buffer); template class KnxFacade : private SaveRestore { @@ -288,24 +288,18 @@ template class KnxFacade : private SaveRestore return 0; } - uint8_t* save(uint8_t* buffer) + void save() { if (_saveCallback != 0) - return _saveCallback(buffer); - - return buffer; + _saveCallback(NULL); } - uint8_t* save() - { - }; - uint8_t* restore(uint8_t* buffer) + void restore(uint8_t* startAddr) { if (_restoreCallback != 0) - return _restoreCallback(buffer); + _restoreCallback(startAddr); - return buffer; } }; diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp index ad2f4ac..9b67cbe 100644 --- a/src/linux_platform.cpp +++ b/src/linux_platform.cpp @@ -200,31 +200,86 @@ int LinuxPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) return len; } -bool LinuxPlatform::writeNVMemory(uintptr_t addr,uint8_t data) +bool LinuxPlatform::writeNVMemory(uint8_t* addr,uint8_t data) { - *((uint8_t*)addr) = data; + *addr = data; return true; } -uint8_t LinuxPlatform::readNVMemory(uintptr_t addr) +uint8_t LinuxPlatform::readNVMemory(uint8_t* addr) { - return *((uint8_t*)addr); + return *addr; } -uintptr_t LinuxPlatform::allocNVMemory(size_t size,uint32_t ID) +uint8_t* LinuxPlatform::allocNVMemory(size_t size,uint32_t ID) +{ + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + fatalError(); + + + _memoryBlocks[i].data = (uint8_t*)malloc(size); + if(_memoryBlocks[i].data == NULL) + fatalError(); + + _memoryBlocks[i].ID = ID; + _memoryBlocks[i].size = size; + + return _memoryBlocks[i].data; +} + +void LinuxPlatform::initNVMemory() { if (_fd < 0) doMemoryMapping(); - - return (uintptr_t)(_mappedFile + 2); + + uint8_t* addr = (_mappedFile + 2); + + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++){ + + if (*addr++ != 0xBA || *addr++ != 0xAD || *addr++ != 0xC0 || *addr++ != 0xDE){ + _memoryBlocks[i].ID = 0; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].data = NULL; + continue; + } + + ((uint8_t*)&_memoryBlocks[i].ID)[0] = *addr++; + ((uint8_t*)&_memoryBlocks[i].ID)[1] = *addr++; + ((uint8_t*)&_memoryBlocks[i].ID)[2] = *addr++; + ((uint8_t*)&_memoryBlocks[i].ID)[3] = *addr++; + + ((uint8_t*)&_memoryBlocks[i].size)[0] = *addr++; + ((uint8_t*)&_memoryBlocks[i].size)[1] = *addr++; + ((uint8_t*)&_memoryBlocks[i].size)[2] = *addr++; + ((uint8_t*)&_memoryBlocks[i].size)[3] = *addr++; + + _memoryBlocks[i].data = addr; + addr += _memoryBlocks[i].size; + } } -uintptr_t LinuxPlatform::reloadNVMemory(uint32_t ID) +uint8_t* LinuxPlatform::reloadNVMemory(uint32_t ID, bool pointerAccess) { - if (_fd < 0) - doMemoryMapping(); - - return (uintptr_t)(_mappedFile + 2); + if(!_MemoryInitialized) + initNVMemory(); + + _MemoryInitialized=true; + + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return 0; + + + return _memoryBlocks[i].data; } void LinuxPlatform::finishNVMemory() @@ -232,12 +287,55 @@ void LinuxPlatform::finishNVMemory() if (_fd < 0) doMemoryMapping(); + uint8_t* addr = _mappedFile + 2; + + + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++) + { + if(_memoryBlocks[i].ID == 0) + continue; + + //write valid mask + *addr++ = 0xBA; + *addr++ = 0xAD; + *addr++ = 0xC0; + *addr++ = 0xDE; + + //write ID + *addr++ = ((uint8_t*)&_memoryBlocks[i].ID)[0]); + *addr++ = ((uint8_t*)&_memoryBlocks[i].ID)[1]); + *addr++ = ((uint8_t*)&_memoryBlocks[i].ID)[2]); + *addr++ = ((uint8_t*)&_memoryBlocks[i].ID)[3]); + + //write size + *addr++ = ((uint8_t*)&_memoryBlocks[i].size)[0]); + *addr++ = ((uint8_t*)&_memoryBlocks[i].size)[1]); + *addr++ = ((uint8_t*)&_memoryBlocks[i].size)[2]); + *addr++ = ((uint8_t*)&_memoryBlocks[i].size)[3]); + + //write data + for (uint32_t e=0;e<_memoryBlocks[i].size;e++){ + *addr++ = _memoryBlocks[i].data[e]); + } + } fsync(_fd); } void LinuxPlatform::freeNVMemory(uint32_t ID) { + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return; + + _memoryBlocks[i].data = NULL; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].ID = 0; } + #define FLASHSIZE 0x10000 void LinuxPlatform::doMemoryMapping() { diff --git a/src/linux_platform.h b/src/linux_platform.h index ac02e38..45919ef 100644 --- a/src/linux_platform.h +++ b/src/linux_platform.h @@ -5,6 +5,14 @@ #include #include "knx/platform.h" +#define MAX_MEMORY_BLOCKS 6 + +typedef struct{ + uint32_t ID; + size_t size; + uint8_t* data; +}MemoryBlock_t; + class LinuxPlatform: public Platform { using Platform::_memoryReference; @@ -44,12 +52,13 @@ public: size_t readBytesUart(uint8_t *buffer, size_t length) override; //memory - bool writeNVMemory(uintptr_t addr,uint8_t data); - uint8_t readNVMemory(uintptr_t addr); - uintptr_t allocNVMemory(size_t size,uint32_t ID); - uintptr_t reloadNVMemory(uint32_t ID); + bool writeNVMemory(uint8_t* addr,uint8_t data); + uint8_t readNVMemory(uint8_t* addr); + uint8_t* allocNVMemory(size_t size,uint32_t ID); + uint8_t* reloadNVMemory(uint32_t ID, bool pointerAccess); void finishNVMemory(); void freeNVMemory(uint32_t ID); + uint8_t* allocMemory(size_t size) override; void freeMemory(uint8_t* ptr) override; void cmdlineArgs(int argc, char** argv); @@ -64,6 +73,9 @@ public: uint8_t* _currentMaxMem = 0; std::string _flashFilePath = "flash.bin"; char** _args = 0; + void initNVMemory(); + MemoryBlock_t _memoryBlocks[MAX_MEMORY_BLOCKS]; + bool _MemoryInitialized = false; }; #endif diff --git a/src/samd_flash.cpp b/src/samd_flash.cpp index d51c5dc..a1cbd72 100644 --- a/src/samd_flash.cpp +++ b/src/samd_flash.cpp @@ -24,8 +24,8 @@ SamdFlash::SamdFlash(){ _info = (info_data_t*)getRowAddr(_pageSize*_pageCnt-1); //261888 (rowAddr of last row) } -uint32_t SamdFlash::getStartAddress(){ - return _info->freeMemoryStart; +uint8_t* SamdFlash::getStartAddress(){ + return (uint8_t*)_info->freeMemoryStart; } uint8_t SamdFlash::read(uint8_t* addr){ diff --git a/src/samd_flash.h b/src/samd_flash.h index 8617dee..ea3a558 100644 --- a/src/samd_flash.h +++ b/src/samd_flash.h @@ -31,7 +31,7 @@ public: bool write(uint8_t* addr, uint8_t data); uint8_t read(uint8_t* addr); void finalise(); - uint32_t getStartAddress(); + uint8_t* getStartAddress(); private: uint8_t* forcemalloc(uint32_t size, uint32_t ID); diff --git a/src/samd_platform.cpp b/src/samd_platform.cpp index 037dc17..88a954e 100644 --- a/src/samd_platform.cpp +++ b/src/samd_platform.cpp @@ -4,18 +4,27 @@ #include #include +#ifdef INTERN_FLASH_MEMORY #include "samd_flash.h" - SamdFlash Flash; +#endif +#ifdef EXTERN_EEPROM_MEMORY +#include "FlashAsEEPROM.h" +#endif +#ifdef RAM_EMULATED_MEMORY +#include "FlashAsEEPROM.h" +#endif + + SamdPlatform::SamdPlatform() : ArduinoPlatform(&Serial1) { - Platform::_NVMemoryType = internalFlash; + } SamdPlatform::SamdPlatform( HardwareSerial* s) : ArduinoPlatform(s) { - Platform::_NVMemoryType = internalFlash; + } void SamdPlatform::restart() @@ -24,31 +33,31 @@ void SamdPlatform::restart() NVIC_SystemReset(); } - -bool SamdPlatform::writeNVMemory(uintptr_t addr,uint8_t data) +#ifdef INTERN_FLASH_MEMORY +bool SamdPlatform::writeNVMemory(uint8_t* addr,uint8_t data) { - if(Flash.write((uint8_t*)addr, data)==false) + if(Flash.write(addr, data)==false) fatalError(); return true; } -uint8_t SamdPlatform::readNVMemory(uintptr_t addr) +uint8_t SamdPlatform::readNVMemory(uint8_t* addr) { - return Flash.read((uint8_t*)addr); + return Flash.read(addr); } -uintptr_t SamdPlatform::allocNVMemory(size_t size,uint32_t ID) +uint8_t* SamdPlatform::allocNVMemory(size_t size,uint32_t ID) { - uintptr_t addr = (uintptr_t)Flash.malloc(size, ID); + uint8_t* addr = Flash.malloc(size, ID); if(addr == 0) fatalError(); return addr; } -uintptr_t SamdPlatform::reloadNVMemory(uint32_t ID) +uint8_t* SamdPlatform::reloadNVMemory(uint32_t ID, bool pointerAccess) { // Flash.erase(); - return (uintptr_t)Flash.loadBlock(ID); + return Flash.loadBlock(ID); } void SamdPlatform::finishNVMemory() @@ -59,85 +68,293 @@ void SamdPlatform::finishNVMemory() void SamdPlatform::freeNVMemory(uint32_t ID) { Flash.free(ID); - // Flash.erase(); } -uint8_t* SamdPlatform::memoryReference() +uint8_t* SamdPlatform::referenceNVMemory() { return (uint8_t*)Flash.getStartAddress(); } +#endif - - -/*************_NVMemoryType = internalRam************************* - -bool SamdPlatform::writeNVMemory(uintptr_t addr,uint8_t data) +#ifdef EXTERN_EEPROM_MEMORY +bool SamdPlatform::writeNVMemory(uint8_t* addr,uint8_t data) { - *((uint8_t*)addr) = data; + *addr = data; return true; } -uint8_t SamdPlatform::readNVMemory(uintptr_t addr) +uint8_t SamdPlatform::readNVMemory(uint8_t* addr) { - return *((uint8_t*)addr); + return *addr; } -uintptr_t SamdPlatform::allocNVMemory(size_t size,uint32_t ID) +uint8_t* SamdPlatform::allocNVMemory(size_t size,uint32_t ID) { - if(size > EEPROM_EMULATION_SIZE) + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) fatalError(); - return (uintptr_t)EEPROM.getDataPtr(); + + + _memoryBlocks[i].data = (uint8_t*)malloc(size); + if(_memoryBlocks[i].data == NULL) + fatalError(); + + _memoryBlocks[i].ID = ID; + _memoryBlocks[i].size = size; + + return _memoryBlocks[i].data; } -uintptr_t SamdPlatform::reloadNVMemory(uint32_t ID) +void SamdPlatform::initNVMemory() { - return (uintptr_t)EEPROM.getDataPtr(); + uint32_t addr = 0; + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++){ + + if (EEPROM.read(addr++) != 0xBA || EEPROM.read(addr++) != 0xAD || EEPROM.read(addr++) != 0xC0 || EEPROM.read(addr++) != 0xDE){ + _memoryBlocks[i].ID = 0; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].data = NULL; + continue; + } + + ((uint8_t*)&_memoryBlocks[i].ID)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[3] = EEPROM.read(addr++); + + ((uint8_t*)&_memoryBlocks[i].size)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[3] = EEPROM.read(addr++); + + _memoryBlocks[i].data = (uint8_t*)malloc(_memoryBlocks[i].size); + if(_memoryBlocks[i].data == NULL) + fatalError(); + + //read data + for (uint32_t e=0;e<_memoryBlocks[i].size;e++){ + _memoryBlocks[i].data[e] = EEPROM.read(addr++); + } + } +} +uint8_t* SamdPlatform::reloadNVMemory(uint32_t ID, bool pointerAccess) +{ + if(!_MemoryInitialized) + initNVMemory(); + + _MemoryInitialized=true; + + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return 0; + + + return _memoryBlocks[i].data; } void SamdPlatform::finishNVMemory() { + uint32_t addr = 0; + + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++) + { + if(_memoryBlocks[i].ID == 0) + continue; + + //write valid mask + EEPROM.write(addr++,0xBA); + EEPROM.write(addr++,0xAD); + EEPROM.write(addr++,0xC0); + EEPROM.write(addr++,0xDE); + + //write ID + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[3]); + + //write size + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[3]); + + //write data + for (uint32_t e=0;e<_memoryBlocks[i].size;e++){ + EEPROM.write(addr++,_memoryBlocks[i].data[e]); + } + } EEPROM.commit(); } void SamdPlatform::freeNVMemory(uint32_t ID) { -} -/* + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return; -/*************_NVMemoryType = external************************* -bool SamdPlatform::writeNVMemory(uintptr_t addr,uint8_t data) + free(_memoryBlocks[i].data); + _memoryBlocks[i].data = NULL; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].ID = 0; +} + + +uint8_t* SamdPlatform::referenceNVMemory() { - EEPROM.write(addr-1, data); + return (uint8_t*)0x20000000; //ram base address +} + +#endif + +#ifdef RAM_EMULATED_MEMORY +bool SamdPlatform::writeNVMemory(uint8_t* addr,uint8_t data) +{ + *addr = data; return true; } -uint8_t SamdPlatform::readNVMemory(uintptr_t addr) +uint8_t SamdPlatform::readNVMemory(uint8_t* addr) { - return EEPROM.read(addr-1); + return *addr; } -uintptr_t SamdPlatform::allocNVMemory(size_t size,uint32_t ID) +uint8_t* SamdPlatform::allocNVMemory(size_t size,uint32_t ID) { - if(size > EEPROM_EMULATION_SIZE) + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) fatalError(); - return 1; + + + _memoryBlocks[i].data = (uint8_t*)malloc(size); + if(_memoryBlocks[i].data == NULL) + fatalError(); + + _memoryBlocks[i].ID = ID; + _memoryBlocks[i].size = size; + + return _memoryBlocks[i].data; } -uintptr_t SamdPlatform::reloadNVMemory(uint32_t ID) +void SamdPlatform::initNVMemory() { - return 1; + uint32_t addr = 0; + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++){ + + if (EEPROM.read(addr++) != 0xBA || EEPROM.read(addr++) != 0xAD || EEPROM.read(addr++) != 0xC0 || EEPROM.read(addr++) != 0xDE){ + _memoryBlocks[i].ID = 0; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].data = NULL; + continue; + } + + ((uint8_t*)&_memoryBlocks[i].ID)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].ID)[3] = EEPROM.read(addr++); + + ((uint8_t*)&_memoryBlocks[i].size)[0] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[1] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[2] = EEPROM.read(addr++); + ((uint8_t*)&_memoryBlocks[i].size)[3] = EEPROM.read(addr++); + + _memoryBlocks[i].data = EEPROM.getDataPtr() + addr; + addr += _memoryBlocks[i].size; + } +} + +uint8_t* SamdPlatform::reloadNVMemory(uint32_t ID, bool pointerAccess) +{ + if(!_MemoryInitialized) + initNVMemory(); + + _MemoryInitialized=true; + + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return 0; + + + return _memoryBlocks[i].data; } void SamdPlatform::finishNVMemory() { + uint32_t addr = 0; + + for (int i = 0; i < MAX_MEMORY_BLOCKS; i++) + { + if(_memoryBlocks[i].ID == 0) + continue; + + //write valid mask + EEPROM.write(addr++,0xBA); + EEPROM.write(addr++,0xAD); + EEPROM.write(addr++,0xC0); + EEPROM.write(addr++,0xDE); + + //write ID + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].ID)[3]); + + //write size + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[0]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[1]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[2]); + EEPROM.write(addr++,((uint8_t*)&_memoryBlocks[i].size)[3]); + + //write data + for (uint32_t e=0;e<_memoryBlocks[i].size;e++){ + EEPROM.write(addr++,_memoryBlocks[i].data[e]); + } + } EEPROM.commit(); } void SamdPlatform::freeNVMemory(uint32_t ID) { + int i; + for(i=0;i= MAX_MEMORY_BLOCKS) + return; + + _memoryBlocks[i].data = NULL; + _memoryBlocks[i].size = 0; + _memoryBlocks[i].ID = 0; } -*/ + +uint8_t* SamdPlatform::referenceNVMemory() +{ + return (uint8_t*)0x20000000; //ram base address +} + +#endif #endif diff --git a/src/samd_platform.h b/src/samd_platform.h index 288cb17..7412aeb 100644 --- a/src/samd_platform.h +++ b/src/samd_platform.h @@ -4,6 +4,21 @@ #ifdef ARDUINO_ARCH_SAMD +//define which memory type is used for non-volatile memory +#define INTERN_FLASH_MEMORY +//#define EXTERN_EEPROM_MEMORY +//#define RAM_EMULATED_MEMORY //like FlashStorage lib + +#ifndef INTERN_FLASH_MEMORY +#define MAX_MEMORY_BLOCKS 6 + +typedef struct{ + uint32_t ID; + size_t size; + uint8_t* data; +}MemoryBlock_t; +#endif + class SamdPlatform : public ArduinoPlatform { public: @@ -11,13 +26,19 @@ public: SamdPlatform( HardwareSerial* s); void restart(); - bool writeNVMemory(uintptr_t addr,uint8_t data); - uint8_t readNVMemory(uintptr_t addr); - uintptr_t allocNVMemory(size_t size,uint32_t ID); - uintptr_t reloadNVMemory(uint32_t ID); + bool writeNVMemory(uint8_t* addr,uint8_t data); + uint8_t readNVMemory(uint8_t* addr); + uint8_t* allocNVMemory(size_t size,uint32_t ID); + uint8_t* reloadNVMemory(uint32_t ID, bool pointerAccess); void finishNVMemory(); void freeNVMemory(uint32_t ID); - uint8_t* memoryReference(); + uint8_t* referenceNVMemory(); +private: +#ifndef INTERN_FLASH_MEMORY + void initNVMemory(); + MemoryBlock_t _memoryBlocks[MAX_MEMORY_BLOCKS]; + bool _MemoryInitialized = false; +#endif }; #endif