put non-volatile memory type dependet stuff into platform

This commit is contained in:
Bernhard 2019-10-16 22:28:17 +02:00
parent 1226103126
commit 5386a3c833
31 changed files with 912 additions and 572 deletions

View File

@ -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;i++){
if(_memoryBlocks[i].ID == 0)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(i >= MAX_MEMORY_BLOCKS)
return;
_memoryBlocks[i].data = NULL;
_memoryBlocks[i].size = 0;
_memoryBlocks[i].ID = 0;
}
#endif

View File

@ -3,6 +3,13 @@
#include <WiFi.h>
#include <WiFiUdp.h>
#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

View File

@ -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;i++){
if(_memoryBlocks[i].ID == 0)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(i >= MAX_MEMORY_BLOCKS)
return;
_memoryBlocks[i].data = NULL;
_memoryBlocks[i].size = 0;
_memoryBlocks[i].ID = 0;
}
#endif

View File

@ -3,6 +3,13 @@
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#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

View File

@ -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

View File

@ -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.
*/

View File

@ -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;i<sizeof(_programVersion);i++)
TableObject::_platform.writeNVMemory(addr+i, buffer[i]);
delete[] buffer;
}
return TableObject::save();
uint8_t* addr =TableObject::data() - sizeof(_programVersion) - TableObject::sizeMetadata();
_platform.pushNVMemoryArray(_programVersion, &addr, sizeof(_programVersion));
TableObject::save();
}
uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
void ApplicationProgramObject::restore(uint8_t* startAddr)
{
buffer = pushByteArray(_programVersion, 5, buffer);
return TableObject::save(buffer);
}
uint8_t* ApplicationProgramObject::restore(uint8_t* buffer)
{
TableObject::_dataComplete = buffer;
buffer = popByteArray(_programVersion, 5, buffer);
return TableObject::restore(buffer);
_platform.popNVMemoryArray(_programVersion, &startAddr, sizeof(_programVersion));
TableObject::restore(startAddr);
}
static PropertyDescription _propertyDescriptions[] =

View File

@ -13,9 +13,8 @@ class ApplicationProgramObject : public TableObject
uint8_t getByte(uint32_t addr);
uint16_t getWord(uint32_t addr);
uint32_t getInt(uint32_t addr);
uint8_t* save(uint8_t* buffer);
uint8_t* save();
uint8_t* restore(uint8_t* buffer);
void save();
void restore(uint8_t* startAddr);
uint32_t size();
protected:

View File

@ -45,16 +45,10 @@ uint16_t AssociationTableObject::getASAP(uint16_t idx)
return ntohs(_tableData[2 * idx + 2]);
}
uint8_t* AssociationTableObject::save(uint8_t* buffer)
void AssociationTableObject::restore(uint8_t* startAddr)
{
return TableObject::save(buffer);
}
uint8_t* AssociationTableObject::restore(uint8_t* buffer)
{
buffer = TableObject::restore(buffer);
TableObject::restore(startAddr);
_tableData = (uint16_t*)data();
return buffer;
}
// return type is int32 so that we can return uint16 and -1

View File

@ -8,8 +8,7 @@ class AssociationTableObject : public TableObject
AssociationTableObject(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);
int32_t translateAsap(uint16_t asap);
int32_t nextAsap(uint16_t tsap, uint16_t& startIdx);

View File

