Flash Memory Corruption - SAM E70

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

I am seeing corrupt bytes when I write then examine the built-in flash memory on a SAM E70 (custom) board. Basically, I am writing 2 sectors of the (previously erased) flash at a time (262,144 bytes) with a 1-255 pattern stored in an identically sized (262,144 byte) buffer in SRAM. I am using the ASF built-in flash_write() function to write the flash memory. I then check the flash memory element by element, comparing it to my SRAM buffer. I have verified in the memory view of the debugger that some of the flash bytes are indeed corrupt/wrong.

 

A few observations:

- The corrupted sections seem to always occur in 4 byte sequences

- These 4 byte sequences are always sequentially increasing (for example [5,6,7,8] or [111,112,113,114])

- The location of the sequences in memory appears random

- Usually only 4 or 8 bytes out of the entire 262,144 bytes originally written are corrupted like this. But it is very repeatable in that it happens very often.

 

I initialize the flash with 6 wait states:

ul_rc = flash_init(FLASH_ACCESS_MODE_128,FLASH_NUM_OF_WAIT_STATES);

I then unlock the flash:

flash_unlock(UNLOCK_ADDRESS_1,UNLOCK_ADDRESS_2,&actualUnlock1,&actualUnlock2);

where UNLOCK_ADDRESS_1= 0x0041fe00 and UNLOCK_ADDRESS_2 = 0x0051ffff and the actual regions unlocked are: actualUnlock1= 0x0041c000 and actualUnlock2 = 0x0051ffff. (They are different but sufficiently large.)

 

To write the flash, I use:

ul_rc = flash_write(flashAddress, &dataBuffer, numBytesToWrite, false);

where flashAddress = 0x00420000 [in this example, sector 01 of the flash], &dataBuffer = 0x20400d00 [the SRAM buffer with the pattern], and numBytesToWrite = 0x00040000 [262144 bytes]. Even when I see the corruption, ul_rc always returns as FLASH_RC_OK.

 

I've finally attached a photo highlighting one of the 4 byte sequences of corruption amongst the correct 1-255 pattern, as seen in the memory view of the debugger. Any thoughts?

 

Attachment(s): 

This topic has a solution.
Last Edited: Thu. Mar 22, 2018 - 03:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just observed a similar symptom. This was fixed for me by inserting a __DSB() into the generated _efc_write_page() function between writing the buffer and triggering the ESF write. See https://community.atmel.com/forum/bug-efcwritepage-writes-garbage-end-each-flash-page-written for details.

 

Below is patched function. Note: If you are then executing the code just written to flash you will also want to wait for the last write to complete and issue an __ISB() before branching to the newly flashed code address.

RAMFUNC
static void _efc_write_page(void *const hw, const bool ewp, const uint32_t page, const uint8_t buffer[IFLASH_PAGE_SIZE])
{
        uint32_t i;

        while (!hri_efc_get_EEFC_FSR_FRDY_bit(hw)) {
                /* Wait for EFC ready to start a new command */
        }

        /**
        * Data to be programmed in the Flash must be written in an internal latch
        * buffer before writing the programming command in EEFC_FCR.
        * Byte and half-word AHB accesses to the latch buffer are not allowed.
        * Only 32-bit word accesses are supported.
        */
        for (i = 0; i < IFLASH_PAGE_SIZE; i += 4) {
                *((uint32_t *)(IFLASH_ADDR + (page * EFC_PAGE_SIZE) + i)) = *((uint32_t *)(buffer + i));
        }

        __DSB(); /* <<<<< Barrier was missing HERE <<<<<<< */
 
        /* Erase and write page */
        hri_efc_write_EEFC_FCR_reg(
            hw, ((ewp) ? EEFC_FCR_FCMD_EWP : EEFC_FCR_FCMD_WP) | EEFC_FCR_FARG(page) | EEFC_FCR_FKEY_PASSWD);
}

 

 

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

I observed occasionally corrupted data after flash write on E70 too. Also blank check failure after a flash erase.

Unfortunately I cannot find the source code of the _efc_write_page() function shown above.

I'm on ASF 3.35.1 and use flash_write() function located in \ASF\sam\services\flash_efc\flash_efc.c

