mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	fix merge conflict
This commit is contained in:
		
						commit
						1226103126
					
				| @ -34,8 +34,8 @@ before_install: | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -i 's#compiler.warning_level=all#compiler.warning_level=default#' ~/.arduino15/preferences.txt; fi | ||||
|     # changes for bsec lib | ||||
|     # samd | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -ri 's#(recipe.c.combine.pattern=[^$]*\{archive_file\}")( -Wl,--end-group)#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/arduino/hardware/samd/1.8.3/platform.txt; fi | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/arduino/hardware/samd/1.8.3/platform.txt; fi | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -ri 's#(recipe.c.combine.pattern=[^$]*\{archive_file\}")( -Wl,--end-group)#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/arduino/hardware/samd/1.8.4/platform.txt; fi | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/arduino/hardware/samd/1.8.4/platform.txt; fi | ||||
|     # esp8266 | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -ri 's#(recipe.c.combine.pattern=[^$]*\{compiler.c.elf.libs\})( -Wl,--end-group  "-L\{build.path\}")#\1 {compiler.libraries.ldflags}\2#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/platform.txt; fi | ||||
|     - if [ "$MODE" = "ARDUINO" ]; then sed -i 's#compiler.elf2hex.extra_flags=#compiler.elf2hex.extra_flags=\ncompiler.libraries.ldflags=#' ~/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/platform.txt; fi | ||||
|  | ||||
| @ -84,15 +84,34 @@ int Esp32Platform::readBytes(uint8_t * buffer, uint16_t maxLen) | ||||
|     return len; | ||||
| } | ||||
| 
 | ||||
| uint8_t * Esp32Platform::getEepromBuffer(uint16_t size) | ||||
| bool Esp32Platform::writeNVMemory(uintptr_t addr,uint8_t data) | ||||
| { | ||||
|     EEPROM.begin(size); | ||||
|     return EEPROM.getDataPtr(); | ||||
|     *((uint8_t*)addr) = data; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void Esp32Platform::commitToEeprom() | ||||
| uint8_t Esp32Platform::readNVMemory(uintptr_t addr) | ||||
| { | ||||
|     return *((uint8_t*)addr); | ||||
| } | ||||
| 
 | ||||
| uintptr_t Esp32Platform::allocNVMemory(size_t size,uint32_t ID) | ||||
| { | ||||
|     return (uintptr_t)EEPROM.getDataPtr(); | ||||
| } | ||||
| 
 | ||||
| uintptr_t Esp32Platform::reloadNVMemory(uint32_t ID) | ||||
| { | ||||
|     EEPROM.begin(1024); | ||||
|     return (uintptr_t)EEPROM.getDataPtr(); | ||||
| } | ||||
| 
 | ||||
| void Esp32Platform::finishNVMemory() | ||||
| { | ||||
|     EEPROM.commit(); | ||||
| } | ||||
| 
 | ||||
| void Esp32Platform::freeNVMemory(uint32_t ID) | ||||
| { | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -28,8 +28,12 @@ public: | ||||
|     int readBytes(uint8_t* buffer, uint16_t maxLen) override; | ||||
|      | ||||
|     //memory
 | ||||
|     uint8_t* getEepromBuffer(uint16_t size); | ||||
|     void commitToEeprom(); | ||||
|     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); | ||||
|     void finishNVMemory(); | ||||
|     void freeNVMemory(uint32_t ID); | ||||
| private: | ||||
|     WiFiUDP _udp; | ||||
| }; | ||||
|  | ||||
| @ -85,14 +85,34 @@ int EspPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) | ||||
|     return len; | ||||
| } | ||||
| 
 | ||||