@ -9,11 +9,11 @@ BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platfo
{
_appLayer.transportLayer(_transLayer);
_transLayer.networkLayer(_netLayer);
_memory.addSaveRestore(&_deviceObj);
_memory.addSaveRestore(&_appProgram);
_memory.addSaveRestore(&_addrTable);
_memory.addSaveRestore(&_assocTable);
_memory.addSaveRestore(&_groupObjTable);
_memory.addSaveRestore(&_deviceObj);
_memory.addSaveRestore(&_appProgram);
}
void BauSystemB::loop()
@ -139,12 +139,9 @@ void BauSystemB::deviceDescriptorReadIndication(Priority priority, HopCountType
void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint16_t memoryAddress, uint8_t * data)
{
if(_platform.NVMemoryType() == internalFlash){
for(uint8_t i=0;i<number;i++)
_platform.writeNVMemory((uintptr_t)_platform.memoryReference() + memoryAddress+i, data[i]);
}
else
memcpy(_platform.memoryReference() + memoryAddress, data, number);
for(uint8_t i=0;i<number;i++)
_platform.writeNVMemory(_platform.referenceNVMemory() + memoryAddress+i, data[i]);
_memory.memoryModified();
@ -155,18 +152,12 @@ void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType,
void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
uint16_t memoryAddress)
{
if(_platform.NVMemoryType() == internalFlash){
uint8_t* buffer = new uint8_t[number];
for(uint8_t i=0;i<number;i++)
buffer[i] = _platform.readNVMemory((uintptr_t)_platform.memoryReference() + memoryAddress+i);
uint8_t* buffer = new uint8_t[number];
for(uint8_t i=0;i<number;i++)
buffer[i] = _platform.readNVMemory(_platform.referenceNVMemory() + memoryAddress+i);
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer);
delete[] buffer;
}
else{
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
_platform.memoryReference() + memoryAddress);
}
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer);
delete[] buffer;
}
void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap)
@ -183,30 +174,19 @@ void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, ui
void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress)
{
if(_platform.NVMemoryType() == internalFlash){
uint8_t* buffer = new uint8_t[number];
for(uint8_t i=0;i<number;i++)
buffer[i] = _platform.readNVMemory((uintptr_t)_platform.memoryReference() + memoryAddress+i);
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer);
delete[] buffer;
}
else{
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
_platform.memoryReference() + memoryAddress);
}
uint8_t* buffer = new uint8_t[number];
for(uint8_t i=0;i<number;i++)
buffer[i] = _platform.readNVMemory(_platform.referenceNVMemory() + memoryAddress+i);
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer);
delete[] buffer;
}
void BauSystemB::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* data)
{
if(_platform.NVMemoryType() == internalFlash){
for(uint8_t i=0;i<number;i++)
_platform.writeNVMemory((uintptr_t)_platform.memoryReference() + memoryAddress+i, data[i]);
}
else{
memcpy(_platform.memoryReference() + memoryAddress, data, number);
}
_memory.memoryModified();
for(uint8_t i=0;i<number;i++)
_platform.writeNVMemory(_platform.referenceNVMemory() + memoryAddress+i, data[i]);
_memory.memoryModified();
if (_deviceObj.verifyMode())
userMemoryReadIndication(priority, hopType, asap, number, memoryAddress);
}

View File

@ -119,43 +119,23 @@ uint32_t DeviceObject::size(){
return METADATA_SIZE;
}
uint8_t* DeviceObject::save()
void DeviceObject::save()
{
uint8_t* buffer = new uint8_t[METADATA_SIZE];
_platform.freeNVMemory(_ID);
uint8_t* addr = _platform.allocNVMemory(METADATA_SIZE, _ID);
buffer = pushByte(_deviceControl, buffer);
buffer = pushByte(_routingCount, buffer);
buffer = pushWord(_ownAddress, buffer);
buffer -= METADATA_SIZE;
if(_platform.NVMemoryType() == internalFlash){
_platform.freeNVMemory(_ID);
uintptr_t addr = _platform.allocNVMemory(METADATA_SIZE, _ID);
for(size_t i=0;i<METADATA_SIZE;i++)
_platform.writeNVMemory(addr+i, buffer[i]);
delete[] buffer;
return (uint8_t*)addr;
}
return buffer;
}
uint8_t* DeviceObject::save(uint8_t* buffer)
{
buffer = pushByte(_deviceControl, buffer);
buffer = pushByte(_routingCount, buffer);
buffer = pushWord(_ownAddress, buffer);
return buffer;
_platform.pushNVMemoryByte(_deviceControl, &addr);
_platform.pushNVMemoryByte(_routingCount, &addr);
_platform.pushNVMemoryWord(_ownAddress, &addr);
}
uint8_t* DeviceObject::restore(uint8_t* buffer)
void DeviceObject::restore(uint8_t* startAddr)
{
buffer = popByte(_deviceControl, buffer);
buffer = popByte(_routingCount, buffer);
buffer = popWord(_ownAddress, buffer);
uint8_t* addr = startAddr;
_deviceControl = _platform.popNVMemoryByte(&addr);
_routingCount = _platform.popNVMemoryByte(&addr);
_ownAddress = _platform.popNVMemoryWord(&addr);
_prgMode = 0;
return buffer;
}
uint16_t DeviceObject::induvidualAddress()

