2.3 Flash Programming
In the AVR DA family, the Flash accesses are handled through the NVM controller. This means that each part (in blocks of 32 KB) of the Flash area is mapped into data space by utilizing the NVMCTRL.CTRLB register and the erase and write operations are handled by utilizing the NVMCTRL.CTRLA register.
The current implementation of the bootloader uses program memory space to
access the entire Flash. The addressing is done using LPM/SPM
instructions.
The Flash is erased by page and is written with word granularity when it is
mapped in the program memory space. To write a word, the page that contains the
respective word address must be previously erased, otherwise the result will be an
AND
between the existing value and the new one.
The current implementation of the bootloader assumes that the write address
is incremented step-by-step, so the Flash Page Erase (FLPER
) command is
sent via the NVMCTRL.CTRLA register when the write address enters a new page. To
effectively start the erase operation, a dummy write to the selected page needs to be
executed:
if((addr_flash % MAPPED_PROGMEM_PAGE_SIZE) == 0x0000) //new page { /* Wait for completion of previous command */ while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm) { ; } /* Clear the current command */ _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc); /* Erase the flash page */ _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc); /* Dummy write to start erase operation */ pgm_word_write(flash_addr, 0x00); }
NOCMD
) or No Operation
(NOOP
). Otherwise, the Command Collision error will be set in the
ERROR bit field in the NVMCTRL.STATUS register and the current command will not be
executed. The write operation is initiated by writing a Flash Write Enable
(FLWR
) command into the NVMCTRL.CTRLA register. After this command,
multiple byte writes are allowed to the selected page locations, as long as no other
command is written into the NVMCTRL.CTRLA register.
/* Enable flash Write Mode */
_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
/* Program flash word with desired value*/
pgm_word_write((flash_addr & 0xFFFFFE), data_word);