| uint8_t * EspPlatform::getEepromBuffer(uint16_t size) | ||||
| bool EspPlatform::writeNVMemory(uintptr_t addr,uint8_t data) | ||||
| { | ||||
|     EEPROM.begin(size); | ||||
|     return EEPROM.getDataPtr(); | ||||
|     *((uint8_t*)addr) = data; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void EspPlatform::commitToEeprom() | ||||
| uint8_t EspPlatform::readNVMemory(uintptr_t addr) | ||||
| { | ||||
|     return *((uint8_t*)addr); | ||||
| } | ||||
| 
 | ||||
| uintptr_t EspPlatform::allocNVMemory(size_t size,uint32_t ID) | ||||
| { | ||||
|     return (uintptr_t)EEPROM.getDataPtr(); | ||||
| } | ||||
| 
 | ||||
| uintptr_t EspPlatform::reloadNVMemory(uint32_t ID) | ||||
| { | ||||
|     EEPROM.begin(1024); | ||||
|     return (uintptr_t)EEPROM.getDataPtr(); | ||||
| } | ||||
| 
 | ||||
| void EspPlatform::finishNVMemory() | ||||
| { | ||||
|     EEPROM.commit(); | ||||
| } | ||||
| 
 | ||||
| void EspPlatform::freeNVMemory(uint32_t ID) | ||||
| { | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -29,8 +29,12 @@ class EspPlatform : public ArduinoPlatform | ||||
|     int readBytes(uint8_t* buffer, uint16_t maxLen) override; | ||||
|     | ||||
|     //memory
 | ||||
|     uint8_t* getEepromBuffer(uint16_t size); | ||||
|     void commitToEeprom(); | ||||
|     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); | ||||
|     void finishNVMemory(); | ||||
|     void freeNVMemory(uint32_t ID); | ||||
| private: | ||||
|     WiFiUDP _udp; | ||||
| }; | ||||
|  | ||||
| @ -74,6 +74,35 @@ uint32_t ApplicationProgramObject::getInt(uint32_t 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; | ||||
|     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* ApplicationProgramObject::save(uint8_t* buffer) | ||||
| { | ||||
|     buffer = pushByteArray(_programVersion, 5, buffer); | ||||
| @ -83,8 +112,8 @@ uint8_t* ApplicationProgramObject::save(uint8_t* buffer) | ||||
| 
 | ||||
| uint8_t* ApplicationProgramObject::restore(uint8_t* buffer) | ||||
| { | ||||
|     TableObject::_dataComplete = buffer; | ||||
|     buffer = popByteArray(_programVersion, 5, buffer); | ||||
| 
 | ||||
|     return TableObject::restore(buffer); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -14,7 +14,9 @@ class ApplicationProgramObject : public TableObject | ||||
|     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); | ||||
|     uint32_t size(); | ||||
| 
 | ||||
|   protected: | ||||
|     uint8_t propertyCount(); | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
| BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platform), | ||||
|     _assocTable(platform), _groupObjTable(platform), _appProgram(platform), | ||||
|     _platform(platform), _appLayer(_assocTable, *this), | ||||
|     _transLayer(_appLayer, _addrTable), _netLayer(_transLayer) | ||||
|     _transLayer(_appLayer, _addrTable), _netLayer(_transLayer), _deviceObj(platform) | ||||
| { | ||||
|     _appLayer.transportLayer(_transLayer); | ||||
|     _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, | ||||
|     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((uintptr_t)_platform.memoryReference() + memoryAddress+i, data[i]); | ||||
|     } | ||||
|     else | ||||
|         memcpy(_platform.memoryReference() + memoryAddress, data, number); | ||||
| 
 | ||||
|     _memory.memoryModified(); | ||||
| 
 | ||||
|     if (_deviceObj.verifyMode()) | ||||
| @ -149,8 +155,18 @@ 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); | ||||
| 
 | ||||
|         _appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,buffer); | ||||
|         delete[] buffer; | ||||
|     } | ||||
|     else{ | ||||
|     _appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress, | ||||
|         _platform.memoryReference() + memoryAddress); | ||||
|             _platform.memoryReference() + memoryAddress); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap) | ||||
| @ -167,13 +183,28 @@ void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, ui | ||||
| 
 | ||||
| void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress) | ||||
| { | ||||
|     _appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress, | ||||
|         _platform.memoryReference() + 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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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((uintptr_t)_platform.memoryReference() + memoryAddress+i, data[i]); | ||||
|     } | ||||
|     else{ | ||||
|         memcpy(_platform.memoryReference() + memoryAddress, data, number); | ||||
|     } | ||||
|     _memory.memoryModified(); | ||||
| 
 | ||||