View File

@ -10,9 +10,8 @@ public:
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data);
void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count);
uint8_t propertySize(PropertyID id);
uint8_t* save(uint8_t* buffer);
uint8_t* save();
uint8_t* restore(uint8_t* buffer);
void save();
void restore(uint8_t* startAddr);
uint32_t size();
void readPropertyDescription(uint8_t propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);

View File

@ -41,21 +41,12 @@ GroupObject& GroupObjectTableObject::get(uint16_t asap)
return _groupObjects[asap - 1];
}
uint8_t* GroupObjectTableObject::save(uint8_t* buffer)
void GroupObjectTableObject::restore(uint8_t* startAddr)
{
return TableObject::save(buffer);
}
uint8_t* GroupObjectTableObject::restore(uint8_t* buffer)
{
buffer = TableObject::restore(buffer);
TableObject::restore(startAddr);
_tableData = (uint16_t*)data();
initGroupObjects();
return buffer;
}
GroupObject& GroupObjectTableObject::nextUpdatedObject(bool& valid)

View File

@ -16,8 +16,7 @@ class GroupObjectTableObject : public TableObject
GroupObject& nextUpdatedObject(bool& valid);
void groupObjects(GroupObject* objs, uint16_t size);
virtual uint8_t* save(uint8_t* buffer);
virtual uint8_t* restore(uint8_t* buffer);
virtual void restore(uint8_t* startAddr);
protected:
virtual void beforeStateChange(LoadState& newState);

View File

