3 #ifdef ARDUINO_ARCH_SAMD
7 #ifdef USE_SAMD_EEPROM_EMULATION
8 #include <FlashAsEEPROM.h>
11 #if KNX_FLASH_SIZE % 1024
12 #error "KNX_FLASH_SIZE must be multiple of 1024"
16 #define KNX_SERIAL Serial1
20 #ifndef KNX_NO_DEFAULT_UART
24 #ifndef USE_SAMD_EEPROM_EMULATION
31 #ifndef USE_SAMD_EEPROM_EMULATION
38 #if defined (__SAMD51__)
40 #define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x008061FC)
41 #define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x00806010)
42 #define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x00806014)
43 #define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x00806018)
47 #define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
48 #define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
49 #define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
50 #define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)
53 return SERIAL_NUMBER_WORD_0 ^ SERIAL_NUMBER_WORD_1 ^ SERIAL_NUMBER_WORD_2 ^ SERIAL_NUMBER_WORD_3;
62 #ifdef USE_SAMD_EEPROM_EMULATION
63 #pragma warning "Using EEPROM Simulation"
67 if (size > EEPROM_EMULATION_SIZE)
70 return EEPROM.getDataPtr();
83 static const uint32_t pageSizes[] = {8, 16, 32, 64, 128, 256, 512, 1024};
85 void SamdPlatform::init()
88 _pageSize = pageSizes[NVMCTRL->PARAM.bit.PSZ];
89 _pageCnt = NVMCTRL->PARAM.bit.NVMP;
90 _rowSize = PAGES_PER_ROW * _pageSize;
94 #ifdef KNX_FLASH_OFFSET
95 _MemoryStart = KNX_FLASH_OFFSET;
96 _MemoryEnd = KNX_FLASH_OFFSET + KNX_FLASH_SIZE;
98 _MemoryStart = getRowAddr(_pageSize * _pageCnt - KNX_FLASH_SIZE - 1);
99 _MemoryEnd = getRowAddr(_pageSize * _pageCnt - 1);
103 if (_MemoryStart < endEddr)
105 println(
"KNX_FLASH_SIZE is not available (possible too much flash use by firmware)");
112 return PAGES_PER_ROW;
122 return (uint8_t*)_MemoryStart;
127 if (KNX_FLASH_SIZE <= 0)
137 eraseRow((
void*)(_MemoryStart + eraseBlockNum * _rowSize));
147 write((
void*)(_MemoryStart + pageNumber * _pageSize), data, _pageSize);
170 uint32_t SamdPlatform::getRowAddr(uint32_t flasAddr)
172 return flasAddr & ~(_rowSize - 1);
175 void SamdPlatform::write(
const volatile void* flash_ptr,
const void* data, uint32_t size)
178 size = (size + 3) / 4;
179 volatile uint32_t* src_addr = (
volatile uint32_t*)data;
180 volatile uint32_t* dst_addr = (
volatile uint32_t*)flash_ptr;
185 NVMCTRL->CTRLB.bit.MANW = 1;
191 NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
193 while (NVMCTRL->INTFLAG.bit.READY == 0)
200 for (i = 0; i < (_pageSize / 4) && size; i++)
202 *dst_addr = *src_addr;
209 NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
211 while (NVMCTRL->INTFLAG.bit.READY == 0)
217 void SamdPlatform::erase(
const volatile void* flash_ptr, uint32_t size)
219 const uint8_t* ptr = (
const uint8_t*)flash_ptr;
221 while (size > _rowSize)
231 void SamdPlatform::eraseRow(
const volatile void* flash_ptr)
233 NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
234 NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
236 while (!NVMCTRL->INTFLAG.bit.READY)