|     if (_deviceObj.verifyMode()) | ||||
|  | ||||
| @ -2,6 +2,15 @@ | ||||
| #include "device_object.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) | ||||
| { | ||||
|     switch (propertyId) | ||||
| @ -106,6 +115,32 @@ uint8_t DeviceObject::propertySize(PropertyID id) | ||||
|     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); | ||||
|         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); | ||||
|  | ||||
| @ -1,15 +1,19 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "interface_object.h" | ||||
| #include "platform.h" | ||||
| 
 | ||||
| class DeviceObject: public InterfaceObject | ||||
| { | ||||
| public: | ||||
|     DeviceObject(Platform& platform); | ||||
|     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); | ||||
|     uint32_t size(); | ||||
|     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 _manufacturerId = 0xfa; //Default to KNXA
 | ||||
|     uint32_t _bauNumber = 0; | ||||
|     char _orderNumber[10] = ""; | ||||
|     uint8_t _hardwareType[6] = { 0, 0, 0, 0, 0, 0}; | ||||
|     char _orderNumber[10]; | ||||
|     uint8_t _hardwareType[6]; | ||||
|     uint16_t _version = 0; | ||||
|     Platform& _platform; | ||||
| }; | ||||
| @ -1810,7 +1810,7 @@ void float16ToPayload(uint8_t* payload, size_t payload_length, int index, double | ||||
|     if (wasNegative) | ||||
|         mantissa *= -1; | ||||
| 
 | ||||
|     println(mantissa); | ||||
|  //   println(mantissa);
 | ||||
|      | ||||
|     signed16ToPayload(payload, payload_length, index, mantissa, mask); | ||||
|     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); | ||||
|     else | ||||
|         payload[index / 2] = (payload[index / 2] & 0x0F) | ((value << 4) & 0xF0); | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,15 @@ | ||||
| 
 | ||||
| //224.0.23.12
 | ||||
| #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), | ||||
|     _platform(platform) | ||||
| @ -146,6 +155,38 @@ uint8_t IpParameterObject::propertySize(PropertyID id) | ||||
|     } | ||||
|     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); | ||||
|         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* IpParameterObject::save(uint8_t* buffer) | ||||
| { | ||||
| @ -320,4 +361,4 @@ uint8_t IpParameterObject::propertyCount() | ||||
| PropertyDescription* IpParameterObject::propertyDescriptions() | ||||
| { | ||||
|     return _propertyDescriptions; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -13,7 +13,9 @@ class IpParameterObject : public InterfaceObject | ||||
|     uint8_t propertySize(PropertyID id); | ||||
| 
 | ||||
|     uint8_t* save(uint8_t* buffer); | ||||
|     uint8_t* save(); | ||||
|     uint8_t* restore(uint8_t* buffer); | ||||
|     uint32_t size(); | ||||
| 
 | ||||
|     uint32_t multicastAddress() const; | ||||
|     uint8_t ttl() const { return _ttl; } | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| #include "memory.h" | ||||
| 
 | ||||
| #define BASE_ID     0xC0DE0000 | ||||
| 
 | ||||
| Memory::Memory(Platform & platform): _platform(platform) | ||||
| { | ||||
| } | ||||
| @ -14,9 +16,66 @@ bool Memory::isMemoryModified() | ||||
|     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) | ||||
|         return; | ||||
| @ -26,11 +85,20 @@ void Memory::readMemory() | ||||
|     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::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[1] = 0xAD; | ||||
|     _data[2] = 0xAF; | ||||
| @ -41,16 +109,103 @@ void Memory::writeMemory() | ||||
|     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.commitToEeprom(); | ||||
|     _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) | ||||
|         return; | ||||
| 
 | ||||