@ -159,63 +159,34 @@ uint32_t IpParameterObject::size(){
return METADATA_SIZE;
}
uint8_t* IpParameterObject::save()
void IpParameterObject::save()
{
uint8_t* buffer = new uint8_t[METADATA_SIZE];
_platform.freeNVMemory(_ID);
uint8_t* addr = _platform.allocNVMemory(METADATA_SIZE, _ID);
buffer = pushWord(_projectInstallationId, buffer);
buffer = pushByte(_ipAssignmentMethod, buffer);
buffer = pushByte(_ipCapabilities, buffer);
buffer = pushInt(_ipAddress, buffer);
buffer = pushInt(_subnetMask, buffer);
buffer = pushInt(_defaultGateway, buffer);
buffer = pushInt(_multicastAddress, buffer);
buffer = pushByte(_ttl, buffer);
buffer = pushByteArray((uint8_t*)_friendlyName, 30, buffer);
buffer -= METADATA_SIZE;
if(_platform.NVMemoryType() == internalFlash){
_platform.freeNVMemory(_ID);
uintptr_t addr = _platform.allocNVMemory(METADATA_SIZE, _ID);
for(size_t i=0;i<METADATA_SIZE;i++)
_platform.writeNVMemory(addr+i, buffer[i]);
delete[] buffer;
return (uint8_t*)addr;
}
return buffer;
_platform.pushNVMemoryWord(_projectInstallationId, &addr);
_platform.pushNVMemoryByte(_ipAssignmentMethod, &addr);
_platform.pushNVMemoryByte(_ipCapabilities, &addr);
_platform.pushNVMemoryInt(_ipAddress, &addr);
_platform.pushNVMemoryInt(_subnetMask, &addr);
_platform.pushNVMemoryInt(_defaultGateway, &addr);
_platform.pushNVMemoryInt(_multicastAddress, &addr);
_platform.pushNVMemoryByte(_ttl, &addr);
_platform.pushNVMemoryArray((uint8_t*)_friendlyName, &addr, sizeof(_friendlyName));
}
uint8_t* IpParameterObject::save(uint8_t* buffer)
void IpParameterObject::restore(uint8_t* startAddr)
{
buffer = pushWord(_projectInstallationId, buffer);
buffer = pushByte(_ipAssignmentMethod, buffer);
buffer = pushByte(_ipCapabilities, buffer);
buffer = pushInt(_ipAddress, buffer);
buffer = pushInt(_subnetMask, buffer);
buffer = pushInt(_defaultGateway, buffer);
buffer = pushInt(_multicastAddress, buffer);
buffer = pushByte(_ttl, buffer);
buffer = pushByteArray((uint8_t*)_friendlyName, 30, buffer);
return buffer;
}
uint8_t* IpParameterObject::restore(uint8_t* buffer)
{
buffer = popWord(_projectInstallationId, buffer);
buffer = popByte(_ipAssignmentMethod, buffer);
buffer = popByte(_ipCapabilities, buffer);
buffer = popInt(_ipAddress, buffer);
buffer = popInt(_subnetMask, buffer);
buffer = popInt(_defaultGateway, buffer);
buffer = popInt(_multicastAddress, buffer);
buffer = popByte(_ttl, buffer);
buffer = popByteArray((uint8_t*)_friendlyName, 30, buffer);
return buffer;
uint8_t* addr = startAddr;
_projectInstallationId = _platform.popNVMemoryWord(&addr);
_ipAssignmentMethod = _platform.popNVMemoryByte(&addr);
_ipCapabilities = _platform.popNVMemoryByte(&addr);
_ipAddress = _platform.popNVMemoryInt(&addr);
_subnetMask = _platform.popNVMemoryInt(&addr);
_defaultGateway = _platform.popNVMemoryInt(&addr);
_multicastAddress = _platform.popNVMemoryInt(&addr);
_ttl = _platform.popNVMemoryByte(&addr);
_platform.popNVMemoryArray((uint8_t*)_friendlyName, &addr, sizeof(_friendlyName));
}
uint32_t IpParameterObject::multicastAddress() const

View File

@ -12,9 +12,8 @@ class IpParameterObject : public InterfaceObject
void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count);
uint8_t propertySize(PropertyID id);
uint8_t* save(uint8_t* buffer);
uint8_t* save();
uint8_t* restore(uint8_t* buffer);
void save();
void restore(uint8_t* startAddr);
uint32_t size();
uint32_t multicastAddress() const;

View File

@ -16,54 +16,24 @@ bool Memory::isMemoryModified()
return _modified;
}
void Memory::readMemory(){
switch (_platform.NVMemoryType()){
case internalRam:
readRamMemory();
break;
case internalFlash:
readFlashMemory();
break;
case external:
readExternalMemory();
break;
case notDefined:
default:
_platform.fatalError();
}
}
void Memory::writeMemory(){
switch (_platform.NVMemoryType()){
case internalRam:
writeRamMemory();
break;
case internalFlash:
writeFlashMemory();
break;
case external:
writeExternalMemory();
break;
case notDefined:
default:
_platform.fatalError();
}
}
void Memory::readFlashMemory()
void Memory::readMemory()
{
for (int i = 0; i < _saveCount; i++)
{
uint8_t* data = (uint8_t*)_platform.reloadNVMemory(BASE_ID+i);
bool pointerAccess;
if(i<=2)
pointerAccess = true;
else
pointerAccess = false;
uint8_t* data = _platform.reloadNVMemory(BASE_ID+i, pointerAccess);
if(data == NULL)
continue;
_saveRestores[i]->restore(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;e<bytesToRestore;e++){
_data[e] = _platform.readNVMemory(addr++);
}
_saveRestores[i]->restore(_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<bytesToSave;e++){
_platform.writeNVMemory(addr++,_data[e]);
}
_platform.freeMemory(_data);
}
_platform.finishNVMemory();
_modified = false;
}
void Memory::addSaveRestore(SaveRestore * obj)
{
if (_saveCount >= MAXSAVE - 1)

View File

@ -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};

