SAME54 flash partial write problem

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

Hi,

 

I'm having problems writing to the internal flash of a SAME54P20A MCU on a SAME54 Xplained Pro board. I'm seeing flash corruption and getting errors with the debugger stopping to respond.

 

The problem was discovered in a bigger code base, but I've managed to reproduce it with using a small Atmel Start based example. Using the LED flasher example and adding a Flash driver component to the project, I've modified the FLASH_0_example() function like so:

static uint8_t chk_data[512];
/**
 * Example of using FLASH_0 to read and write Flash main array.
 */
void FLASH_0_example(void)
{
    uint8_t a1[16] = {0x1a, 0x27, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x00, 0xff, 0xff, 0xad, 0xfd, 0x00, 0x00, 0x00, 0x00};
    uint8_t a2[4] = {0xa5, 0x5a, 0xaa, 0x55};

    uint8_t b1[28] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x34, 0x00, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    uint8_t b2[4] = {0xa5, 0x5a, 0xaa, 0x55};

    flash_append(&FLASH_0, 0x80024, a1, sizeof(a1));
    flash_read(&FLASH_0, 0x80024, &chk_data[0x24], sizeof(a1));

    flash_append(&FLASH_0, 0x80020, a2, sizeof(a2));
    flash_read(&FLASH_0, 0x80020, &chk_data[0x20], sizeof(a2));

    flash_append(&FLASH_0, 0x80004, b1, sizeof(b1));
    flash_read(&FLASH_0, 0x80004, &chk_data[0x04], sizeof(b1));

    flash_append(&FLASH_0, 0x80000, b2, sizeof(b2));                // <-- This write is corrupted
    flash_read(&FLASH_0, 0x80000, &chk_data[0x00], sizeof(b2));     // <-- Debugger stops working after this line
}

 

And the main() function:

int main(void)
{
    atmel_start_init();

    FLASH_0_example();

    while (true) {
        delay_ms(500);
        gpio_toggle_pin_level(LED0);
    }
}

 

As you can see I'm doing partial writes to the flash. The error that occurs is
that the last write is corrupted:

 

0x00080000  a5 5a aa 15 01 00 00 00 00 00 80 3f 00 00 00 00  ¥Zª.......€?....  // <-- The first bytes should be a5 5a aa 55
0x00080010  00 00 00 00 01 00 34 00 0a ff ff ff ff ff ff ff  ......4..ÿÿÿÿÿÿÿ
0x00080020  a5 5a aa 55 1a 27 00 00 00 0f 04 00 ff ff ad fd  ¥ZªU.'......ÿÿ.ý
0x00080030  00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff  ....ÿÿÿÿÿÿÿÿÿÿÿÿ

 

Another problem that occurs is that the debugger stops working after the last read and stops responding. The LED also does not blink, so the loop is not entered. If I run the project without a debugger the LED blinks, so the MCU does not lock up in that case. But reading back the flash memory using the debugger, I can see that the same flash corruption occurs.

 

I've tried disabling the cache lines in the NVM controller, but it does not help. Does anyone know why this is happening? Does the SAME54 not support multiple partial writes to it's internal flash pages? I can't find anything in the data sheet about any limitations.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to dig down into flash_append() to see exactly what it's doing. If it is simply overwriting the existing contents with new data without first erasing the page, then all bets are off. The SAME5x Flash controller implements ECC, so re-writing a page with no intervening erase will most likely result in a bad ECC, which will likely lead to the fault handler being invoked when the memory is accessed. Worst case, the core could enter lock-up.

 

It sounds like the SmartEEPROM feature would be more suitable for your needs.

 

Steve

Maverick Embedded Technologies Ltd. Home of Maven and wAVR.

Maven: WiFi ARM Cortex-M Debugger/Programmer

wAVR: WiFi AVR ISP/PDI/uPDI Programmer

https://www.maverick-embedded.co...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the reply! I found the cause of the error yesterday, and you are right that it is because of ECC.

 

For every 8 bytes there is an ECC, meaning that partial writes of 8 byte blocks can cause ECC failures. The ECC errors are discovered during reads, that's why the debugger stopped responding after the read. (It is still strange that the debugger stopped working and that I couldn't see any of the fault handlers being entered).

I've since updated the writes to be 8 byte aligned, and now it is working.

 

flash_append() only writes, and does not erase the block first. This is exactly what I need. I see no mention of partial writes not being supported by the MCU in the data sheet. It mentions that partial page writes must be done using manual mode. It also supports automatic writes with dual and quad word granularity. I don't want to use the SmartEEPROM feature since the code implements its own wear leveling and other features. (The data sheet also says that ECC is disabled for SmartEEPROM, I guess since it has the same issues with partial writes and ECC).

 

Do you see any issues with partial writes if the writes are ECC-block (8-bytes) aligned?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tech1234 wrote:

Do you see any issues with partial writes if the writes are ECC-block (8-bytes) aligned?

 

While it will fix the ECC issue, you're still re-writing a page (16-bytes) without an intervening erase. Someone from Microchip will need to comment on how that may or may not affect the Flash's endurance. The data sheet says "1. An endurance cycle is a write-and-erase operation."; it says nothing about double-write. The effects of this will vary according to how the Flash cells are implemented.

 

Steve

Maverick Embedded Technologies Ltd. Home of Maven and wAVR.

Maven: WiFi ARM Cortex-M Debugger/Programmer

wAVR: WiFi AVR ISP/PDI/uPDI Programmer

https://www.maverick-embedded.co...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you find any explanation or solution? Because I have the same problem.