I have an application that writes a new image to flash "swap1" flash bank and most of the time it works, but every now and then a write will fail with a IO_ERROR_WRITE error. This happens even if I use the same image and try it multiple times. Most of the time everything works fine, but every now and then a write fails.
I am using the K64FN part and MQX 4.1.
I made sure the writes are 8 bytes at a time, phrase aligned, and are sequential, so I'm not writing to the same phrase, and the phrase is erased before writing to it.
I did some testing and set a breakpoint when the write fails (see below) and here is what I found:
The address the write fails on is random.
The address IS on a phrase boundary, and 8 bytes are to be written.
The phrase appears to have been written to flash because I can look at memory when it fails and the written phrase is there.
If I look at the FTFE registers the FSTAT is 0x80 (no errors) and the FCCOB registers contain the proper information for the write. The command is 0x07 (program phrase).
The file pointer has ERROR set to 0xA03 (IO_ERROR_WRITE).
The file pointer LOCATION is set to the address I wanted to write to.
I tried reading the first byte I was about to write to, to verify it was 0xFF before the write and it was. After the write that fails the byte was not 0xFF but what I was writing (verified by looking into memory). It appears the write actually happened, but the _io_write function returns IO_ERROR anyway for some reason.
Here are parts of my code:
opens the bank and erases:
flash_file = _io_fopen("flashx:swap1", NULL);
if (NULL == flash_file)
retval = Erase_Flash(flash_file, 0, MAX_FLASH); <----- erases all but the last sector
if (ERASE_SUCCESS == retval)
if (IO_ERROR == _io_fseek(flash_file, (_file_offset)0, IO_SEEK_SET))
retval = ERASE_SEEK;
The write portion:
static uint32_t Flash_Write_and_Verify(uint32_t address, uint8_t *buffer, uint32_t num_bytes)
uint32_t retval = UPDATE_OK;
if (IO_ERROR == _io_write(flash_file, buffer, (int32_t)num_bytes)) <------ sometimes fails here
retval = UPDATE_ERROR_WRITE; <----- breakpoint is set here
if (IO_ERROR == Verify_Written(address, buffer, num_bytes)) <---- directly reads bytes, compares to buffer
retval = UPDATE_ERROR_WRITE;
I have tried _task_stop_preemption() before the io_write and _task_start_preemption() after in case another task was interfering with the write. It didn't make a difference. The FTFE code appears to disable / enable interrupts so I didn't try that.