SAME newbie

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good news. I solved my flash corruption issue by simply upgrading Atmel Studio to 7.0.1645 *and* updating my code to use ASF 3.35.1. I'm no longer seeing flash corruption.

 

I still see merit in JohnBC's comment about inserting __DSB();. It appears that he is using Atmel Start instead of ASF (?). The corresponding location in the ASF function flash_write() to potentially insert __DSB(); might be where I've put it below, but I am not familiar with these low level commands. Perhaps JohnBC would have further input?

/* Write page.
   * Writing 8-bit and 16-bit data is not allowed and may lead to
   * unpredictable data corruption.
   */
  p_aligned_dest = (uint32_t *) ul_page_addr;
  for (ul_idx = 0; ul_idx < (IFLASH_PAGE_SIZE / sizeof(uint32_t));
    ++ul_idx) {
   *p_aligned_dest++ = gs_ul_page_buffer[ul_idx];
  }
  
  __DSB(); // INSERT HERE???
  
  if (ul_erase_flag) {
   ul_error = efc_perform_command(p_efc, EFC_FCMD_EWP,
     us_page);
  } else {
   ul_error = efc_perform_command(p_efc, EFC_FCMD_WP,
     us_page);
  }
  if (ul_error) {
   return ul_error;
  }

 

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

@ucbuyer77

 

Yes: I am using Atmel START/ASF4.

 

Yes: Your DSB is in an equivalent location (but I am not in position to test ASF3.5 stuff at the moment).

 

DSB makes sure that all data that the CPU "thinks" it has already written has actually been flushed from the data pipeline into memory before the EFC hardware starts to read from it. This is a common pattern in hardware drivers with CPUs that have data pipelines.

 

Peeps should also be aware of a more subtle pipeline problem if they are loading code into flash that they then intend to execute: Under some circumstances the CPU code prefetch logic could fetch invalid instructions from the "yet to be jumped to" flash address before it has been updated. The fix for this is to wait for the flash write to complete and then issue ISB before any possible branch to it. ISB invalidates the code prefetch pipeline and forces the CPU to reload instructions from flash. I would personally include this overhead at the tail of the above function as insurance and sleep well, than try and reason whether its highly unlikely or not depending on my call path and details of the prefetch pipeline implementation....

 

Last Edited: Thu. Mar 22, 2018 - 04:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@regjoe

 

You probably already saw this, but if not then try patching __DSB() into the location shown by ucbuyer77 and see if that fixes the write for you. (I am on ASF4 at the moment so the libs are quite different).

 

I don't know about erase though ...If you can tell me the name of function you use for that in ASF3, or post the code, I will have a quick look and see if there is anything obvious.

Last Edited: Thu. Mar 22, 2018 - 04:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ucbuyer77 wrote:
I solved my flash corruption issue by simply upgrading Atmel Studio to 7.0.1645 *and* updating my code to use ASF 3.35.1. I'm no longer seeing flash corruption.

 

Hmm. Which older ASF version caused flash corruption on your side?   I do not see any change in the flash source code in the last ASF versions.

SAME newbie

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

regjoe wrote:

Hmm. Which older ASF version caused flash corruption on your side?   I do not see any change in the flash source code in the last ASF versions.

 

If this latch/pre-buffer memory is in fixed location (I assume it is but have not checked), then they could have fixed it by using an MPU region to flag it as non-cacheable.

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

I was on 3.32.0 ASF. I suspect an updated version of the gcc compiler is being used on Atmel Studio 7.0.1645 versus 7.0.1188 or 7.0.1006.

 

I had created the Atmel flash example program in Atmel Studio 7.0.1645 for the E70 development board (on ASF 3.35.1) and compiled then run it successfully without errors. I then copied that exact project to a different machine running an older version of Atmel Studio 7 (7.0.1188 I think, but maybe 7.0.1006), and compiled and ran the exact same project on the same dev board, but I immediately began seeing errors again.

 

Simply updating to the latest version of Atmel Studio (1645) on the second machine fixed this example project. For my personal code though, I had to also update the ASF in my project to 3.35.1, because it was still giving errors on 3.32.0, even on the latest version of Atmel Studio...