mirror of
https://github.com/thelsing/knx.git
synced 2025-08-17 13:47:28 +02:00
-change memory management
This commit is contained in:
parent
29ef91f2e0
commit
afe3ae7936
@ -84,15 +84,36 @@ int Esp32Platform::readBytes(uint8_t * buffer, uint16_t maxLen)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * Esp32Platform::getEepromBuffer(uint16_t size)
|
bool Esp32Platform::writeNVMemory(uint32_t addr,uint8_t data)
|
||||||
{
|
{
|
||||||
EEPROM.begin(size);
|
*((uint8_t*)addr) = data;
|
||||||
return EEPROM.getDataPtr();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Esp32Platform::commitToEeprom()
|
uint8_t Esp32Platform::readNVMemory(uint32_t addr)
|
||||||
|
{
|
||||||
|
return *((uint8_t*)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Esp32Platform::allocNVMemory(uint32_t size,uint32_t ID)
|
||||||
|
{
|
||||||
|
if(size > EEPROM_EMULATION_SIZE)
|
||||||
|
fatalError();
|
||||||
|
return (uint32_t)EEPROM.getDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Esp32Platform::reloadNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
EEPROM.begin(1024);
|
||||||
|
return (uint32_t)EEPROM.getDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Esp32Platform::finishNVMemory()
|
||||||
{
|
{
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Esp32Platform::freeNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,8 +28,12 @@ public:
|
|||||||
int readBytes(uint8_t* buffer, uint16_t maxLen) override;
|
int readBytes(uint8_t* buffer, uint16_t maxLen) override;
|
||||||
|
|
||||||
//memory
|
//memory
|
||||||
uint8_t* getEepromBuffer(uint16_t size);
|
bool writeNVMemory(uint32_t addr,uint8_t data);
|
||||||
void commitToEeprom();
|
uint8_t readNVMemory(uint32_t addr);
|
||||||
|
uint32_t allocNVMemory(uint32_t size,uint32_t ID);
|
||||||
|
uint32_t reloadNVMemory(uint32_t ID);
|
||||||
|
void finishNVMemory();
|
||||||
|
void freeNVMemory(uint32_t ID);
|
||||||
private:
|
private:
|
||||||
WiFiUDP _udp;
|
WiFiUDP _udp;
|
||||||
};
|
};
|
||||||
|
@ -85,14 +85,36 @@ int EspPlatform::readBytes(uint8_t * buffer, uint16_t maxLen)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * EspPlatform::getEepromBuffer(uint16_t size)
|
bool EspPlatform::writeNVMemory(uint32_t addr,uint8_t data)
|
||||||
{
|
{
|
||||||
EEPROM.begin(size);
|
*((uint8_t*)addr) = data;
|
||||||
return EEPROM.getDataPtr();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EspPlatform::commitToEeprom()
|
uint8_t EspPlatform::readNVMemory(uint32_t addr)
|
||||||
|
{
|
||||||
|
return *((uint8_t*)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspPlatform::allocNVMemory(uint32_t size,uint32_t ID)
|
||||||
|
{
|
||||||
|
if(size > EEPROM_EMULATION_SIZE)
|
||||||
|
fatalError();
|
||||||
|
return (uint32_t)EEPROM.getDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EspPlatform::reloadNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
EEPROM.begin(1024);
|
||||||
|
return (uint32_t)EEPROM.getDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EspPlatform::finishNVMemory()
|
||||||
{
|
{
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EspPlatform::freeNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,8 +29,12 @@ class EspPlatform : public ArduinoPlatform
|
|||||||
int readBytes(uint8_t* buffer, uint16_t maxLen) override;
|
int readBytes(uint8_t* buffer, uint16_t maxLen) override;
|
||||||
|
|
||||||
//memory
|
//memory
|
||||||
uint8_t* getEepromBuffer(uint16_t size);
|
bool writeNVMemory(uint32_t addr,uint8_t data);
|
||||||
void commitToEeprom();
|
uint8_t readNVMemory(uint32_t addr);
|
||||||
|
uint32_t allocNVMemory(uint32_t size,uint32_t ID);
|
||||||
|
uint32_t reloadNVMemory(uint32_t ID);
|
||||||
|
void finishNVMemory();
|
||||||
|
void freeNVMemory(uint32_t ID);
|
||||||
private:
|
private:
|
||||||
WiFiUDP _udp;
|
WiFiUDP _udp;
|
||||||
};
|
};
|
||||||
|
@ -74,6 +74,35 @@ uint32_t ApplicationProgramObject::getInt(uint32_t addr)
|
|||||||
return ::getInt(TableObject::data() + addr);
|
return ::getInt(TableObject::data() + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t ApplicationProgramObject::size(){
|
||||||
|
return sizeof(_programVersion)+TableObject::size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t* ApplicationProgramObject::save()
|
||||||
|
{
|
||||||
|
if(TableObject::data() == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
uint8_t* buffer;
|
||||||
|
uint32_t addr =(uint32_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]);
|
||||||
|
|
||||||
|
free (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TableObject::save();
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
|
uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
buffer = pushByteArray(_programVersion, 5, buffer);
|
buffer = pushByteArray(_programVersion, 5, buffer);
|
||||||
@ -83,8 +112,8 @@ uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
|
|||||||
|
|
||||||
uint8_t* ApplicationProgramObject::restore(uint8_t* buffer)
|
uint8_t* ApplicationProgramObject::restore(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
|
TableObject::_dataComplete = buffer;
|
||||||
buffer = popByteArray(_programVersion, 5, buffer);
|
buffer = popByteArray(_programVersion, 5, buffer);
|
||||||
|
|
||||||
return TableObject::restore(buffer);
|
return TableObject::restore(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,9 @@ class ApplicationProgramObject : public TableObject
|
|||||||
uint16_t getWord(uint32_t addr);
|
uint16_t getWord(uint32_t addr);
|
||||||
uint32_t getInt(uint32_t addr);
|
uint32_t getInt(uint32_t addr);
|
||||||
uint8_t* save(uint8_t* buffer);
|
uint8_t* save(uint8_t* buffer);
|
||||||
|
uint8_t* save();
|
||||||
uint8_t* restore(uint8_t* buffer);
|
uint8_t* restore(uint8_t* buffer);
|
||||||
|
uint32_t size();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t propertyCount();
|
uint8_t propertyCount();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platform),
|
BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platform),
|
||||||
_assocTable(platform), _groupObjTable(platform), _appProgram(platform),
|
_assocTable(platform), _groupObjTable(platform), _appProgram(platform),
|
||||||
_platform(platform), _appLayer(_assocTable, *this),
|
_platform(platform), _appLayer(_assocTable, *this),
|
||||||
_transLayer(_appLayer, _addrTable), _netLayer(_transLayer)
|
_transLayer(_appLayer, _addrTable), _netLayer(_transLayer), _deviceObj(platform)
|
||||||
{
|
{
|
||||||
_appLayer.transportLayer(_transLayer);
|
_appLayer.transportLayer(_transLayer);
|
||||||
_transLayer.networkLayer(_netLayer);
|
_transLayer.networkLayer(_netLayer);
|
||||||
@ -139,7 +139,13 @@ void BauSystemB::deviceDescriptorReadIndication(Priority priority, HopCountType
|
|||||||
void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
|
void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
|
||||||
uint16_t memoryAddress, uint8_t * data)
|
uint16_t memoryAddress, uint8_t * data)
|
||||||
{
|
{
|
||||||
memcpy(_platform.memoryReference() + memoryAddress, data, number);
|
if(_platform.NVMemoryType() == internalFlash){
|
||||||
|
for(uint8_t i=0;i<number;i++)
|
||||||
|
_platform.writeNVMemory((uint32_t)_platform.memoryReference() + memoryAddress+i, data[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memcpy(_platform.memoryReference() + memoryAddress, data, number);
|
||||||
|
|
||||||
_memory.memoryModified();
|
_memory.memoryModified();
|
||||||
|
|
||||||
if (_deviceObj.verifyMode())
|
if (_deviceObj.verifyMode())
|
||||||
@ -149,8 +155,17 @@ void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType,
|
|||||||
void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
|
void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
|
||||||
uint16_t memoryAddress)
|
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((uint32_t)_platform.memoryReference() + memoryAddress+i);
|
||||||
|
|
||||||
|
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer);
|
||||||
|
}
|
||||||
|
else{
|
||||||
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
|
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
|
||||||
_platform.memoryReference() + memoryAddress);
|
_platform.memoryReference() + memoryAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap)
|
void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap)
|
||||||
@ -167,13 +182,27 @@ void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, ui
|
|||||||
|
|
||||||
void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress)
|
void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress)
|
||||||
{
|
{
|
||||||
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
|
if(_platform.NVMemoryType() == internalFlash){
|
||||||
_platform.memoryReference() + memoryAddress);
|
uint8_t* buffer = new uint8_t[number];
|
||||||
|
for(uint8_t i=0;i<number;i++)
|
||||||
|
buffer[i] = _platform.readNVMemory((uint32_t)_platform.memoryReference() + memoryAddress+i);
|
||||||
|
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
|
||||||
|
_platform.memoryReference() + memoryAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BauSystemB::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* data)
|
void BauSystemB::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* data)
|
||||||
{
|
{
|
||||||
memcpy(_platform.memoryReference() + memoryAddress, data, number);
|
if(_platform.NVMemoryType() == internalFlash){
|
||||||
|
for(uint8_t i=0;i<number;i++)
|
||||||
|
_platform.writeNVMemory((uint32_t)_platform.memoryReference() + memoryAddress+i, data[i]);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
memcpy(_platform.memoryReference() + memoryAddress, data, number);
|
||||||
|
}
|
||||||
_memory.memoryModified();
|
_memory.memoryModified();
|
||||||
|
|
||||||
if (_deviceObj.verifyMode())
|
if (_deviceObj.verifyMode())
|
||||||
|
@ -2,6 +2,15 @@
|
|||||||
#include "device_object.h"
|
#include "device_object.h"
|
||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
|
|
||||||
|
#define METADATA_SIZE (sizeof(_deviceControl)+sizeof(_routingCount)+sizeof(_ownAddress))
|
||||||
|
|
||||||
|
DeviceObject::DeviceObject(Platform& platform): _platform(platform)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 10; ++i)
|
||||||
|
_orderNumber[i] = 0;
|
||||||
|
for(int i = 0; i < 6; ++i)
|
||||||
|
_hardwareType[i] = 0;
|
||||||
|
}
|
||||||
void DeviceObject::readProperty(PropertyID propertyId, uint32_t start, uint32_t& count, uint8_t* data)
|
void DeviceObject::readProperty(PropertyID propertyId, uint32_t start, uint32_t& count, uint8_t* data)
|
||||||
{
|
{
|
||||||
switch (propertyId)
|
switch (propertyId)
|
||||||
@ -106,6 +115,32 @@ uint8_t DeviceObject::propertySize(PropertyID id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t DeviceObject::size(){
|
||||||
|
return METADATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* DeviceObject::save()
|
||||||
|
{
|
||||||
|
uint8_t* buffer = new uint8_t[METADATA_SIZE];
|
||||||
|
|
||||||
|
buffer = pushByte(_deviceControl, buffer);
|
||||||
|
buffer = pushByte(_routingCount, buffer);
|
||||||
|
buffer = pushWord(_ownAddress, buffer);
|
||||||
|
buffer -= METADATA_SIZE;
|
||||||
|
|
||||||
|
if(_platform.NVMemoryType() == internalFlash){
|
||||||
|
_platform.freeNVMemory(_ID);
|
||||||
|
uint32_t addr = _platform.allocNVMemory(METADATA_SIZE, _ID);
|
||||||
|
|
||||||
|
for(uint32_t i=0;i<METADATA_SIZE;i++)
|
||||||
|
_platform.writeNVMemory(addr+i, buffer[i]);
|
||||||
|
|
||||||
|
free (buffer);
|
||||||
|
return (uint8_t*)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
uint8_t* DeviceObject::save(uint8_t* buffer)
|
uint8_t* DeviceObject::save(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
buffer = pushByte(_deviceControl, buffer);
|
buffer = pushByte(_deviceControl, buffer);
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "interface_object.h"
|
#include "interface_object.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
class DeviceObject: public InterfaceObject
|
class DeviceObject: public InterfaceObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
DeviceObject(Platform& platform);
|
||||||
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data);
|
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);
|
void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count);
|
||||||
uint8_t propertySize(PropertyID id);
|
uint8_t propertySize(PropertyID id);
|
||||||
uint8_t* save(uint8_t* buffer);
|
uint8_t* save(uint8_t* buffer);
|
||||||
|
uint8_t* save();
|
||||||
uint8_t* restore(uint8_t* buffer);
|
uint8_t* restore(uint8_t* buffer);
|
||||||
|
uint32_t size();
|
||||||
void readPropertyDescription(uint8_t propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
|
void readPropertyDescription(uint8_t propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
|
||||||
|
|
||||||
|
|
||||||
@ -45,7 +49,8 @@ private:
|
|||||||
uint16_t _ownAddress = 0;
|
uint16_t _ownAddress = 0;
|
||||||
uint16_t _manufacturerId = 0xfa; //Default to KNXA
|
uint16_t _manufacturerId = 0xfa; //Default to KNXA
|
||||||
uint32_t _bauNumber = 0;
|
uint32_t _bauNumber = 0;
|
||||||
char _orderNumber[10] = "";
|
char _orderNumber[10];
|
||||||
uint8_t _hardwareType[6] = { 0, 0, 0, 0, 0, 0};
|
uint8_t _hardwareType[6];
|
||||||
uint16_t _version = 0;
|
uint16_t _version = 0;
|
||||||
|
Platform& _platform;
|
||||||
};
|
};
|
@ -1810,7 +1810,7 @@ void float16ToPayload(uint8_t* payload, size_t payload_length, int index, double
|
|||||||
if (wasNegative)
|
if (wasNegative)
|
||||||
mantissa *= -1;
|
mantissa *= -1;
|
||||||
|
|
||||||
println(mantissa);
|
// println(mantissa);
|
||||||
|
|
||||||
signed16ToPayload(payload, payload_length, index, mantissa, mask);
|
signed16ToPayload(payload, payload_length, index, mantissa, mask);
|
||||||
unsigned8ToPayload(payload, payload_length, index, exponent << 3, 0x78 & (mask >> 8));
|
unsigned8ToPayload(payload, payload_length, index, exponent << 3, 0x78 & (mask >> 8));
|
||||||
@ -1839,4 +1839,4 @@ void bcdToPayload(uint8_t* payload, size_t payload_length, int index, uint8_t va
|
|||||||
payload[index / 2] = (payload[index / 2] & 0xF0) | (value & 0x0F);
|
payload[index / 2] = (payload[index / 2] & 0xF0) | (value & 0x0F);
|
||||||
else
|
else
|
||||||
payload[index / 2] = (payload[index / 2] & 0x0F) | ((value << 4) & 0xF0);
|
payload[index / 2] = (payload[index / 2] & 0x0F) | ((value << 4) & 0xF0);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
//224.0.23.12
|
//224.0.23.12
|
||||||
#define DEFAULT_MULTICAST_ADDR 0xE000170C
|
#define DEFAULT_MULTICAST_ADDR 0xE000170C
|
||||||
|
#define METADATA_SIZE ( sizeof(_projectInstallationId) \
|
||||||
|
+sizeof(_ipAssignmentMethod) \
|
||||||
|
+sizeof(_ipCapabilities) \
|
||||||
|
+sizeof(_ipAddress) \
|
||||||
|
+sizeof(_subnetMask) \
|
||||||
|
+sizeof(_defaultGateway) \
|
||||||
|
+sizeof(_multicastAddress) \
|
||||||
|
+sizeof(_ttl) \
|
||||||
|
+sizeof(_friendlyName))
|
||||||
|
|
||||||
IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platform): _deviceObject(deviceObject),
|
IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platform): _deviceObject(deviceObject),
|
||||||
_platform(platform)
|
_platform(platform)
|
||||||
@ -146,6 +155,38 @@ uint8_t IpParameterObject::propertySize(PropertyID id)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
uint32_t IpParameterObject::size(){
|
||||||
|
return METADATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* IpParameterObject::save()
|
||||||
|
{
|
||||||
|
uint8_t* buffer = new uint8_t[METADATA_SIZE];
|
||||||
|
|
||||||
|
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);
|
||||||
|
uint32_t addr = _platform.allocNVMemory(METADATA_SIZE, _ID);
|
||||||
|
|
||||||
|
for(uint32_t i=0;i<METADATA_SIZE;i++)
|
||||||
|
_platform.writeNVMemory(addr+i, buffer[i]);
|
||||||
|
|
||||||
|
free (buffer);
|
||||||
|
return (uint8_t*)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* IpParameterObject::save(uint8_t* buffer)
|
uint8_t* IpParameterObject::save(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
@ -320,4 +361,4 @@ uint8_t IpParameterObject::propertyCount()
|
|||||||
PropertyDescription* IpParameterObject::propertyDescriptions()
|
PropertyDescription* IpParameterObject::propertyDescriptions()
|
||||||
{
|
{
|
||||||
return _propertyDescriptions;
|
return _propertyDescriptions;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,9 @@ class IpParameterObject : public InterfaceObject
|
|||||||
uint8_t propertySize(PropertyID id);
|
uint8_t propertySize(PropertyID id);
|
||||||
|
|
||||||
uint8_t* save(uint8_t* buffer);
|
uint8_t* save(uint8_t* buffer);
|
||||||
|
uint8_t* save();
|
||||||
uint8_t* restore(uint8_t* buffer);
|
uint8_t* restore(uint8_t* buffer);
|
||||||
|
uint32_t size();
|
||||||
|
|
||||||
uint32_t multicastAddress() const;
|
uint32_t multicastAddress() const;
|
||||||
uint8_t ttl() const { return _ttl; }
|
uint8_t ttl() const { return _ttl; }
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#define BASE_ID 0xC0DE0000
|
||||||
|
|
||||||
Memory::Memory(Platform & platform): _platform(platform)
|
Memory::Memory(Platform & platform): _platform(platform)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -14,9 +16,66 @@ bool Memory::isMemoryModified()
|
|||||||
return _modified;
|
return _modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::readMemory()
|
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()
|
||||||
{
|
{
|
||||||
_data = _platform.getEepromBuffer(512);
|
for (int i = 0; i < _saveCount; i++)
|
||||||
|
{
|
||||||
|
uint8_t* data = (uint8_t*)_platform.reloadNVMemory(BASE_ID+i);
|
||||||
|
if(data == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_saveRestores[i]->restore(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::writeFlashMemory()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _saveCount; i++){
|
||||||
|
_saveRestores[i]->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
_platform.finishNVMemory();
|
||||||
|
_modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Memory::readRamMemory()
|
||||||
|
{
|
||||||
|
_data = (uint8_t*)_platform.reloadNVMemory(1);
|
||||||
|
|
||||||
if (_data[0] != 0x00 || _data[1] != 0xAD || _data[2] != 0xAF || _data[3] != 0xFE)
|
if (_data[0] != 0x00 || _data[1] != 0xAD || _data[2] != 0xAF || _data[3] != 0xFE)
|
||||||
return;
|
return;
|
||||||
@ -26,11 +85,20 @@ void Memory::readMemory()
|
|||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
buffer = _saveRestores[i]->restore(buffer);
|
buffer = _saveRestores[i]->restore(buffer);
|
||||||
|
buffer = (uint8_t*)(((uint32_t)buffer + 3) / 4 * 4); //allign to 32bit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::writeMemory()
|
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[0] = 0x00;
|
||||||
_data[1] = 0xAD;
|
_data[1] = 0xAD;
|
||||||
_data[2] = 0xAF;
|
_data[2] = 0xAF;
|
||||||
@ -41,16 +109,103 @@ void Memory::writeMemory()
|
|||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
buffer = _saveRestores[i]->save(buffer);
|
buffer = _saveRestores[i]->save(buffer);
|
||||||
|
buffer = (uint8_t*)(((uint32_t)buffer + 3) / 4 * 4); //allign to 32bit
|
||||||
}
|
}
|
||||||
_platform.commitToEeprom();
|
_platform.finishNVMemory();
|
||||||
_modified = false;
|
_modified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Memory::readExternalMemory()
|
||||||
|
{
|
||||||
|
|
||||||
|
int size = _saveCount;
|
||||||
|
volatile uint32_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_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)
|
void Memory::addSaveRestore(SaveRestore * obj)
|
||||||
{
|
{
|
||||||
if (_saveCount >= MAXSAVE - 1)
|
if (_saveCount >= MAXSAVE - 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
obj->memoryID(BASE_ID + _saveCount);
|
||||||
_saveRestores[_saveCount] = obj;
|
_saveRestores[_saveCount] = obj;
|
||||||
_saveCount += 1;
|
_saveCount += 1;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,12 @@ public:
|
|||||||
void writeMemory();
|
void writeMemory();
|
||||||
void addSaveRestore(SaveRestore* obj);
|
void addSaveRestore(SaveRestore* obj);
|
||||||
private:
|
private:
|
||||||
|
void readFlashMemory();
|
||||||
|
void writeFlashMemory();
|
||||||
|
void readRamMemory();
|
||||||
|
void writeRamMemory();
|
||||||
|
void readExternalMemory();
|
||||||
|
void writeExternalMemory();
|
||||||
Platform& _platform;
|
Platform& _platform;
|
||||||
bool _modified = false;
|
bool _modified = false;
|
||||||
SaveRestore* _saveRestores[MAXSAVE] = {0};
|
SaveRestore* _saveRestores[MAXSAVE] = {0};
|
||||||
|
@ -12,6 +12,8 @@ uint8_t* Platform::memoryReference()
|
|||||||
uint8_t* Platform::allocMemory(size_t size)
|
uint8_t* Platform::allocMemory(size_t size)
|
||||||
{
|
{
|
||||||
uint8_t* address = (uint8_t*)malloc(size);
|
uint8_t* address = (uint8_t*)malloc(size);
|
||||||
|
if(address == NULL)
|
||||||
|
fatalError();
|
||||||
// if (_memoryReference == 0 || address < _memoryReference)
|
// if (_memoryReference == 0 || address < _memoryReference)
|
||||||
// _memoryReference = address;
|
// _memoryReference = address;
|
||||||
print("MemRef: ");
|
print("MemRef: ");
|
||||||
|
@ -4,6 +4,13 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "save_restore.h"
|
#include "save_restore.h"
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
notDefined,
|
||||||
|
internalRam,
|
||||||
|
internalFlash,
|
||||||
|
external
|
||||||
|
}NVMemory_t;
|
||||||
|
|
||||||
class Platform
|
class Platform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -29,13 +36,18 @@ class Platform
|
|||||||
virtual int readUart() = 0;
|
virtual int readUart() = 0;
|
||||||
virtual size_t readBytesUart(uint8_t* buffer, size_t length) = 0;
|
virtual size_t readBytesUart(uint8_t* buffer, size_t length) = 0;
|
||||||
|
|
||||||
virtual uint8_t* getEepromBuffer(uint16_t size) = 0;
|
virtual bool writeNVMemory(uint32_t addr,uint8_t data) = 0;
|
||||||
virtual void commitToEeprom() = 0;
|
virtual uint8_t readNVMemory(uint32_t addr) = 0;
|
||||||
|
virtual uint32_t allocNVMemory(uint32_t size,uint32_t ID) = 0;
|
||||||
|
virtual uint32_t reloadNVMemory(uint32_t ID) = 0;
|
||||||
|
virtual void finishNVMemory() = 0;
|
||||||
|
virtual void freeNVMemory(uint32_t ID) = 0;
|
||||||
|
|
||||||
virtual uint8_t* memoryReference();
|
virtual uint8_t* memoryReference();
|
||||||
virtual uint8_t* allocMemory(size_t size);
|
virtual uint8_t* allocMemory(size_t size);
|
||||||
virtual void freeMemory(uint8_t* ptr);
|
virtual void freeMemory(uint8_t* ptr);
|
||||||
|
NVMemory_t NVMemoryType(){return _NVMemoryType;}
|
||||||
protected:
|
protected:
|
||||||
uint8_t* _memoryReference = 0;
|
uint8_t* _memoryReference = 0;
|
||||||
};
|
NVMemory_t _NVMemoryType = notDefined;
|
||||||
|
};
|
||||||
|
@ -16,6 +16,7 @@ class SaveRestore
|
|||||||
* the start of its buffer.
|
* the start of its buffer.
|
||||||
*/
|
*/
|
||||||
virtual uint8_t* save(uint8_t* buffer) = 0;
|
virtual uint8_t* save(uint8_t* buffer) = 0;
|
||||||
|
virtual uint8_t* 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 buffer.
|
||||||
*
|
*
|
||||||
@ -25,4 +26,8 @@ class SaveRestore
|
|||||||
* the start of its buffer.
|
* the start of its buffer.
|
||||||
*/
|
*/
|
||||||
virtual uint8_t* restore(uint8_t* buffer) = 0;
|
virtual uint8_t* restore(uint8_t* buffer) = 0;
|
||||||
|
virtual uint32_t size() = 0;
|
||||||
|
void memoryID (uint32_t ID){_ID = ID;}
|
||||||
|
protected:
|
||||||
|
uint32_t _ID;
|
||||||
};
|
};
|
@ -3,6 +3,8 @@
|
|||||||
#include "table_object.h"
|
#include "table_object.h"
|
||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
|
|
||||||
|
#define METADATA_SIZE (sizeof(_state)+sizeof(_errorCode)+sizeof(_size))
|
||||||
|
|
||||||
TableObject::TableObject(Platform& platform): _platform(platform)
|
TableObject::TableObject(Platform& platform): _platform(platform)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -92,11 +94,40 @@ uint8_t* TableObject::save(uint8_t* buffer)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t* TableObject::save()
|
||||||
|
{
|
||||||
|
if(_data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
uint32_t addr;
|
||||||
|
uint8_t* buffer;
|
||||||
|
addr =(uint32_t)(_data - METADATA_SIZE);
|
||||||
|
if(_platform.NVMemoryType() == internalFlash)
|
||||||
|
buffer = new uint8_t[METADATA_SIZE];
|
||||||
|
else
|
||||||
|
buffer = (uint8_t*)addr;
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
free (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _dataComplete;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t* TableObject::restore(uint8_t* buffer)
|
uint8_t* TableObject::restore(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
uint8_t state = 0;
|
uint8_t state = 0;
|
||||||
uint8_t errorCode = 0;
|
uint8_t errorCode = 0;
|
||||||
|
if(_dataComplete == NULL)
|
||||||
|
_dataComplete = buffer;
|
||||||
buffer = popByte(state, buffer);
|
buffer = popByte(state, buffer);
|
||||||
buffer = popByte(errorCode, buffer);
|
buffer = popByte(errorCode, buffer);
|
||||||
_state = (LoadState)state;
|
_state = (LoadState)state;
|
||||||
@ -104,15 +135,13 @@ uint8_t* TableObject::restore(uint8_t* buffer)
|
|||||||
|
|
||||||
buffer = popInt(_size, buffer);
|
buffer = popInt(_size, buffer);
|
||||||
|
|
||||||
if (_data)
|
|
||||||
_platform.freeMemory(_data);
|
|
||||||
|
|
||||||
if (_size > 0)
|
if (_size > 0)
|
||||||
_data = _platform.allocMemory(_size);
|
_data = buffer;
|
||||||
|
|
||||||
else
|
else
|
||||||
_data = 0;
|
_data = 0;
|
||||||
|
|
||||||
buffer = popByteArray(_data, _size, buffer);
|
buffer += _size;
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@ -124,9 +153,13 @@ uint32_t TableObject::tableReference()
|
|||||||
|
|
||||||
bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte)
|
bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte)
|
||||||
{
|
{
|
||||||
if (_data)
|
if (_dataComplete)
|
||||||
{
|
{
|
||||||
_platform.freeMemory(_data);
|
if(_platform.NVMemoryType() == internalFlash)
|
||||||
|
_platform.freeNVMemory(_ID);
|
||||||
|
else if(_platform.NVMemoryType() == external)
|
||||||
|
_platform.freeMemory(_dataComplete);
|
||||||
|
_dataComplete = 0;
|
||||||
_data = 0;
|
_data = 0;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
@ -134,15 +167,24 @@ bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte)
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
_data = _platform.allocMemory(size);
|
if(_platform.NVMemoryType() == internalFlash){
|
||||||
if (!_data)
|
_dataComplete = (uint8_t*)_platform.allocNVMemory(size+this->size(), _ID);
|
||||||
return false;
|
}
|
||||||
|
else{
|
||||||
|
_dataComplete = _platform.allocMemory(size+this->size());
|
||||||
|
}
|
||||||
|
_data = _dataComplete + this->size(); //skip metadata
|
||||||
_size = size;
|
_size = size;
|
||||||
|
if (doFill){
|
||||||
if (doFill)
|
if(_platform.NVMemoryType() == internalFlash){
|
||||||
memset(_data, fillByte, size);
|
uint32_t addr = (uint32_t)_data;
|
||||||
|
for(uint32_t i=0; i<_size;i++)
|
||||||
|
_platform.writeNVMemory(addr++, fillByte);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
memset(_data, fillByte, _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +321,12 @@ uint8_t* TableObject::data()
|
|||||||
|
|
||||||
uint32_t TableObject::size()
|
uint32_t TableObject::size()
|
||||||
{
|
{
|
||||||
return _size;
|
return _size + METADATA_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TableObject::sizeMetadata()
|
||||||
|
{
|
||||||
|
return METADATA_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableObject::errorCode(ErrorCode errorCode)
|
void TableObject::errorCode(ErrorCode errorCode)
|
||||||
|
@ -26,7 +26,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
LoadState loadState();
|
LoadState loadState();
|
||||||
virtual uint8_t* save(uint8_t* buffer);
|
virtual uint8_t* save(uint8_t* buffer);
|
||||||
|
virtual uint8_t* save();
|
||||||
virtual uint8_t* restore(uint8_t* buffer);
|
virtual uint8_t* restore(uint8_t* buffer);
|
||||||
|
virtual uint32_t size();
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* This method is called before the interface object enters a new ::LoadState.
|
* This method is called before the interface object enters a new ::LoadState.
|
||||||
@ -40,15 +42,18 @@ protected:
|
|||||||
* must not be freed.
|
* must not be freed.
|
||||||
*/
|
*/
|
||||||
uint8_t* data();
|
uint8_t* data();
|
||||||
|
uint32_t sizeMetadata();
|
||||||
/**
|
/**
|
||||||
* returns the size of the internal data of the interface object int byte.
|
* returns the size of the internal data of the interface object int byte.
|
||||||
*/
|
*/
|
||||||
uint32_t size();
|
// uint32_t size();
|
||||||
/**
|
/**
|
||||||
* Set the reason for a state change failure.
|
* Set the reason for a state change failure.
|
||||||
*/
|
*/
|
||||||
void errorCode(ErrorCode errorCode);
|
void errorCode(ErrorCode errorCode);
|
||||||
|
|
||||||
|
Platform& _platform;
|
||||||
|
uint8_t *_dataComplete = 0;
|
||||||
private:
|
private:
|
||||||
uint32_t tableReference();
|
uint32_t tableReference();
|
||||||
bool allocTable(uint32_t size, bool doFill, uint8_t fillByte);
|
bool allocTable(uint32_t size, bool doFill, uint8_t fillByte);
|
||||||
@ -67,7 +72,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void loadState(LoadState newState);
|
void loadState(LoadState newState);
|
||||||
LoadState _state = LS_UNLOADED;
|
LoadState _state = LS_UNLOADED;
|
||||||
Platform& _platform;
|
|
||||||
uint8_t *_data = 0;
|
uint8_t *_data = 0;
|
||||||
uint32_t _size = 0;
|
uint32_t _size = 0;
|
||||||
ErrorCode _errorCode = E_NO_FAULT;
|
ErrorCode _errorCode = E_NO_FAULT;
|
||||||
|
@ -257,9 +257,16 @@ template <class P, class B> class KnxFacade : private SaveRestore
|
|||||||
uint32_t _buttonPin = 0;
|
uint32_t _buttonPin = 0;
|
||||||
saveRestoreCallback _saveCallback = 0;
|
saveRestoreCallback _saveCallback = 0;
|
||||||
saveRestoreCallback _restoreCallback = 0;
|
saveRestoreCallback _restoreCallback = 0;
|
||||||
|
uint32_t (*_sizeCallback)() = 0;
|
||||||
bool _toogleProgMode = false;
|
bool _toogleProgMode = false;
|
||||||
bool _progLedState = false;
|
bool _progLedState = false;
|
||||||
|
|
||||||
|
uint32_t size(){
|
||||||
|
if (_sizeCallback != 0)
|
||||||
|
return _sizeCallback();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
uint8_t* save(uint8_t* buffer)
|
uint8_t* save(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
if (_saveCallback != 0)
|
if (_saveCallback != 0)
|
||||||
@ -268,6 +275,7 @@ template <class P, class B> class KnxFacade : private SaveRestore
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t* save(){};
|
||||||
uint8_t* restore(uint8_t* buffer)
|
uint8_t* restore(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
if (_restoreCallback != 0)
|
if (_restoreCallback != 0)
|
||||||
|
@ -200,22 +200,44 @@ int LinuxPlatform::readBytes(uint8_t * buffer, uint16_t maxLen)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * LinuxPlatform::getEepromBuffer(uint16_t size)
|
bool LinuxPlatform::writeNVMemory(uint32_t addr,uint8_t data)
|
||||||
{
|
{
|
||||||
if (_fd < 0)
|
*((uint8_t*)addr) = data;
|
||||||
doMemoryMapping();
|
return true;
|
||||||
|
|
||||||
return _mappedFile + 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxPlatform::commitToEeprom()
|
uint8_t LinuxPlatform::readNVMemory(uint32_t addr)
|
||||||
|
{
|
||||||
|
return *((uint8_t*)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t LinuxPlatform::allocNVMemory(uint32_t size,uint32_t ID)
|
||||||
{
|
{
|
||||||
if (_fd < 0)
|
if (_fd < 0)
|
||||||
doMemoryMapping();
|
doMemoryMapping();
|
||||||
|
|
||||||
|
return (uint32_t)_mappedFile + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t LinuxPlatform::reloadNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
if (_fd < 0)
|
||||||
|
doMemoryMapping();
|
||||||
|
|
||||||
|
return (uint32_t)_mappedFile + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinuxPlatform::finishNVMemory()
|
||||||
|
{
|
||||||
|
if (_fd < 0)
|
||||||
|
doMemoryMapping();
|
||||||
|
|
||||||
fsync(_fd);
|
fsync(_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinuxPlatform::freeNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
}
|
||||||
#define FLASHSIZE 0x10000
|
#define FLASHSIZE 0x10000
|
||||||
void LinuxPlatform::doMemoryMapping()
|
void LinuxPlatform::doMemoryMapping()
|
||||||
{
|
{
|
||||||
|
@ -44,8 +44,12 @@ public:
|
|||||||
size_t readBytesUart(uint8_t *buffer, size_t length) override;
|
size_t readBytesUart(uint8_t *buffer, size_t length) override;
|
||||||
|
|
||||||
//memory
|
//memory
|
||||||
uint8_t* getEepromBuffer(uint16_t size) override;
|
bool writeNVMemory(uint32_t addr,uint8_t data);
|
||||||
void commitToEeprom() override;
|
uint8_t readNVMemory(uint32_t addr);
|
||||||
|
uint32_t allocNVMemory(uint32_t size,uint32_t ID);
|
||||||
|
uint32_t reloadNVMemory(uint32_t ID);
|
||||||
|
void finishNVMemory();
|
||||||
|
void freeNVMemory(uint32_t ID);
|
||||||
uint8_t* allocMemory(size_t size) override;
|
uint8_t* allocMemory(size_t size) override;
|
||||||
void freeMemory(uint8_t* ptr) override;
|
void freeMemory(uint8_t* ptr) override;
|
||||||
void cmdlineArgs(int argc, char** argv);
|
void cmdlineArgs(int argc, char** argv);
|
||||||
|
416
src/samd_flash.cpp
Normal file
416
src/samd_flash.cpp
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include "samd_flash.h"
|
||||||
|
|
||||||
|
#define VALID (0xDEADC0DE)
|
||||||
|
|
||||||
|
extern uint32_t __etext;
|
||||||
|
extern uint32_t __data_start__;
|
||||||
|
extern uint32_t __data_end__;
|
||||||
|
|
||||||
|
static const uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
|
||||||
|
|
||||||
|
SamdFlash::SamdFlash(){
|
||||||
|
_pageSize = pageSizes[NVMCTRL->PARAM.bit.PSZ];
|
||||||
|
_pageCnt = NVMCTRL->PARAM.bit.NVMP;
|
||||||
|
_rowSize = PAGES_PER_ROW * _pageSize;
|
||||||
|
_rowBuffer = new uint8_t[_rowSize];
|
||||||
|
|
||||||
|
//find end of program flash and set limit to next row
|
||||||
|
uint32_t endEddr = (uint32_t)(&__etext + (&__data_end__ - &__data_start__)); //text + data MemoryBlock
|
||||||
|
_MemoryEnd = getRowAddr(endEddr) + _rowSize-1; //23295
|
||||||
|
|
||||||
|
//map info structure to last row in flash
|
||||||
|
_info = (info_data_t*)getRowAddr(_pageSize*_pageCnt-1); //261888 (rowAddr of last row)
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdFlash::getStartAddress(){
|
||||||
|
return _info->freeMemoryStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SamdFlash::read(uint8_t* addr){
|
||||||
|
if(_rowBufferModified == false)
|
||||||
|
return *addr;
|
||||||
|
|
||||||
|
if(getRowAddr((uint32_t)addr) != _rowBufferAddr)
|
||||||
|
return *addr;
|
||||||
|
|
||||||
|
//return data from buffer because flash data is not up to date
|
||||||
|
return _rowBuffer[(uint32_t)addr-_rowBufferAddr];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SamdFlash::write(uint8_t* addr, uint8_t data){
|
||||||
|
//Check if the destination address is valid
|
||||||
|
if ((uint32_t)addr >= (_pageSize * _pageCnt) || (uint32_t)addr <= _MemoryEnd)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint32_t newRowAddr = getRowAddr((uint32_t)addr);
|
||||||
|
//if the row changed, write old Buffer and init new
|
||||||
|
if(newRowAddr != _rowBufferAddr){
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
downloadRowBuffer(newRowAddr);
|
||||||
|
_rowBufferAddr = newRowAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rowBuffer[(uint32_t)addr-_rowBufferAddr] = data;
|
||||||
|
_rowBufferModified = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdFlash::uploadRowBuffer(uint32_t rowAddr){
|
||||||
|
if(!_rowBufferModified) return;
|
||||||
|
eraseRow(rowAddr);
|
||||||
|
//Clear Page Buffer
|
||||||
|
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||||
|
while (NVMCTRL->INTFLAG.bit.READY == 0) {}
|
||||||
|
// Disable automatic page write
|
||||||
|
NVMCTRL->CTRLB.bit.MANW = 1;
|
||||||
|
|
||||||
|
volatile uint32_t* src_addr = (volatile uint32_t*)_rowBuffer;
|
||||||
|
volatile uint32_t* dst_addr = (volatile uint32_t *)rowAddr;
|
||||||
|
for(uint32_t p=0;p<PAGES_PER_ROW;p++){
|
||||||
|
for (uint32_t i=0; i<(_pageSize/4); i++) {
|
||||||
|
*dst_addr = *src_addr;
|
||||||
|
dst_addr++;
|
||||||
|
src_addr++;
|
||||||
|
}
|
||||||
|
// Execute "WP" Write Page
|
||||||
|
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
|
||||||
|
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SamdFlash::downloadRowBuffer(uint32_t rowAddr){
|
||||||
|
volatile uint32_t* src_addr = (volatile uint32_t*)rowAddr;
|
||||||
|
volatile uint32_t* dst_addr = (volatile uint32_t *)_rowBuffer;
|
||||||
|
for(uint32_t p=0;p<PAGES_PER_ROW;p++){
|
||||||
|
for (uint32_t i=0; i<(_pageSize/4); i++) {
|
||||||
|
*dst_addr = *src_addr;
|
||||||
|
dst_addr++;
|
||||||
|
src_addr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_rowBufferModified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdFlash::getRowAddr(uint32_t flasAddr){
|
||||||
|
return flasAddr & ~(_rowSize-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdFlash::finalise(){
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdFlash::eraseRow(uint32_t rowAddr){
|
||||||
|
NVMCTRL->ADDR.reg = rowAddr/2;
|
||||||
|
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||||
|
while (!NVMCTRL->INTFLAG.bit.READY) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdFlash::erase(){
|
||||||
|
uint32_t rowAddr = getRowAddr((uint32_t)_info);
|
||||||
|
uint32_t nextrowAddr = getRowAddr(_MemoryEnd);
|
||||||
|
|
||||||
|
while(rowAddr != nextrowAddr){
|
||||||
|
eraseRow(rowAddr);
|
||||||
|
rowAddr = rowAddr - _rowSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdFlash::erase(uint32_t ID){
|
||||||
|
block_meta_data_t ramCopy;
|
||||||
|
block_meta_data_t* block = getBlock(ID);
|
||||||
|
if(block == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ramCopy = *block;
|
||||||
|
uint32_t rowAddr = (uint32_t)block;
|
||||||
|
uint32_t nextrowAddr = getRowAddr(rowAddr + block->size - 1 +sizeof(block_meta_data_t));
|
||||||
|
|
||||||
|
while(rowAddr != nextrowAddr){
|
||||||
|
eraseRow(nextrowAddr);
|
||||||
|
nextrowAddr = nextrowAddr - _rowSize;
|
||||||
|
}
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
|
||||||
|
_rowBufferAddr = rowAddr;
|
||||||
|
downloadRowBuffer(_rowBufferAddr);
|
||||||
|
//map block meta structure into ram copy
|
||||||
|
block = (block_meta_data_t*)_rowBuffer;
|
||||||
|
//copy into row buffer
|
||||||
|
*block = ramCopy;
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
}
|
||||||
|
void SamdFlash::copyAndFree(block_meta_data_t* src, block_meta_data_t* dst){
|
||||||
|
block_meta_data_t metaDataRamCopy;
|
||||||
|
block_meta_data_t* tempBlock;
|
||||||
|
if(src == NULL || dst == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
metaDataRamCopy = *dst;
|
||||||
|
uint32_t lastRow = getRowAddr((uint32_t)src + src->size -1 + sizeof(block_meta_data_t));
|
||||||
|
uint32_t srcRow = (uint32_t)src;
|
||||||
|
uint32_t dstRow = (uint32_t)dst;
|
||||||
|
|
||||||
|
while(srcRow <= lastRow){
|
||||||
|
downloadRowBuffer(srcRow);
|
||||||
|
//if first row copy meta data too
|
||||||
|
if(srcRow == (uint32_t)src){
|
||||||
|
//map block meta structure into ram copy
|
||||||
|
tempBlock = (block_meta_data_t*)_rowBuffer;
|
||||||
|
//copy into row buffer
|
||||||
|
*tempBlock = metaDataRamCopy;
|
||||||
|
}
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer(dstRow);
|
||||||
|
|
||||||
|
srcRow = srcRow + _rowSize;
|
||||||
|
dstRow = dstRow + _rowSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
//free src
|
||||||
|
downloadRowBuffer((uint32_t)src);
|
||||||
|
//map block meta structure into ram copy
|
||||||
|
tempBlock = (block_meta_data_t*)_rowBuffer;
|
||||||
|
tempBlock->ID = 0;
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer((uint32_t)src);
|
||||||
|
}
|
||||||
|
|
||||||
|
block_meta_data_t* SamdFlash::findEmptyBlock(uint32_t size,uint32_t* compSize, uint32_t* previousBlockAddr){
|
||||||
|
block_meta_data_t* block = _info->firstBlock;
|
||||||
|
block_meta_data_t* preblock = NULL;
|
||||||
|
block_meta_data_t* conblock = NULL;
|
||||||
|
if(block != NULL && block->validMask == VALID){
|
||||||
|
do{
|
||||||
|
if(block->ID == 0){
|
||||||
|
if(block->size >= size){
|
||||||
|
*compSize = 0;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
//ceck if we can merge next empty blocks
|
||||||
|
else if(block->next != NULL){
|
||||||
|
conblock = block->next;
|
||||||
|
*compSize = block->size;
|
||||||
|
while(conblock != NULL && conblock->ID == 0){
|
||||||
|
*compSize += conblock->size + sizeof(block_meta_data_t);
|
||||||
|
if(*compSize >= size){
|
||||||
|
*previousBlockAddr = (uint32_t)preblock;
|
||||||
|
return conblock;
|
||||||
|
}
|
||||||
|
conblock = conblock->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//block is last one
|
||||||
|
else{
|
||||||
|
*compSize = 0;
|
||||||
|
*previousBlockAddr = (uint32_t)preblock;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preblock = block;
|
||||||
|
block = block->next;
|
||||||
|
}while(block != NULL && block->validMask == VALID);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* SamdFlash::loadBlock(uint32_t ID){
|
||||||
|
block_meta_data_t* block = _info->firstBlock;
|
||||||
|
if(block == (block_meta_data_t*)0xFFFFFFFF)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(block != NULL && block->validMask == VALID){
|
||||||
|
do{
|
||||||
|
if(block->ID == ID){
|
||||||
|
return ((uint8_t*)block)+sizeof(block_meta_data_t);
|
||||||
|
}
|
||||||
|
block = block->next;
|
||||||
|
}while(block != NULL && block->validMask == VALID);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_meta_data_t* SamdFlash::getBlock(uint32_t ID){
|
||||||
|
uint8_t* block = loadBlock(ID);
|
||||||
|
if(block == NULL)
|
||||||
|
return NULL;
|
||||||
|
return (block_meta_data_t*)(block-sizeof(block_meta_data_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
block_meta_data_t* SamdFlash::findLastBlock(){
|
||||||
|
block_meta_data_t* block = _info->firstBlock;
|
||||||
|
if(block == (block_meta_data_t*)0xFFFFFFFF || block == NULL)
|
||||||
|
return NULL;
|
||||||
|
while(block->next != NULL && block->next->validMask == VALID){
|
||||||
|
block = block->next;
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdFlash::free(uint32_t ID){
|
||||||
|
block_meta_data_t* block = getBlock(ID);
|
||||||
|
if(block != NULL){
|
||||||
|
//upload actual rowBuffer if necessary
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
//download block into ram buffer
|
||||||
|
_rowBufferAddr = (uint32_t)block;
|
||||||
|
downloadRowBuffer(_rowBufferAddr);
|
||||||
|
//map block structure into ram copy
|
||||||
|
block = (block_meta_data_t*)_rowBuffer;
|
||||||
|
//mark the block as empty and write to flash
|
||||||
|
block->ID = 0;
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* SamdFlash::malloc(uint32_t size, uint32_t ID){
|
||||||
|
//check if ID is already present
|
||||||
|
if(loadBlock(ID) != NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return forcemalloc(size, ID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* SamdFlash::forcemalloc(uint32_t size, uint32_t ID){
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
//download actual info row into ram buffer
|
||||||
|
_rowBufferAddr = (uint32_t)_info; //261888
|
||||||
|
downloadRowBuffer(_rowBufferAddr);
|
||||||
|
//map info structure into ram copy
|
||||||
|
_info = (info_data_t*)_rowBuffer;
|
||||||
|
|
||||||
|
//create new info if actual is not valid (all data got lost)
|
||||||
|
if(_info->validMask != VALID){
|
||||||
|
_info->validMask = VALID;
|
||||||
|
_info->freeMemoryStart = getRowAddr(_pageSize*_pageCnt-1)-1; //161887
|
||||||
|
_info->firstBlock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create ram copies for further usage
|
||||||
|
block_meta_data_t newBlock;
|
||||||
|
block_meta_data_t previousBlock;
|
||||||
|
uint32_t newBlockFlashAddr;
|
||||||
|
uint32_t previousBlockFlashAddr = 0;
|
||||||
|
block_meta_data_t* tempBlock;
|
||||||
|
|
||||||
|
//check if we can use an existing empty block or allocate a new one
|
||||||
|
uint32_t newSize;
|
||||||
|
tempBlock = findEmptyBlock(size,&newSize,&previousBlockFlashAddr);
|
||||||
|
if(tempBlock != NULL){
|
||||||
|
//copy found block into ram
|
||||||
|
newBlock = *tempBlock;
|
||||||
|
newBlockFlashAddr = (uint32_t)tempBlock;
|
||||||
|
//two ore more empty blocks were connected
|
||||||
|
if(newSize != 0){
|
||||||
|
newBlock.size = newSize;
|
||||||
|
if(previousBlockFlashAddr == 0){
|
||||||
|
_info->firstBlock = (block_meta_data_t*)newBlockFlashAddr;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//copy found block into ram
|
||||||
|
previousBlock = *((block_meta_data_t*)previousBlockFlashAddr);
|
||||||
|
previousBlock.next = (block_meta_data_t*)newBlockFlashAddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//newBlock is last one in list an can be extended
|
||||||
|
if(newBlock.size < size){
|
||||||
|
if(previousBlockFlashAddr == 0){
|
||||||
|
newBlockFlashAddr = getRowAddr(getRowAddr(_pageSize*_pageCnt-1) - (size+sizeof(block_meta_data_t)));
|
||||||
|
newBlock.size = getRowAddr(_pageSize*_pageCnt-1)-newBlockFlashAddr-sizeof(block_meta_data_t); //1008
|
||||||
|
//update newBlockAddr in list
|
||||||
|
_info->firstBlock = (block_meta_data_t*)newBlockFlashAddr;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
newBlockFlashAddr = getRowAddr(previousBlockFlashAddr - (size+sizeof(block_meta_data_t)));
|
||||||
|
newBlock.size = previousBlockFlashAddr-newBlockFlashAddr-sizeof(block_meta_data_t); //1008
|
||||||
|
//copy found block into ram and update newBlockAddr in list
|
||||||
|
previousBlock = *((block_meta_data_t*)previousBlockFlashAddr);
|
||||||
|
previousBlock.next = (block_meta_data_t*)newBlockFlashAddr;
|
||||||
|
}
|
||||||
|
//set MemoryStart to end of new block
|
||||||
|
_info->freeMemoryStart = newBlockFlashAddr-1; //260863
|
||||||
|
}
|
||||||
|
//fill meta data of new block
|
||||||
|
newBlock.validMask = VALID;
|
||||||
|
newBlock.ID = ID;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//check if size fits into free area
|
||||||
|
if(_info->freeMemoryStart - (size+sizeof(block_meta_data_t)) <= _MemoryEnd)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
//get start address of new block
|
||||||
|
newBlockFlashAddr = getRowAddr(_info->freeMemoryStart +1 - (size+sizeof(block_meta_data_t))); //260864 (size= 1024-16=1008)
|
||||||
|
newBlock.size = _info->freeMemoryStart-newBlockFlashAddr+1-sizeof(block_meta_data_t); //1008
|
||||||
|
newBlock.next = NULL;
|
||||||
|
//set MemoryStart to end of new block
|
||||||
|
_info->freeMemoryStart = newBlockFlashAddr-1; //260863
|
||||||
|
//fill meta data of new block
|
||||||
|
newBlock.validMask = VALID;
|
||||||
|
newBlock.ID = ID;
|
||||||
|
|
||||||
|
//add block to end of list
|
||||||
|
tempBlock = findLastBlock();//(block_meta_data_t*)previousBlockFlashAddr;
|
||||||
|
if(tempBlock == NULL){
|
||||||
|
_info->firstBlock = (block_meta_data_t*)newBlockFlashAddr;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//copy found block into ram
|
||||||
|
previousBlock = *tempBlock;
|
||||||
|
previousBlock.next = (block_meta_data_t*)newBlockFlashAddr;
|
||||||
|
previousBlockFlashAddr = (uint32_t)tempBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//write modified ram info structure into last flash row
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
|
||||||
|
//write modified ram copy of last block meta into flash
|
||||||
|
if(previousBlockFlashAddr != 0){
|
||||||
|
_rowBufferAddr = previousBlockFlashAddr;
|
||||||
|
downloadRowBuffer(_rowBufferAddr);
|
||||||
|
//map block meta structure into ram copy
|
||||||
|
tempBlock = (block_meta_data_t*)_rowBuffer;
|
||||||
|
//copy into row buffer
|
||||||
|
*tempBlock = previousBlock;
|
||||||
|
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//write ram copy of new block meta into flash
|
||||||
|
_rowBufferAddr = newBlockFlashAddr;
|
||||||
|
downloadRowBuffer(_rowBufferAddr);
|
||||||
|
//map block meta structure into ram copy
|
||||||
|
tempBlock = (block_meta_data_t*)_rowBuffer;
|
||||||
|
//copy into row buffer
|
||||||
|
*tempBlock = newBlock;
|
||||||
|
_rowBufferModified = true;
|
||||||
|
uploadRowBuffer(_rowBufferAddr);
|
||||||
|
|
||||||
|
//config structure now points into updated flash again
|
||||||
|
_info = (info_data_t*)getRowAddr(_pageSize*_pageCnt-1);
|
||||||
|
return (uint8_t*)(newBlockFlashAddr+sizeof(block_meta_data_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* SamdFlash::realloc(uint32_t size, uint32_t ID){
|
||||||
|
uint32_t newBlockFlashAddr;
|
||||||
|
block_meta_data_t* actualBlock;
|
||||||
|
|
||||||
|
actualBlock = getBlock(ID);
|
||||||
|
|
||||||
|
//check if ID is presenty
|
||||||
|
if(actualBlock == NULL)
|
||||||
|
return malloc(size, ID);
|
||||||
|
|
||||||
|
//if size already fits into block, nothing to do otherwise alloc block with new size
|
||||||
|
if(actualBlock->size >= size)
|
||||||
|
return loadBlock(ID);
|
||||||
|
|
||||||
|
newBlockFlashAddr = (uint32_t)(forcemalloc(size, ID)-sizeof(block_meta_data_t));
|
||||||
|
copyAndFree(actualBlock, (block_meta_data_t*)newBlockFlashAddr);
|
||||||
|
return (uint8_t*)(newBlockFlashAddr+sizeof(block_meta_data_t));
|
||||||
|
}
|
59
src/samd_flash.h
Normal file
59
src/samd_flash.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#ifndef SAMD_FLASH_H
|
||||||
|
#define SAMD_FLASH_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define PAGES_PER_ROW 4
|
||||||
|
|
||||||
|
typedef struct block_meta_data{
|
||||||
|
uint32_t validMask;
|
||||||
|
uint32_t ID;
|
||||||
|
uint32_t size;
|
||||||
|
struct block_meta_data *next;
|
||||||
|
}__attribute__((__packed__))block_meta_data_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t validMask;
|
||||||
|
uint32_t freeMemoryStart;
|
||||||
|
block_meta_data_t* firstBlock;
|
||||||
|
}__attribute__((__packed__))info_data_t;
|
||||||
|
|
||||||
|
class SamdFlash{
|
||||||
|
public:
|
||||||
|
SamdFlash();
|
||||||
|
void erase();
|
||||||
|
void erase(uint32_t ID);
|
||||||
|
void free(uint32_t ID);
|
||||||
|
uint8_t* malloc(uint32_t size, uint32_t ID);
|
||||||
|
uint8_t* realloc(uint32_t size, uint32_t ID);
|
||||||
|
uint8_t* loadBlock(uint32_t ID);
|
||||||
|
bool write(uint8_t* addr, uint8_t data);
|
||||||
|
uint8_t read(uint8_t* addr);
|
||||||
|
void finalise();
|
||||||
|
uint32_t getStartAddress();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t* forcemalloc(uint32_t size, uint32_t ID);
|
||||||
|
void uploadRowBuffer(uint32_t rowAddr);
|
||||||
|
void downloadRowBuffer(uint32_t rowAddr);
|
||||||
|
uint32_t getRowAddr(uint32_t flasAddr);
|
||||||
|
void eraseRow(uint32_t rowAddr);
|
||||||
|
void copyAndFree(block_meta_data_t* src, block_meta_data_t* dst);
|
||||||
|
|
||||||
|
|
||||||
|
block_meta_data_t* findEmptyBlock(uint32_t size,uint32_t* compSize, uint32_t* nextBlockAddr);
|
||||||
|
block_meta_data_t* findLastBlock();
|
||||||
|
block_meta_data_t* getBlock(uint32_t ID);
|
||||||
|
|
||||||
|
uint32_t _MemoryEnd=0;
|
||||||
|
uint32_t _pageSize;
|
||||||
|
uint32_t _rowSize;
|
||||||
|
uint32_t _pageCnt;
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t* _rowBuffer;
|
||||||
|
bool _rowBufferModified = false;
|
||||||
|
uint32_t _rowBufferAddr;
|
||||||
|
volatile info_data_t* _info;
|
||||||
|
};
|
||||||
|
#endif /* SAMD_FLASH_H */
|
@ -4,14 +4,18 @@
|
|||||||
#include <knx/bits.h>
|
#include <knx/bits.h>
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <FlashAsEEPROM.h>
|
#include "samd_flash.h"
|
||||||
|
|
||||||
|
SamdFlash Flash;
|
||||||
|
|
||||||
SamdPlatform::SamdPlatform() : ArduinoPlatform(&Serial1)
|
SamdPlatform::SamdPlatform() : ArduinoPlatform(&Serial1)
|
||||||
{
|
{
|
||||||
|
Platform::_NVMemoryType = internalFlash;
|
||||||
}
|
}
|
||||||
|
|
||||||
SamdPlatform::SamdPlatform( HardwareSerial* s) : ArduinoPlatform(s)
|
SamdPlatform::SamdPlatform( HardwareSerial* s) : ArduinoPlatform(s)
|
||||||
{
|
{
|
||||||
|
Platform::_NVMemoryType = internalFlash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SamdPlatform::restart()
|
void SamdPlatform::restart()
|
||||||
@ -20,19 +24,121 @@ void SamdPlatform::restart()
|
|||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * SamdPlatform::getEepromBuffer(uint16_t size)
|
|
||||||
|
bool SamdPlatform::writeNVMemory(uint32_t addr,uint8_t data)
|
||||||
{
|
{
|
||||||
//EEPROM.begin(size);
|
if(Flash.write((uint8_t*)addr, data)==false)
|
||||||
if(size > EEPROM_EMULATION_SIZE)
|
|
||||||
fatalError();
|
fatalError();
|
||||||
|
return true;
|
||||||
return EEPROM.getDataPtr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SamdPlatform::commitToEeprom()
|
uint8_t SamdPlatform::readNVMemory(uint32_t addr)
|
||||||
|
{
|
||||||
|
return Flash.read((uint8_t*)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdPlatform::allocNVMemory(uint32_t size,uint32_t ID)
|
||||||
|
{
|
||||||
|
uint32_t addr = (uint32_t)Flash.malloc(size, ID);
|
||||||
|
if(addr == 0)
|
||||||
|
fatalError();
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdPlatform::reloadNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
// Flash.erase();
|
||||||
|
return (uint32_t)Flash.loadBlock(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdPlatform::finishNVMemory()
|
||||||
|
{
|
||||||
|
Flash.finalise();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdPlatform::freeNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
Flash.free(ID);
|
||||||
|
// Flash.erase();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* SamdPlatform::memoryReference()
|
||||||
|
{
|
||||||
|
return (uint8_t*)Flash.getStartAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************_NVMemoryType = internalRam*************************
|
||||||
|
|
||||||
|
bool SamdPlatform::writeNVMemory(uint32_t addr,uint8_t data)
|
||||||
|
{
|
||||||
|
*((uint8_t*)addr) = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SamdPlatform::readNVMemory(uint32_t addr)
|
||||||
|
{
|
||||||
|
return *((uint8_t*)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdPlatform::allocNVMemory(uint32_t size,uint32_t ID)
|
||||||
|
{
|
||||||
|
if(size > EEPROM_EMULATION_SIZE)
|
||||||
|
fatalError();
|
||||||
|
return (uint32_t)EEPROM.getDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdPlatform::reloadNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
return (uint32_t)EEPROM.getDataPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdPlatform::finishNVMemory()
|
||||||
{
|
{
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SamdPlatform::freeNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
/*************_NVMemoryType = external*************************
|
||||||
|
bool SamdPlatform::writeNVMemory(uint32_t addr,uint8_t data)
|
||||||
|
{
|
||||||
|
EEPROM.write(addr-1, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SamdPlatform::readNVMemory(uint32_t addr)
|
||||||
|
{
|
||||||
|
return EEPROM.read(addr-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdPlatform::allocNVMemory(uint32_t size,uint32_t ID)
|
||||||
|
{
|
||||||
|
if(size > EEPROM_EMULATION_SIZE)
|
||||||
|
fatalError();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SamdPlatform::reloadNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdPlatform::finishNVMemory()
|
||||||
|
{
|
||||||
|
EEPROM.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SamdPlatform::freeNVMemory(uint32_t ID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,8 +11,13 @@ public:
|
|||||||
SamdPlatform( HardwareSerial* s);
|
SamdPlatform( HardwareSerial* s);
|
||||||
|
|
||||||
void restart();
|
void restart();
|
||||||
uint8_t* getEepromBuffer(uint16_t size);
|
bool writeNVMemory(uint32_t addr,uint8_t data);
|
||||||
void commitToEeprom();
|
uint8_t readNVMemory(uint32_t addr);
|
||||||
|
uint32_t allocNVMemory(uint32_t size,uint32_t ID);
|
||||||
|
uint32_t reloadNVMemory(uint32_t ID);
|
||||||
|
void finishNVMemory();
|
||||||
|
void freeNVMemory(uint32_t ID);
|
||||||
|
uint8_t* memoryReference();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user