David Schroeder

FLASH_LDD issue with safe write and FTFE

Discussion created by David Schroeder on Sep 13, 2013
Latest reply on Sep 16, 2013 by Vojtech Filip

I have a project that was running on a K20DX256 that stores some parameters in flash using the IntFLASH and FLASH_LDD components. The project is transitioning to a K20FX512 in order have more ram available when. When I did this I started to receive hard faults when writing to flash. The hard faults would always occur at the the same address, but I was able to complete several other flash writes successfully before getting the fault. To further complicated the issue, once I'd received the hard fault during the write subsequent reads of the same memory would also generate a hard fault.

 

Digging into it it looks like there is a bug in the IntFlashLdd2_CommandCompleteInterrupt function generated by FLASH_LDD. This code has logic to allow writes of less than the 8 bytes by reading the values that are currently in flash and merging it with the data to be written. However, if the data being written lines up such that it's only in part of the top 4 bytes then the data that is read back is not properly merged resulting in the hard fault. The code snipet below shows the fix that worked for me.

 

...

      FlashPrgUnitAddr = DeviceDataPrv->CurrentFlashAddress - DstAddrOffset;

      CurrentFlashPrgUnitData[0] = ((uint32_t *)FlashPrgUnitAddr)[0];

      CurrentFlashPrgUnitData[1] = ((uint32_t *)FlashPrgUnitAddr)[1];

      if(((DataToPrg[0] & DataToPrgMask[0]) & (~CurrentFlashPrgUnitData[0])) > 0U) {

        DeviceDataPrv->CurrentErrorFlags |= LDD_FLASH_MULTIPLE_WRITE_ERROR;

        return;

      }

      if(((DataToPrg[1] & DataToPrgMask[1]) & (~CurrentFlashPrgUnitData[1])) > 0U) {

        DeviceDataPrv->CurrentErrorFlags |= LDD_FLASH_MULTIPLE_WRITE_ERROR;

        return;

      }

      DataToPrg[0] = DataToPrg[0] ^ (~CurrentFlashPrgUnitData[0]);

      DataToPrg[1] = DataToPrg[1] ^ (~CurrentFlashPrgUnitData[1]);                           <<---- This line was missing!

      DeviceDataPrv->CurrentDataSize = PrgBytesCount;

      DeviceDataPrv->DataCounter -= PrgBytesCount;

      FTFE_PDD_WriteFCCOBFirstLongWordData(FTFE_BASE_PTR, DataToPrg[0]);

      FTFE_PDD_WriteFCCOBSecondLongWordData(FTFE_BASE_PTR, DataToPrg[1]);

...

Outcomes