SAM4N problems with memcpy from flash

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi there,

I have created a custom bootloader that uses an SPI flash to store images. Everything is working well, except that when the firmware first boots it needs to backup the current firmware to the flash. To do this, I have a loop that does a memcpy from a pointer to the SAM flash memory into a buffer, and then writes the buffer to the SPI flash. What I have discovered is that after memcpy the contents of the buffer are not always the same as what is actually stored in the SAM flash memory. Here is an excerpt from the spi flash write function to make this clearer:

 

int8_t
flash_write(spi_flash_ptr addr, uint32_t size, uint8_t *buf) {
    uint8_t cmd[4 + PAGE_SIZE];
    int8_t retval = ERR_IO_ERROR;

    if (size > PAGE_SIZE) {
        retval = ERR_INVALID_ARG;
        goto end;
    }

    cmd[0] = PageProgram;
    cmd[1] = (uint8_t)((addr >> 16) & 0xff);
    cmd[2] = (uint8_t)((addr >> 8) & 0xff);
    cmd[3] = (uint8_t)(addr & 0xff);

    /* We need to write enable before we can write */
    if (write_enable() != STATUS_OK) goto end;

    memcpy(cmd + 4, buf, size);

This failure is repeatable with certain flash memory addresses: when this function is called with buf = 0x404300, and size = 256, the bytes stored at 0x404354 and 0x0404355 are copied incorrectly. If I stop execution just after the memcpy (last line), cmd has incorrect content, but only for those two bytes, the rest is perfect.

 

I can't really understand how this can happen. I have played with the EFC settings. By default it is set to 128 bit access mode with 6 wait states. These don't seem to make any difference however. 

 

Can anyone provide any help? Thanks.

Last Edited: Fri. Nov 10, 2017 - 03:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I eventually figured out this really frustrating problem.

 

First of all, one very odd thing is that whatever I set the EFC MR to it is always reset to 0x00000600 (6 wait states) on the next function call. Which doesn't make a lot of sense (since we really want 4 wait states), maybe the debugger is forcing this?

 

To debug the problem I manually patched each failed address in the write function above as I found them, so that the correct bytes got written instead, and then forced my bootloader to write the new image from SPI flash to the MCU flash. Then I could use the atmel studio programming tool to verify the MCU flash, and see the next address where the read had failed, to see if there was some pattern. I used readelf and objdump to disassemble the binary and look for symbols matching the failure addresses. After all this, it turned out that the read failures were at locations where I had breakpoints enabled! So for example in my first post above I mentioned address 0x404354 as the first location where the SAM integrated flash read failure occurs. This is the entry point of the main function, which I just happened to have a breakpoint on (for no particular reason).

 

Does anyone know of a note about this somewhere in the Atmel documentation? Because I looked through the datasheet and looked for errata but didn't see anything!

Last Edited: Mon. Nov 20, 2017 - 10:45 AM