|     obj->memoryID(BASE_ID + _saveCount); | ||||
|     _saveRestores[_saveCount] = obj; | ||||
|     _saveCount += 1; | ||||
| } | ||||
|  | ||||
| @ -16,6 +16,12 @@ 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}; | ||||
|  | ||||
| @ -12,6 +12,8 @@ uint8_t* Platform::memoryReference() | ||||
| uint8_t* Platform::allocMemory(size_t size) | ||||
| { | ||||
|     uint8_t* address =  (uint8_t*)malloc(size); | ||||
|     if(address == NULL) | ||||
|         fatalError(); | ||||
| //    if (_memoryReference == 0 || address < _memoryReference)
 | ||||
| //        _memoryReference = address;
 | ||||
| 	print("MemRef: "); | ||||
|  | ||||
| @ -4,6 +4,13 @@ | ||||
| #include <stddef.h> | ||||
| #include "save_restore.h" | ||||
| 
 | ||||
| typedef enum{ | ||||
|     notDefined, | ||||
|     internalRam, | ||||
|     internalFlash, | ||||
|     external | ||||
| }NVMemory_t; | ||||
| 
 | ||||
| class Platform | ||||
| { | ||||
|   public: | ||||
| @ -29,13 +36,18 @@ class Platform | ||||
|     virtual int readUart() = 0; | ||||
|     virtual size_t readBytesUart(uint8_t* buffer, size_t length) = 0; | ||||
| 
 | ||||
|     virtual uint8_t* getEepromBuffer(uint16_t size) = 0; | ||||
|     virtual void commitToEeprom() = 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; | ||||
|     virtual void finishNVMemory() = 0; | ||||
|     virtual void freeNVMemory(uint32_t ID) = 0; | ||||
| 
 | ||||
|     virtual uint8_t* memoryReference(); | ||||
|     virtual uint8_t* allocMemory(size_t size); | ||||
|     virtual void freeMemory(uint8_t* ptr); | ||||
| 
 | ||||
|     NVMemory_t NVMemoryType(){return _NVMemoryType;} | ||||
|   protected: | ||||
|     uint8_t* _memoryReference = 0; | ||||
| }; | ||||
|     NVMemory_t _NVMemoryType = notDefined; | ||||
| }; | ||||
|  | ||||
| @ -16,6 +16,7 @@ class SaveRestore | ||||
|      * the start of its buffer. | ||||
|      */ | ||||
|     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. | ||||
|      *   | ||||
| @ -25,4 +26,8 @@ class SaveRestore | ||||
|      * the start of its buffer. | ||||
|      */ | ||||
|     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 "bits.h" | ||||
| 
 | ||||
| #define METADATA_SIZE     (sizeof(_state)+sizeof(_errorCode)+sizeof(_size)) | ||||
| 
 | ||||
| TableObject::TableObject(Platform& platform): _platform(platform) | ||||
| { | ||||
| 
 | ||||
| @ -92,11 +94,40 @@ uint8_t* TableObject::save(uint8_t* buffer) | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| uint8_t* TableObject::save() | ||||
| { | ||||
|     if(_data == NULL) | ||||
|         return NULL; | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| uint8_t* TableObject::restore(uint8_t* buffer) | ||||
| { | ||||
|     uint8_t state = 0; | ||||
|     uint8_t errorCode = 0; | ||||
|     if(_dataComplete == NULL) | ||||
|         _dataComplete = buffer; | ||||
|     buffer = popByte(state, buffer); | ||||
|     buffer = popByte(errorCode, buffer); | ||||
|     _state = (LoadState)state; | ||||
| @ -104,15 +135,13 @@ uint8_t* TableObject::restore(uint8_t* buffer) | ||||
| 
 | ||||
|     buffer = popInt(_size, buffer); | ||||
| 
 | ||||
|     if (_data) | ||||
|         _platform.freeMemory(_data); | ||||
| 
 | ||||
|     if (_size > 0) | ||||
|         _data = _platform.allocMemory(_size); | ||||
|         _data = buffer; | ||||
| 
 | ||||
|     else | ||||
|         _data = 0; | ||||
| 
 | ||||
|     buffer = popByteArray(_data, _size, buffer); | ||||
|     buffer += _size; | ||||
| 
 | ||||
|     return buffer; | ||||
| } | ||||
| @ -124,9 +153,13 @@ uint32_t TableObject::tableReference() | ||||
| 
 | ||||
| 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; | ||||
|         _size = 0; | ||||
|     } | ||||
| @ -134,15 +167,24 @@ bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte) | ||||
|     if (size == 0) | ||||
|         return true; | ||||
|      | ||||
|     _data = _platform.allocMemory(size); | ||||
|     if (!_data) | ||||
|         return false; | ||||
| 
 | ||||