View File

@ -3,7 +3,7 @@
#include <cstdlib>
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<size;i++){
dest[i] = readNVMemory((*addr)++);
}
}
void Platform::pushNVMemoryByte(uint8_t val, uint8_t** addr)
{
writeNVMemory((*addr), val);
(*addr) += 1;
}
void Platform::pushNVMemoryWord(uint16_t val, uint8_t** addr)
{
writeNVMemory((*addr), ((val >> 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<size;i++){
writeNVMemory((*addr)++,src[i]);
}
}

View File

@ -4,13 +4,6 @@
#include <stddef.h>
#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;
};

View File

@ -8,24 +8,16 @@ 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:

View File

@ -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<METADATA_SIZE;i++)
_platform.writeNVMemory(addr+i, buffer[i]);
delete[] buffer;
}
return _dataComplete;
_platform.pushNVMemoryByte(_state, &addr);
_platform.pushNVMemoryByte(_errorCode, &addr);
_platform.pushNVMemoryInt(_size, &addr);
}
uint8_t* TableObject::restore(uint8_t* buffer)
void TableObject::restore(uint8_t* startAddr)
{
uint8_t state = 0;
uint8_t errorCode = 0;
if(_dataComplete == NULL)
_dataComplete = buffer;
buffer = popByte(state, buffer);
buffer = popByte(errorCode, buffer);
_state = (LoadState)state;
_errorCode = (ErrorCode)errorCode;
buffer = popInt(_size, buffer);
uint8_t* addr = startAddr;
_state = (LoadState)_platform.popNVMemoryByte(&addr);
_errorCode = (ErrorCode)_platform.popNVMemoryByte(&addr);
_size = _platform.popNVMemoryInt(&addr);
if (_size > 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;
}

View File

@ -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);

View File

@ -19,7 +19,7 @@
#endif
void buttonUp();
typedef uint8_t* (*saveRestoreCallback)(uint8_t* buffer);
typedef void (*saveRestoreCallback)(uint8_t* buffer);
template <class P, class B> class KnxFacade : private SaveRestore
{
@ -288,24 +288,18 @@ template <class P, class B> 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;
}
};

View File

@ -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;i++){
if(_memoryBlocks[i].ID == 0)
break;
}
if(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();
if(!_MemoryInitialized)
initNVMemory();
return (uintptr_t)(_mappedFile + 2);
_MemoryInitialized=true;
int i;
for(i=0;i<MAX_MEMORY_BLOCKS;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(i >= MAX_MEMORY_BLOCKS)
return;
_memoryBlocks[i].data = NULL;
_memoryBlocks[i].size = 0;
_memoryBlocks[i].ID = 0;
}
#define FLASHSIZE 0x10000
void LinuxPlatform::doMemoryMapping()
{

View File

@ -5,6 +5,14 @@
#include <string>
#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

View File

@ -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){

View File

@ -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);

View File

@ -4,18 +4,27 @@
#include <knx/bits.h>
#include <Arduino.h>
#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;i++){
if(_memoryBlocks[i].ID == 0)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == 0)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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;i++){
if(_memoryBlocks[i].ID == ID)
break;
}
if(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

View File

@ -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