Skip to content

Commit

Permalink
Initial SAMD51 support (#104)
Browse files Browse the repository at this point in the history
Volodymyr, thank you for the contribution. code looks good, it compiles for other boards. I can't check more. Merged.
  • Loading branch information
vshymanskyy authored Jul 30, 2021
1 parent 91471fa commit b17bec1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
41 changes: 36 additions & 5 deletions src/InternalStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,41 @@ extern "C" {

__attribute__ ((long_call, noinline, section (".data#"))) //
void waitForReady() {
#if defined(ARDUINO_ARCH_SAMD)
#if defined(__SAMD51__)
while (!NVMCTRL->STATUS.bit.READY);
#elif defined(ARDUINO_ARCH_SAMD)
while (!NVMCTRL->INTFLAG.bit.READY);
#elif defined(ARDUINO_ARCH_NRF5)
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
#endif
}

#if defined(__SAMD51__)
// Invalidate all CMCC cache entries if CMCC cache is enabled.
__attribute__ ((long_call, noinline, section (".data#")))
static void invalidate_CMCC_cache()
{
if (CMCC->SR.bit.CSTS) {
CMCC->CTRL.bit.CEN = 0;
while (CMCC->SR.bit.CSTS) {}
CMCC->MAINT0.bit.INVALL = 1;
CMCC->CTRL.bit.CEN = 1;
}
}
#endif

__attribute__ ((long_call, noinline, section (".data#")))
static void eraseFlash(int address, int length, int pageSize)
{
#if defined(ARDUINO_ARCH_SAMD)
#if defined(__SAMD51__)
int rowSize = (pageSize * NVMCTRL->PARAM.bit.NVMP) / 64;
for (int i = 0; i < length; i += rowSize) {
NVMCTRL->ADDR.reg = ((uint32_t)(address + i));
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
waitForReady();
invalidate_CMCC_cache();
}
#elif defined(ARDUINO_ARCH_SAMD)
int rowSize = pageSize * 4;
for (int i = 0; i < length; i += rowSize) {
NVMCTRL->ADDR.reg = ((uint32_t)(address + i)) / 2;
Expand Down Expand Up @@ -94,7 +118,7 @@ extern "C" {
__attribute__ ((long_call, noinline, section (".data#")))
static void copyFlashAndReset(int dest, int src, int length, int pageSize)
{
uint32_t* d = (uint32_t*)dest;
volatile uint32_t* d = (volatile uint32_t*)dest;
uint32_t* s = (uint32_t*)src;

eraseFlash(dest, length, pageSize);
Expand All @@ -115,8 +139,15 @@ int InternalStorageClass::open(int length)
_writeIndex = 0;
_writeAddress = (uint32_t*)STORAGE_START_ADDRESS;

#ifdef ARDUINO_ARCH_SAMD
// enable auto page writes
#if defined(__SAMD51__)
// Enable auto dword writes
NVMCTRL->CTRLA.bit.WMODE = NVMCTRL_CTRLA_WMODE_ADW_Val;
waitForReady();
// Disable NVMCTRL cache while writing, per SAMD51 errata
NVMCTRL->CTRLA.bit.CACHEDIS0 = 1;
NVMCTRL->CTRLA.bit.CACHEDIS1 = 1;
#elif defined(ARDUINO_ARCH_SAMD)
// Enable auto page writes
NVMCTRL->CTRLB.bit.MANW = 0;
#endif

Expand Down
6 changes: 5 additions & 1 deletion src/OTAStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
#if defined(ARDUINO_ARCH_SAMD)
static const uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
static const uint32_t eepromSizes[] = { 16384, 8192, 4096, 2048, 1024, 512, 256, 0 };
#define EEPROM_EMULATION_RESERVATION ((*(uint32_t*)(NVMCTRL_FUSES_EEPROM_SIZE_ADDR) & NVMCTRL_FUSES_EEPROM_SIZE_Msk) >> NVMCTRL_FUSES_EEPROM_SIZE_Pos)
#if defined(__SAMD51__)
# define EEPROM_EMULATION_RESERVATION 0
#else
# define EEPROM_EMULATION_RESERVATION ((*(uint32_t*)(NVMCTRL_FUSES_EEPROM_SIZE_ADDR) & NVMCTRL_FUSES_EEPROM_SIZE_Msk) >> NVMCTRL_FUSES_EEPROM_SIZE_Pos)
#endif
extern "C" {
char * __text_start__(); // 0x2000, 0x0 without bootloader and 0x4000 for M0 original bootloader
}
Expand Down

0 comments on commit b17bec1

Please sign in to comment.