|     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
 | ||||
|     _size = size; | ||||
| 
 | ||||
|     if (doFill) | ||||
|         memset(_data, fillByte, 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); | ||||
|         } | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| @ -279,10 +321,15 @@ uint8_t* TableObject::data() | ||||
| 
 | ||||
| uint32_t TableObject::size() | ||||
| { | ||||
|     return _size; | ||||
|     return _size + METADATA_SIZE; | ||||
| } | ||||
| 
 | ||||
| uint32_t TableObject::sizeMetadata() | ||||
| { | ||||
|     return METADATA_SIZE; | ||||
| } | ||||
| 
 | ||||
| void TableObject::errorCode(ErrorCode errorCode) | ||||
| { | ||||
|     _errorCode = errorCode; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -26,7 +26,9 @@ public: | ||||
|      */ | ||||
|     LoadState loadState(); | ||||
|     virtual uint8_t* save(uint8_t* buffer); | ||||
|     virtual uint8_t* save(); | ||||
|     virtual uint8_t* restore(uint8_t* buffer); | ||||
|     virtual uint32_t size(); | ||||
| protected: | ||||
|     /**
 | ||||
|      * This method is called before the interface object enters a new ::LoadState. | ||||
| @ -40,15 +42,18 @@ protected: | ||||
|      * must not be freed. | ||||
|      */ | ||||
|     uint8_t* data(); | ||||
|     uint32_t sizeMetadata(); | ||||
|     /**
 | ||||
|      * 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. | ||||
|      */ | ||||
|     void errorCode(ErrorCode errorCode); | ||||
| 
 | ||||
|     Platform& _platform; | ||||
|     uint8_t *_dataComplete = 0; | ||||
|   private: | ||||
|     uint32_t tableReference(); | ||||
|     bool allocTable(uint32_t size, bool doFill, uint8_t fillByte); | ||||
| @ -67,7 +72,6 @@ protected: | ||||
|      */ | ||||
|     void loadState(LoadState newState); | ||||
|     LoadState _state = LS_UNLOADED; | ||||
|     Platform& _platform; | ||||
|     uint8_t *_data = 0; | ||||
|     uint32_t _size = 0; | ||||
|     ErrorCode _errorCode = E_NO_FAULT; | ||||
|  | ||||
| @ -276,9 +276,18 @@ template <class P, class B> class KnxFacade : private SaveRestore | ||||
|     uint32_t _buttonPin = 0; | ||||
|     saveRestoreCallback _saveCallback = 0; | ||||
|     saveRestoreCallback _restoreCallback = 0; | ||||
|     uint32_t (*_sizeCallback)() = 0; | ||||
|     bool _toogleProgMode = false; | ||||
|     bool _progLedState = false; | ||||
| 
 | ||||
|     uint32_t size() | ||||
|     { | ||||
|         if (_sizeCallback != 0) | ||||
|             return _sizeCallback(); | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     uint8_t* save(uint8_t* buffer) | ||||
|     { | ||||
|         if (_saveCallback != 0) | ||||
| @ -287,6 +296,10 @@ template <class P, class B> class KnxFacade : private SaveRestore | ||||
|         return buffer; | ||||
|     } | ||||
| 
 | ||||
|     uint8_t* save() | ||||
|     { | ||||
|     }; | ||||
| 
 | ||||
|     uint8_t* restore(uint8_t* buffer) | ||||
|     { | ||||
|         if (_restoreCallback != 0) | ||||
| @ -304,4 +317,4 @@ extern KnxFacade<EspPlatform, Bau57B0> knx; | ||||
| extern KnxFacade<Esp32Platform, Bau57B0> knx; | ||||
| #elif __linux__ | ||||
| // no predefined global instance
 | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -200,22 +200,44 @@ int LinuxPlatform::readBytes(uint8_t * buffer, uint16_t maxLen) | ||||
|     return len; | ||||
| } | ||||
| 
 | ||||
| uint8_t * LinuxPlatform::getEepromBuffer(uint16_t size) | ||||
| bool LinuxPlatform::writeNVMemory(uintptr_t addr,uint8_t data) | ||||
| { | ||||
|     if (_fd < 0) | ||||
|         doMemoryMapping(); | ||||
|      | ||||
|     return _mappedFile + 2; | ||||
|     *((uint8_t*)addr) = data; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void LinuxPlatform::commitToEeprom() | ||||
| uint8_t LinuxPlatform::readNVMemory(uintptr_t addr) | ||||
| { | ||||
|     return *((uint8_t*)addr); | ||||
| } | ||||
| 
 | ||||
| uintptr_t LinuxPlatform::allocNVMemory(size_t size,uint32_t ID) | ||||
| { | ||||
|     if (_fd < 0) | ||||
|         doMemoryMapping(); | ||||
|      | ||||
|     return (uintptr_t)(_mappedFile + 2); | ||||
| } | ||||
| 
 | ||||
| uintptr_t LinuxPlatform::reloadNVMemory(uint32_t ID) | ||||
| { | ||||
|     if (_fd < 0) | ||||
|         doMemoryMapping(); | ||||
|      | ||||
|     return (uintptr_t)(_mappedFile + 2); | ||||
| } | ||||
| 
 | ||||
| void LinuxPlatform::finishNVMemory() | ||||
| { | ||||
|     if (_fd < 0) | ||||
|         doMemoryMapping(); | ||||
| 
 | ||||
|     fsync(_fd); | ||||
| } | ||||
| 
 | ||||
| void LinuxPlatform::freeNVMemory(uint32_t ID) | ||||
| { | ||||
| } | ||||
| #define FLASHSIZE 0x10000 | ||||
| void LinuxPlatform::doMemoryMapping() | ||||
| { | ||||
| @ -519,4 +541,4 @@ void LinuxPlatform::cmdLineArgs(int argc, char** argv) | ||||
|     memcpy(_args, argv, argc * sizeof(char*)); | ||||
|     _args[argc] = 0; | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| @ -44,8 +44,12 @@ public: | ||||
|     size_t readBytesUart(uint8_t *buffer, size_t length) override; | ||||
| 
 | ||||
|     //memory
 | ||||
|     uint8_t* getEepromBuffer(uint16_t size) override; | ||||
|     void commitToEeprom() override; | ||||
|     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); | ||||
|     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); | ||||
| @ -62,4 +66,4 @@ public: | ||||
|     char** _args = 0; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										418
									
								
								src/samd_flash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										418
									
								
								src/samd_flash.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,418 @@ | ||||
| #ifdef ARDUINO_ARCH_SAMD | ||||
| #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)); | ||||
| } | ||||
| #endif /* ARDUINO_ARCH_SAMD */ | ||||
							
								
								
									
										61
									
								
								src/samd_flash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/samd_flash.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| #ifndef SAMD_FLASH_H | ||||
| #define SAMD_FLASH_H | ||||
| 
 | ||||
| #ifdef ARDUINO_ARCH_SAMD | ||||
| #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 /* ARDUINO_ARCH_SAMD */ | ||||
| #endif /* SAMD_FLASH_H */ | ||||
| @ -4,14 +4,18 @@ | ||||
| #include <knx/bits.h> | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| #include <FlashAsEEPROM.h> | ||||
| #include "samd_flash.h" | ||||
| 
 | ||||
| SamdFlash Flash; | ||||
| 
 | ||||
| SamdPlatform::SamdPlatform() : ArduinoPlatform(&Serial1) | ||||
| { | ||||
|     Platform::_NVMemoryType = internalFlash; | ||||
| } | ||||
| 
 | ||||
| SamdPlatform::SamdPlatform( HardwareSerial* s) : ArduinoPlatform(s) | ||||
| { | ||||
|     Platform::_NVMemoryType = internalFlash; | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::restart() | ||||
| @ -20,19 +24,121 @@ void SamdPlatform::restart() | ||||
|     NVIC_SystemReset(); | ||||
| } | ||||
| 
 | ||||
| uint8_t * SamdPlatform::getEepromBuffer(uint16_t size) | ||||
| 
 | ||||
| bool SamdPlatform::writeNVMemory(uintptr_t addr,uint8_t data) | ||||
| { | ||||
|     //EEPROM.begin(size);
 | ||||
|     if(size > EEPROM_EMULATION_SIZE) | ||||
|     if(Flash.write((uint8_t*)addr, data)==false) | ||||
|         fatalError(); | ||||
|      | ||||
|     return EEPROM.getDataPtr(); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::commitToEeprom() | ||||
| uint8_t SamdPlatform::readNVMemory(uintptr_t addr) | ||||
| { | ||||
|     return Flash.read((uint8_t*)addr); | ||||
| } | ||||
| 
 | ||||
| uintptr_t SamdPlatform::allocNVMemory(size_t size,uint32_t ID) | ||||
| { | ||||
|     uintptr_t addr = (uintptr_t)Flash.malloc(size, ID); | ||||
|     if(addr == 0) | ||||
|         fatalError(); | ||||
|     return addr; | ||||
| } | ||||
| 
 | ||||
| uintptr_t SamdPlatform::reloadNVMemory(uint32_t ID) | ||||
| { | ||||
|  //  Flash.erase();
 | ||||
|    return (uintptr_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(uintptr_t addr,uint8_t data) | ||||
| { | ||||
|     *((uint8_t*)addr) = data; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| uint8_t SamdPlatform::readNVMemory(uintptr_t addr) | ||||
| { | ||||
|     return *((uint8_t*)addr); | ||||
| } | ||||
| 
 | ||||
| uintptr_t SamdPlatform::allocNVMemory(size_t size,uint32_t ID) | ||||
| { | ||||
|     if(size > EEPROM_EMULATION_SIZE) | ||||
|         fatalError(); | ||||
|     return (uintptr_t)EEPROM.getDataPtr(); | ||||
| } | ||||
| 
 | ||||
| uintptr_t SamdPlatform::reloadNVMemory(uint32_t ID) | ||||
| { | ||||
|     return (uintptr_t)EEPROM.getDataPtr(); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::finishNVMemory() | ||||
| { | ||||
|     EEPROM.commit(); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::freeNVMemory(uint32_t ID) | ||||
| { | ||||
| } | ||||
| /*
 | ||||
| 
 | ||||
| /*************_NVMemoryType = external*************************
 | ||||
| bool SamdPlatform::writeNVMemory(uintptr_t addr,uint8_t data) | ||||
| { | ||||
|     EEPROM.write(addr-1, data); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| uint8_t SamdPlatform::readNVMemory(uintptr_t addr) | ||||
| { | ||||
|     return EEPROM.read(addr-1); | ||||
| } | ||||
| 
 | ||||
| uintptr_t SamdPlatform::allocNVMemory(size_t size,uint32_t ID) | ||||
| { | ||||
|     if(size > EEPROM_EMULATION_SIZE) | ||||
|         fatalError(); | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| uintptr_t SamdPlatform::reloadNVMemory(uint32_t ID) | ||||
| { | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::finishNVMemory() | ||||
| { | ||||
|     EEPROM.commit(); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::freeNVMemory(uint32_t ID) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -11,8 +11,13 @@ public: | ||||
|     SamdPlatform( HardwareSerial* s); | ||||
| 
 | ||||
|     void restart(); | ||||
|     uint8_t* getEepromBuffer(uint16_t size); | ||||
|     void commitToEeprom(); | ||||
|     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); | ||||
|     void finishNVMemory(); | ||||
|     void freeNVMemory(uint32_t ID); | ||||
|     uint8_t* memoryReference(); | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user