0
\$\begingroup\$

I am writing to the internal flash of my SAMD21G18A microcontroller.

I want to erase one row (4 pages), and manually write to one page just to understand the NVMCTRL abit more.

this is the code FYI:

#include <sam.h>

setup()
{
     //code
     #define KEY                0xA500
     #define PAGE_BUFFER_CLR    0x0044
     #define WRITE_PAGE         0x0004
     #define ERASE_ROW          0x0002

     uint8_t data [64];

     int i = 0;
     for(i = 0; i < 64; i++)
          data[i] = i+10;

     uint8_t val[64];

     for(i = 0; i < 64; i++)
          val[i] = 0;

     uint8_t * src_ptr = data;
     uint8_t * dest_ptr = val;

     uint16_t ADDR_VAL;
     uint16_t addr = 0x4000;
     uint16_t addr_start_of_region = 0x0000;
     ADDR_VAL = (addr - addr_start_of_region) / 2;
     
     //erase region
     NVMCTRL->ADDR.reg = ADDR_VAL;
     delay(1);
     NVMCTRL->CTRLA.reg = KEY | ERASE_ROW;
     delay(1);
     while(!NVMCTRL->INTFLAG.bit.READY);
     delay(1);

     delay(100);

     //write to one page at address 0x4000
     NVMCTRL->CTRLB.bit.MANW = 1;
     delay(1);

     //clear buffer
     NVMCTRL->CTRLA.reg = KEY | PAGE_BUFFER_CLR;
     delay(1);
     while(!NVMCTRL->INTFLAG.bit.READY);
     delay(1);

     //write to dest
     for(i = 0; i < 64; i ++)
          dest_ptr[i] = src_ptr[i];

     NVMCTRL->CTRLA.reg = KEY | WRITE_PAGE;
     delay(1);

     delay(100);
}

loop()
{}
     
     

This is my understanding of the write to the NVM procedure as per the NVMCTRL chapter (chapter 22) of the datasheet (link).

  • my intended address is 0x4000, hence NVMCTRL->ADDR.reg = 0x2000 as our address = start_of_region_address + 2*ADDR`

  • send erase row command NVMCTRL->CTRLA.reg = 0xA502

  • clear the page buffer NVMCTRL->CTRLA.reg = 0xA544

  • address the main address space directly via the AHB bus. i.e for(int i = 0; i < 64; i++){dest[i] = src[i]} where 64 is the page size in bytes, and dest and src are pointers (uint8_t*)

  • send the write command NVMCTRL->CTRLA.reg = 0xA504

However, when I write and build the code above, debug and watch the memory I only see 0xFFFFFFFF starting at address 0x4000.

Any help would be really appreciated.

\$\endgroup\$
6
  • \$\begingroup\$ Did you take a look at Atmel's NVM Driver? \$\endgroup\$
    – Velvet
    Sep 5, 2022 at 14:55
  • 1
    \$\begingroup\$ is there a "write protection bit" for the flash by chance ? \$\endgroup\$
    – Rahmany
    Sep 5, 2022 at 15:09
  • \$\begingroup\$ @Rahmany I don't think so, there are in CTRLB, Cache enabled/disabled, ReadMode, and at the STATUS register there is the security enabled / disabled bit. \$\endgroup\$ Sep 5, 2022 at 20:40
  • \$\begingroup\$ @Sier, you I know, but unfortunately the task I am doing requires me to address the registers directly \$\endgroup\$ Sep 5, 2022 at 20:41
  • \$\begingroup\$ Most embedded driver libraries I've used also provide the source code, which can be analyzed. \$\endgroup\$
    – Velvet
    Sep 6, 2022 at 6:47

2 Answers 2

1
\$\begingroup\$

As mentioned by @housecat I've also worked with ATSAM devices specifically the ATSAM4S and ATSAMS70. I've never been successful with using the debugger while writing to flash memory. I had the same issue as you described.

Here's how I verified that the flash memory was properly being written to.

Write a function that reads in the the flash address and stores it in a variable. Then increment that variable and write that to flash. Make sure that this only happens one time. Make an if statement that if the stored value is greater than 5 AND less than 10 that it lights up an LED. Otherwise leave the LED off.

After you've programmed the board, power cycle it multiple times. After the 5 or 6 times the LED will come on. Then after another 5 power cycles of the MCU the LED won't come on anymore. This verifies that you're reading and writing to flash memory correctly.

\$\endgroup\$
0
\$\begingroup\$

I've only worked with the ATSAM4S with the EEFC peripheral, but the main thing I've noticed using Atmel (Microchip) Studio is that the debugger does not always read the blocks of flash memory to update the memory view when paused. You might try printing the memory contents to your console.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.