mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	- Get rid of EEPROM emulation
- Use SAMD-Flash without copying parameters to RAM
This commit is contained in:
		
							parent
							
								
									a306174878
								
							
						
					
					
						commit
						85b5655835
					
				| @ -4,17 +4,29 @@ | ||||
| #include <knx/bits.h> | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| #ifdef USE_SAMD_EEPROM_EMULATION | ||||
| #include <FlashAsEEPROM.h> | ||||
| #endif | ||||
| 
 | ||||
| #if KNX_FLASH_SIZE % 1024 | ||||
| #error "KNX_FLASH_SIZE must be multiple of 1024" | ||||
| #endif | ||||
| 
 | ||||
| SamdPlatform::SamdPlatform() | ||||
| #ifndef KNX_NO_DEFAULT_UART | ||||
|     : ArduinoPlatform(&Serial1) | ||||
| #endif | ||||
| { | ||||
| #ifndef USE_SAMD_EEPROM_EMULATION | ||||
|     init(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| SamdPlatform::SamdPlatform( HardwareSerial* s) : ArduinoPlatform(s) | ||||
| { | ||||
| #ifndef USE_SAMD_EEPROM_EMULATION | ||||
|     init(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| uint32_t SamdPlatform::uniqueSerialNumber() | ||||
| @ -43,7 +55,9 @@ void SamdPlatform::restart() | ||||
|     NVIC_SystemReset(); | ||||
| } | ||||
| 
 | ||||
| uint8_t * SamdPlatform::getEepromBuffer(uint16_t size) | ||||
| #ifdef USE_SAMD_EEPROM_EMULATION | ||||
| #pragma warning "Using EEPROM Simulation" | ||||
| uint8_t* SamdPlatform::getEepromBuffer(uint16_t size) | ||||
| { | ||||
|     //EEPROM.begin(size);
 | ||||
|     if(size > EEPROM_EMULATION_SIZE) | ||||
| @ -56,6 +70,156 @@ void SamdPlatform::commitToEeprom() | ||||
| { | ||||
|     EEPROM.commit(); | ||||
| } | ||||
| #else | ||||
| 
 | ||||
| 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}; | ||||
| 
 | ||||
| void SamdPlatform::init() | ||||
| { | ||||
|     _memoryType = Flash; | ||||
|     _pageSize = pageSizes[NVMCTRL->PARAM.bit.PSZ]; | ||||
|     _pageCnt = NVMCTRL->PARAM.bit.NVMP; | ||||
|     _rowSize = PAGES_PER_ROW * _pageSize; | ||||
| 
 | ||||
|     // find end of program flash and set limit to next row
 | ||||
|     uint32_t endEddr = (uint32_t)(&__etext + (&__data_end__ - &__data_start__)); // text + data MemoryBlock
 | ||||
|     _MemoryStart = getRowAddr(_pageSize * _pageCnt - KNX_FLASH_SIZE - 1);        // 23295
 | ||||
|     _MemoryEnd = getRowAddr(_pageSize * _pageCnt - 1); | ||||
|     // chosen flash size is not available anymore
 | ||||
|     if (_MemoryStart < endEddr) { | ||||
|         println("KNX_FLASH_SIZE is not available (possible too much flash use by firmware)"); | ||||
|         fatalError(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| size_t SamdPlatform::flashEraseBlockSize() | ||||
| { | ||||
|     return PAGES_PER_ROW; | ||||
| } | ||||
| 
 | ||||
| size_t SamdPlatform::flashPageSize() | ||||
| { | ||||
|     return _pageSize; | ||||
| } | ||||
| 
 | ||||
| uint8_t* SamdPlatform::userFlashStart() | ||||
| { | ||||
|     return (uint8_t*)_MemoryStart; | ||||
| } | ||||
| 
 | ||||
| size_t SamdPlatform::userFlashSizeEraseBlocks() | ||||
| { | ||||
|     if (KNX_FLASH_SIZE <= 0) | ||||
|         return 0; | ||||
|     else | ||||
|         return ((KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1; | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::flashErase(uint16_t eraseBlockNum) | ||||
| { | ||||
|     noInterrupts(); | ||||
| 
 | ||||
|     eraseRow((void *)(_MemoryStart + eraseBlockNum * _rowSize)); | ||||
|     // flash_range_erase(KNX_FLASH_OFFSET + eraseBlockNum * flashPageSize() * flashEraseBlockSize(), flashPageSize() * flashEraseBlockSize());
 | ||||
| 
 | ||||
|     interrupts(); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::flashWritePage(uint16_t pageNumber, uint8_t* data) | ||||
| { | ||||
|     noInterrupts(); | ||||
| 
 | ||||
|     write((void *)(_MemoryStart + pageNumber * _pageSize), data, _pageSize); | ||||
|     // flash_range_program(KNX_FLASH_OFFSET + pageNumber * flashPageSize(), data, flashPageSize());
 | ||||
| 
 | ||||
|     interrupts(); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::writeBufferedEraseBlock() | ||||
| { | ||||
|     if (_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty) | ||||
|     { | ||||
|         noInterrupts(); | ||||
| 
 | ||||
|         eraseRow((void *)(_MemoryStart + _bufferedEraseblockNumber * _rowSize)); | ||||
|         write((void *)(_MemoryStart + _bufferedEraseblockNumber * _rowSize), _eraseblockBuffer, _rowSize); | ||||
|         // flash_range_erase(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), flashPageSize() * flashEraseBlockSize());
 | ||||
|         // flash_range_program(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), _eraseblockBuffer, flashPageSize() * flashEraseBlockSize());
 | ||||
| 
 | ||||
|         interrupts(); | ||||
| 
 | ||||
|         _bufferedEraseblockDirty = false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| uint32_t SamdPlatform::getRowAddr(uint32_t flasAddr) | ||||
| { | ||||
|     return flasAddr & ~(_rowSize - 1); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::write(const volatile void *flash_ptr, const void *data, uint32_t size) | ||||
| { | ||||
|     // Calculate data boundaries
 | ||||
|     size = (size + 3) / 4; | ||||
|     volatile uint32_t *src_addr = (volatile uint32_t *)data; | ||||
|     volatile uint32_t *dst_addr = (volatile uint32_t *)flash_ptr; | ||||
|     // volatile uint32_t *dst_addr = (volatile uint32_t *)flash_ptr;
 | ||||
|     // const uint8_t *src_addr = (uint8_t *)data;
 | ||||
| 
 | ||||
|     // Disable automatic page write
 | ||||
|     NVMCTRL->CTRLB.bit.MANW = 1; | ||||
| 
 | ||||
|     // Do writes in pages
 | ||||
|     while (size) | ||||
|     { | ||||
|         // Execute "PBC" Page Buffer Clear
 | ||||
|         NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC; | ||||
|         while (NVMCTRL->INTFLAG.bit.READY == 0) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         // Fill page buffer
 | ||||
|         uint32_t i; | ||||
|         for (i = 0; i < (_pageSize / 4) && size; i++) | ||||
|         { | ||||
|             *dst_addr = *src_addr; | ||||
|             src_addr++; | ||||
|             dst_addr++; | ||||
|             size--; | ||||
|         } | ||||
| 
 | ||||
|         // Execute "WP" Write Page
 | ||||
|         NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP; | ||||
|         while (NVMCTRL->INTFLAG.bit.READY == 0) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::erase(const volatile void *flash_ptr, uint32_t size) | ||||
| { | ||||
|     const uint8_t *ptr = (const uint8_t *)flash_ptr; | ||||
|     while (size > _rowSize) | ||||
|     { | ||||
|         eraseRow(ptr); | ||||
|         ptr += _rowSize; | ||||
|         size -= _rowSize; | ||||
|     } | ||||
|     eraseRow(ptr); | ||||
| } | ||||
| 
 | ||||
| void SamdPlatform::eraseRow(const volatile void *flash_ptr) | ||||
| { | ||||
|     NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2; | ||||
|     NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER; | ||||
|     while (!NVMCTRL->INTFLAG.bit.READY) | ||||
|     { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -4,6 +4,8 @@ | ||||
| 
 | ||||
| #ifdef ARDUINO_ARCH_SAMD | ||||
| 
 | ||||
| #define PAGES_PER_ROW 4 | ||||
| 
 | ||||
| class SamdPlatform : public ArduinoPlatform | ||||
| { | ||||
| public: | ||||
| @ -14,8 +16,40 @@ public: | ||||
|     uint32_t uniqueSerialNumber() override; | ||||
| 
 | ||||
|     void restart(); | ||||
| #ifdef USE_SAMD_EEPROM_EMULATION | ||||
|     uint8_t* getEepromBuffer(uint16_t size); | ||||
|     void commitToEeprom(); | ||||
| #else | ||||
|     // 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(); | ||||
|     // size of the user flash in EraseBlocks
 | ||||
|     virtual size_t userFlashSizeEraseBlocks(); | ||||
|     // relativ to userFlashStart
 | ||||
|     virtual void flashErase(uint16_t eraseBlockNum); | ||||
|     // write a single page to flash (pageNumber relative to userFashStart
 | ||||
|     virtual void flashWritePage(uint16_t pageNumber, uint8_t* data); | ||||
| 
 | ||||
|     // writes _eraseblockBuffer to flash - overrides Plattform::writeBufferedEraseBlock() for performance optimization only
 | ||||
|     void writeBufferedEraseBlock(); | ||||
| 
 | ||||
| private: | ||||
|   void init(); | ||||
|   uint32_t _MemoryEnd = 0; | ||||
|   uint32_t _MemoryStart = 0; | ||||
|   uint32_t _pageSize; | ||||
|   uint32_t _rowSize; | ||||
|   uint32_t _pageCnt; | ||||
| 
 | ||||
|   uint32_t getRowAddr(uint32_t flasAddr); | ||||
|   void write(const volatile void* flash_ptr, const void* data, uint32_t size); | ||||
|   void erase(const volatile void* flash_ptr, uint32_t size); | ||||
|   void eraseRow(const volatile void* flash_ptr); | ||||
| 
 | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user