diff --git a/src/knx/platform.cpp b/src/knx/platform.cpp index fa6906c..e71c35a 100644 --- a/src/knx/platform.cpp +++ b/src/knx/platform.cpp @@ -133,6 +133,12 @@ size_t Platform::getNonVolatileMemorySize() void Platform::commitNonVolatileMemory() { + if(_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty) + { + writeBufferedEraseBlock(_bufferedEraseblockNumber); + + // _bufferedEraseblockNumber = -1; // does that make sense? + } } uint32_t Platform::writeNonVolatileMemory(uint32_t relativeAddress, uint8_t* buffer, size_t size) @@ -172,26 +178,39 @@ void Platform::loadEraseblockContaining(uint32_t relativeAddress) uint32_t Platform::bufferedEraseBlockStart() { - return _bufferedEraseblockNumber * flashEraseBlockSize(); + return _bufferedEraseblockNumber * (flashEraseBlockSize() * flashPageSize()); } uint32_t Platform::bufferedEraseBlockEnd() { - return (_bufferedEraseblockNumber + 1) * flashEraseBlockSize() -1; + return (_bufferedEraseblockNumber + 1) * (flashEraseBlockSize() * flashPageSize()) -1; } int32_t Platform::getEraseBlockNumberOf(uint32_t relativeAddress) { - return -1; + return relativeAddress / (flashEraseBlockSize() * flashPageSize()); } void Platform::writeBufferedEraseBlock() { + if(_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty) + { + flashErase(_bufferedEraseblockNumber); + for(int i = 0; i< ; i++) + { // ToDo + flashWritePage(); + } + _bufferedEraseblockDirty = false; + } } void Platform::bufferEraseBlock(uint32_t eraseBlockNumber) { + memcpy(_eraseblockBuffer, userFlashStart() + eraseBlockNumber * flashEraseBlockSize() * flashPageSize(), flashEraseBlockSize() * flashPageSize()); + + _bufferedEraseblockNumber = eraseBlockNumber; + _bufferedEraseblockDirty = false; } diff --git a/src/knx/platform.h b/src/knx/platform.h index e32e1f6..05616b6 100644 --- a/src/knx/platform.h +++ b/src/knx/platform.h @@ -59,9 +59,12 @@ class Platform protected: // Flash memory - virtual size_t flashEraseBlockSize(); // in pages - virtual size_t flashPageSize(); // in bytes - virtual uint8_t* userFlashStart(); // start of user flash aligned to start of an erase block + // size of one EraseBlock in pages + virtual size_t flashEraseBlockSize(); + // size of one flash page in bytes + virtual size_t flashPageSize(); + // start of user flash aligned to start of an erase block + virtual uint8_t* userFlashStart(); virtual size_t userFlashSizeEraseBlocks(); // in eraseBlocks virtual void flashErase(uint16_t eraseBlockNum); //relativ to userFlashStart virtual void flashWritePage(uint16_t pageNumber, uint8_t* data); //write a single page to flash (pageNumber relative to userFashStart @@ -73,7 +76,9 @@ class Platform uint32_t bufferedEraseBlockStart(); uint32_t bufferedEraseBlockEnd(); int32_t getEraseBlockNumberOf(uint32_t relativeAddress); + // writes _eraseblockBuffer to flash void writeBufferedEraseBlock(); + // copies a EraseBlock into the _eraseblockBuffer void bufferEraseBlock(uint32_t eraseBlockNumber); // in theory we would have to use this buffer for memory reads too, diff --git a/src/rp2040_arduino_platform.cpp b/src/rp2040_arduino_platform.cpp index 72341f5..392a9de 100644 --- a/src/rp2040_arduino_platform.cpp +++ b/src/rp2040_arduino_platform.cpp @@ -16,7 +16,7 @@ For more, use or own emulation (maybe with littlefs) #include "rp2040_arduino_platform.h" #ifdef ARDUINO_ARCH_RP2040 -#include +#include "knx/bits.h" #include @@ -24,6 +24,7 @@ For more, use or own emulation (maybe with littlefs) #include // EEPROM emulation in flash, part of Earl E Philhowers Pi Pico Arduino support #include // from Pico SDK #include // from Pico SDK +#include // from Pico SDK RP2040ArduinoPlatform::RP2040ArduinoPlatform() @@ -77,6 +78,56 @@ void RP2040ArduinoPlatform::commitToEeprom() { EEPROM.commit(); } + + +size_t RP2040ArduinoPlatform::flashEraseBlockSize() +{ + return 16; // 16 pages x 256byte/page = 4096byte +} + +size_t RP2040ArduinoPlatform::flashPageSize() +{ + return 256; +} + +uint8_t* RP2040ArduinoPlatform::userFlashStart() +{ + // TODO + // XIP_BASE + KNX_FLASH_OFFSET + return nullptr; +} + +size_t RP2040ArduinoPlatform::userFlashSizeEraseBlocks() +{ + if(KNX_FLASH_SIZE <= 0) + return 0; + else + return ( (KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1; +} + +void RP2040ArduinoPlatform::flashErase(uint16_t eraseBlockNum) +{ + noInterrupts(); + rp2040.idleOtherCore(); + + // TODO: calculate position in flash + flash_range_erase (0x100, flashPageSize() * flashEraseBlockSize()); + + rp2040.resumeOtherCore(); + interrupts(); +} + +void RP2040ArduinoPlatform::flashWritePage(uint16_t pageNumber, uint8_t* data) +{ + noInterrupts(); + rp2040.idleOtherCore(); + + // TODO: calculate position in flash + flash_range_program(0x100, data, flashPageSize()); + + rp2040.resumeOtherCore(); + interrupts(); +} #endif diff --git a/src/rp2040_arduino_platform.h b/src/rp2040_arduino_platform.h index 3077b21..1b19451 100644 --- a/src/rp2040_arduino_platform.h +++ b/src/rp2040_arduino_platform.h @@ -4,6 +4,14 @@ #ifdef ARDUINO_ARCH_RP2040 +#ifndef KNX_FLASH_OFFSET +#define KNX_FLASH_OFFSET 0x180000 // 1.5MiB +#endif + +#ifndef KNX_FLASH_SIZE +#define KNX_FLASH_SIZE 1024 +#endif + class RP2040ArduinoPlatform : public ArduinoPlatform { public: @@ -11,11 +19,20 @@ public: RP2040ArduinoPlatform( HardwareSerial* s); // unique serial number - uint32_t uniqueSerialNumber() override; + uint32_t uniqueSerialNumber(); //override; void restart(); uint8_t* getEepromBuffer(uint16_t size); void commitToEeprom(); + + + + size_t flashEraseBlockSize(); // in bytes + size_t flashPageSize(); // in bytes + uint8_t* userFlashStart(); // start of user flash aligned to start of an erase block + size_t userFlashSizeEraseBlocks(); // in eraseBlocks + void flashErase(uint16_t eraseBlockNum); //relativ to userFlashStart + void flashWritePage(uint16_t pageNumber, uint8_t* data); //write a single page to flash (pageNumber relative to userFashStart }; #endif