S32K118 RTD EEP issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

S32K118 RTD EEP issue

2,568 Views
hns80
Contributor V

Posting here since support.nxp.com is not working.

Using S32DS, version 3.4 update 3 and S32K1_RTD_1_0_0_D2108_ASR_REL_4_4_REV_0000_20210810.

The S32K118 is configured with the partition set to 0x09 (24k allocated to E-Flash).
The code uses normal writes rather than quick writes. The code verifies CCIF is set before going to sleep (LVPS).
Before going to sleep, writes to the EEP occur without any problem.
After wake-up from LVPS, the system performs a soft reset by writing MCORE_SCS_AIRCR = 0x05FA0004.

After reset, it enters the bootloader and checks the EEPROM partition. If it is incorrect, it will rewrite the settings. The code waits for EERDY to be set, then checks FCCOB5.
Sometimes it is 0x77, 0xAD, 0x00, or 0x04. The code then jumps to the main application.

Sometimes after this wake-up/reset sequence, the code will hang when writing to the EEP.
It gets stuck in the while loop inside Ftfc_Eep_Ip_WaitCcifTimeout(). It will eventually timeout.
When this occurs, FCCOB5 value is 0xFF, FCCOB0 =0xFF, FCCOB1=0x04 or 0x08 or 0x01.

1. Why is the EEP write timing out?
2. If FCCOB5 is 0x04 (incomplete write) after reset, does this mean the last data was not written or that the last write is corrupt?

 

0 Kudos
9 Replies

2,529 Views
Archana_F
Contributor I

Hello Daniel,

After reset or wakeup from deep sleep (soft reset MCORE_SCS_AIRCR = 0x05FA0004) we are calling FlexNVM parttion command to check partition and also calling Ftfc_Eep_Ip_Init api which is in Ftfc_Eep_Ip.c file.

This api take care of brownout code with quick write and EEERDY bit.

Regarding LVD handler if you have any code then please share.

We are checking CCIF bit `before each read write operation for each byte.

return code is 0x03 when CCIF not set (any pending opertion is there). Also before entering into deep sleep we check CCIF bit set and then enter sleep.

 

/*==================================================================================================
Function : NVM_Hal_Write_Eep
Description : Write one or more complete eeprom pages to the eeprom device
Parameter : start_add, *data_buf, size
Return value : return write_status;
FTFC_EEP_IP_STATUS_OK = 0x00 < success >
FTFC_EEP_IP_STATUS_FAILED = 0x01 < failure >

0x03 <CCIF==0>
Remarks : none
==================================================================================================*/
uint8 NVM_Hal_Write_Eep(uint32 start_add, uint8 *data_buf, uint16 size)
{
uint16 crc=0xFFFF;
uint8 write_status = 0x01,read_status = 0x01, read_buf[size], crc_buf[2]={0};
/* calculate crc */
crc=I2C_HAL_Calculate_CRC16_ccitt(data_buf, (size));
/* At the end of data buffer add 2 bytes of calculated CRC */
crc_buf[0] = (uint8)((crc >> & 0xFF);
crc_buf[1] = (uint8)crc;
if(0U != (IP_FTFC->FSTAT & 0x80))
{
/* Write one or more complete eeprom pages to the eeprom device */
for(i=0; (i<(size)) && ( 0U != (IP_FTFC->FSTAT & 0x80)); i++)
{
retJobResultType = Ftfc_Eep_Ip_Write(start_add + i, data_buf + i, FTFC_EEP_IP_PAGE_BYTE, FALSE);
}
if(FTFC_EEP_IP_STATUS_OK == retJobResultType)
{
for(i=0; (i< 2U) && ( 0U != (IP_FTFC->FSTAT & 0x80)); i++)
{
Ftfc_Eep_Ip_Write(start_add + size + i, crc_buf + i, FTFC_EEP_IP_PAGE_BYTE, FALSE);
}
}
if(FTFC_EEP_IP_STATUS_OK == retJobResultType)
{
read_status = NVM_Hal_Read_Eep(start_add, read_buf, size);
if( FTFC_EEP_IP_STATUS_OK == read_status )
{
write_status = FTFC_EEP_IP_STATUS_OK;
}
}
}
else{
write_status = 0x03;
}
return (write_status);

}
/*==================================================================================================
Function : NVM_Hal_Read_Eep
Description : Reads from eeprom memory
Parameter : start_add, *read_buf, size
Return value : return read_status
FTFC_EEP_IP_STATUS_OK = 0x00 < success >
FTFC_EEP_IP_STATUS_FAILED = 0x01 < failure >

0x03<CCIF==0>
Remarks : none
==================================================================================================*/
uint8 NVM_Hal_Read_Eep(uint32 start_add, uint8 *read_buf, uint16 size)
{
uint16 crc=0xFFFF;
uint8 crc_msb = 0, crc_lsb=0, read_status = 0x01;
uint8 myRead_buf[size];
if(0U != (IP_FTFC->FSTAT & 0x80))
{
/* Reads from eeprom memory */
for(i=0; (i<(size + 2U)) && ( 0U != (IP_FTFC->FSTAT & 0x80)); i++)
{
retJobResultType = Ftfc_Eep_Ip_Read(start_add + i, myRead_buf + i, FTFC_EEP_IP_PAGE_BYTE);
}
/* Calculate CRC if read success */
if(FTFC_EEP_IP_STATUS_OK == retJobResultType)
{
crc=I2C_HAL_Calculate_CRC16_ccitt(myRead_buf, size);
crc_msb=(uint8)(crc >> 8 & 0xFF); /* upper 8 bits of crc */
crc_lsb=(uint8)crc; /* lower 8 bit of crc */
if((myRead_buf[size]!=0xFF) && (myRead_buf[size+1]!=0xFF))
{
/* compare lower 8 bit and upper 8 bit of calculated crc with buf's last 2 bytes */
if((myRead_buf[size] != crc_msb) && (myRead_buf[size + 1] != crc_lsb))
{
for(i=0; i < size; i++)
{
myRead_buf[i] = 0xFF;
}
read_status = FTFC_EEP_IP_STATUS_FAILED; /* return status as fail if read CRC not match with calculated CRC */
}
else
{
read_status = FTFC_EEP_IP_STATUS_OK;
}
}
else
{
read_status = FTFC_EEP_IP_STATUS_OK; /* 1st power on data will be all FF, read status =success */
}
}
else
{
read_status = FTFC_EEP_IP_STATUS_FAILED;
}
for(i=0; i < size; i++)
{
read_buf[i] = myRead_buf[i];
}
}
else{
read_status = 0x03;
}
return read_status;
}

 

/*************************************************************************************************************************************************************/

Ftfc_Eep_Ip_StatusType Ftfc_Eep_Ip_Init (Ftfc_Eep_Ip_ConfigType const * pConfig)
{
Ftfc_Eep_Ip_StatusType Status = FTFC_EEP_IP_STATUS_OK;
uint8 BrownoutCode = 0U;

FTFC_DEV_ASSERT(NULL_PTR != pConfig);

/* Overwrite all global variables */
Ftfc_Eep_Ip_pxConfiguration = pConfig;
Ftfc_Eep_Ip_eBrownOutCode = FTFC_EEP_IP_NO_BO_DETECTED;
Ftfc_Eep_Ip_xAsyncJob.TicksStarted = 0U;
Ftfc_Eep_Ip_xAsyncJob.TicksElapsed = 0U;
Ftfc_Eep_Ip_xAsyncJob.Result = FTFC_EEP_IP_STATUS_OK;

if (0U == (IP_EEPROM->FCNFG & FCNFG_EEERDY_MASK))
{
/* When the memory partitioning is done without the option to load the EEPROM data
* to FLEXRAM at reset, a FLEXRAM_FCC_MODE_EEERAM_NORMAL command is needed (so EEERDy gets set).
* Also, the FLEXRAM_FCC_GET_FLEXRAM_STATUS cmd is not allowed unless the EEERDY bit is set. */
Status = Ftfc_Eep_Ip_CmdSetFlexramFunction(FLEXRAM_FCC_MODE_EEERAM_NORMAL, 0U);
}

if (FTFC_EEP_IP_STATUS_OK == Status)
{
Status = Ftfc_Eep_Ip_CmdSetFlexramFunction(FLEXRAM_FCC_GET_FLEXRAM_STATUS, 0U);
if (FTFC_EEP_IP_STATUS_OK == Status)
{
BrownoutCode = IP_EEPROM->FCCOB[FTFC_EEP_IP_FCCOB_SETRAM_READ_BROWNOUT_CODE];
switch (BrownoutCode)
{
case FTFC_EEP_IP_BO_DURING_MAINTENANCE_U8:
Ftfc_Eep_Ip_eBrownOutCode = FTFC_EEP_IP_BO_DURING_MAINTENANCE;
break;

case FTFC_EEP_IP_BO_DURING_QUICK_WRITES_U8:
Ftfc_Eep_Ip_eBrownOutCode = FTFC_EEP_IP_BO_DURING_QUICK_WRITES;
break;

case FTFC_EEP_IP_BO_DURING_NORMAL_WRITES_U8:
Ftfc_Eep_Ip_eBrownOutCode = FTFC_EEP_IP_BO_DURING_NORMAL_WRITES;
break;

case FTFC_EEP_IP_NO_BO_DETECTED_U8:
Ftfc_Eep_Ip_eBrownOutCode = FTFC_EEP_IP_NO_BO_DETECTED;
break;

default:
Status = FTFC_EEP_IP_STATUS_FAILED;
break;
}

if (FTFC_EEP_IP_NO_BO_DETECTED != Ftfc_Eep_Ip_eBrownOutCode)
{
Status = Ftfc_Eep_Ip_CmdSetFlexramFunction(FLEXRAM_FCC_COMPLETE_MAINTENANCE, 0U);
}
}
}

return Status;
}

0 Kudos

2,524 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello @Archana_F,

Maybe I'm missing something from the description, but what is the BO code that the API returns?

How long is the timeout?

Did you measure the execution time of the SetFlexRAM command?

This is the specification:

danielmartynek_0-1672742462665.png

danielmartynek_1-1672742489721.png

 

BR, Daniel

0 Kudos

2,510 Views
Archana_F
Contributor I

The S32K118 is configured with the partition set to 0x09 (24k allocated to E-Flash and 8K D-flash).

The code uses normal writes rather than quick writes.

The code verifies CCIF is set before going to sleep (LVPS).

  • Previously no, but now added that logic before going into sleep it checks no any pending NVM operation and after reset it not shows 0x04 or 0xFF. After wakeup after sometime it stucks in while and it shows 0xFF.

Upon waking from LVPS, the system performs a soft reset by writing MCORE_SCS_AIRCR = 0x05FA0004.

  • After reset checked EEERDY bit and it set’s and after that FCCOB5 is sometimes 0x77, 0xAD, 0x00. And when it stucks in timeout loop then FCCOB5=0xFF.
  • After reset it shows value different each time 0x00, 0xA6, 0x77 and after wakeup after some time it stuck in while Ftfc_Eep_Ip_WaitCcifTimeout() then it FCCOB5 value is 0xFF, FCCOB0 =0xFF, FCCOB1=0x04 or 0x08 or 0x01.
  • The value of FCCOB5 is varying each time it shows different values and when it stucks in while it is constantly 0xFF.

This is when it stuck in while for timeout if CCIF not set and it retry write of that byte till CCIF set.

/************************************* PROBLEM1_FINISH ***********************************************/

 

/********************************* SECOND_SCENARIO_START *******************************************/

PROBLEM1 NOT OBSERVED IN THIS SCENARIO

Now we have added the protection for read/write and erase and for sleep. So now it not stuck in while so please review the code and suggest your feedback.

After power on reset or after wakeup from sleep, the bootloader check the partition which is in bootmanager file NVM_Hal_Eep_DepartParitition(T_EEEPROM_SIZE); with partition code 0x09. So this api is from NXP SDK only and it chekcs the partition. After this command we check EEERDY bit and call ftfc_Eep_Ip_init.

 

NVM_Hal_Eep_DepartParitition(T_EEEPROM_SIZE);

  while(0U == (IP_EEPROM->FCNFG & FCNFG_EEERDY_MASK));

  init_status=Ftfc_Eep_Ip_Init(&EepFtfcCfg_VS_0);

 

Also we call Ftfc_Eep_Ip_Init in application code also.

 

Till now we not get invalid partition code each time it shows device partitioned with correct partition code 0x9.

If in case in future if it show invalid partition then we can’t mass erase and repartition again.

 

Also please check the attached file of NVM read, write, erase and sleep in attached file whether it’s correct or not.

Before each write or read or erase we check CCIF == 1 or not. If it’s set then only we do operation of read/write/erase. By this we not observed the stuck issue in while for timeout. But we have issue of touch freeze so that issue is due to NVM or other module not sure till.

So for safer side are adding the protection for NVM so that in future it will not stuck in while for timeout if CCIF not set.

I added the protection for each byte read/write/erase as well.

Also we are adding the protection for deep sleep as well, it will first check CCIF bit set or not if set then will go into sleep else it will wait till CCIF set.

/* Check NVM not busy in other operations */ 

         if(0U != (IP_FTFC->FSTAT & 0x80))

         {

             Power_Down_Sequence();

         }

Please check thse attached both files and suggest which one is better.

0 Kudos

2,492 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Archana_F,

 

It is rather difficult to navigate in both the description and the code.

 

Both the APIs Ftfc_Eep_Ip_Read and Ftfc_Eep_Ip_Write check that CCIF flag.

danielmartynek_0-1672922203996.png

And return Ftfc_Eep_Ip_StatusType Status = FTFC_EEP_IP_STATUS_FAILED; if it is not set.

 

Whereas you check the flag before you call the APIs in these for loops:

for(i=0; (i<(size)) && (0U != (IP_FTFC->FSTAT & 0x80)); i++)

Which is not correct in my opinion.

Then, you don't read the status of this function:

danielmartynek_1-1672922395451.png

So, you keep writting and reading it based on a wrong status, I think.

 

I would keep the condition before Power_Down_Sequence().

 

I don't see the point in reading the FCCOBn registers unless it is after the Query command.

And in this case, the API returns the correct status.

Does it return a BO error?

 

Regards,

Daniel

 

 

 

0 Kudos

2,485 Views
Archana_F
Contributor I

Hi Daniel,

 

Can you please make required changes as per your suggestion in my code file which was attached in previous discussion and share me back, please.

 

Thanks.

 

Regards,

  Archana

0 Kudos

2,484 Views
Archana_F
Contributor I

Hello Daniel,

Previously we were doing like this but by this it was stuck  in Ftfc_Eep_Ip_WaitCcifTimeout function inside while loop in Ftfc_Eep_Ip.c file.

uint8 NVM_Hal_Write_Eep(uint32 start_add, uint8 *data_buf, uint16 size)
{
    uint16 crc=0xFFFF;
    uint8 write_status = 0x01,read_status = 0x01, read_buf[size], crc_buf[2]={0};
    /* calculate crc */
     crc=I2C_HAL_Calculate_CRC16_ccitt(data_buf, (size));
     /* At the end of data buffer add 2 bytes of calculated CRC */
     crc_buf[0] = (uint8)((crc >> 8) & 0xFF);
     crc_buf[1] = (uint8)crc;
      /* Write one or more complete eeprom pages to the eeprom device */
        for(i=0; i<(size); i++)
        {
            retJobResultType = Ftfc_Eep_Ip_Write(start_add + i, data_buf + i, FTFC_EEP_IP_PAGE_BYTE, FALSE);
        }
        for(i=0; i< 2U; i++)
        {
        Ftfc_Eep_Ip_Write(start_add + size + i, crc_buf + i, FTFC_EEP_IP_PAGE_BYTE, FALSE);
        }
         if(FTFC_EEP_IP_STATUS_OK == retJobResultType)
        {
             read_status = NVM_Hal_Read_Eep(start_add, read_buf, size);
           if( FTFC_EEP_IP_STATUS_OK == read_status )
            {
             write_status = FTFC_EEP_IP_STATUS_OK;
            }
        }
        return (write_status);
}
/*==================================================================================================
   Function         : NVM_Hal_Read_Eep
   Description      : Reads from eeprom memory
   Parameter        : start_add, *read_buf, size
   Return value     : return read_status
   FTFC_EEP_IP_STATUS_OK = 0x00                       < success >
   FTFC_EEP_IP_STATUS_FAILED = 0x01                   < failure >
   Remarks          : none
==================================================================================================*/
uint8 NVM_Hal_Read_Eep(uint32 start_add,  uint8 *read_buf, uint16 size)
{
    uint16 crc=0xFFFF;
    uint8 crc_msb = 0, crc_lsb=0, read_status = 0x01;
    uint8 myRead_buf[size];
    /* Reads from eeprom memory */
        for(i=0; i<(size + 2U); i++)
        {
            retJobResultType = Ftfc_Eep_Ip_Read(start_add + i, myRead_buf + i, FTFC_EEP_IP_PAGE_BYTE);
        }
        /* Calculate CRC if read success */
        if(FTFC_EEP_IP_STATUS_OK == retJobResultType)
        {
        crc=I2C_HAL_Calculate_CRC16_ccitt(myRead_buf, size);
        crc_msb=(uint8)(crc >> 8 & 0xFF); /* upper 8 bits of crc */
        crc_lsb=(uint8)crc; /* lower 8 bit of crc */
       if((myRead_buf[size]!=0xFF) && (myRead_buf[size+1]!=0xFF))
       {
       /* compare lower 8 bit and upper 8 bit of calculated crc with buf's last 2 bytes */
          if((myRead_buf[size] != crc_msb) && (myRead_buf[size + 1] != crc_lsb))
          {
            for(i=0; i < size; i++)
           {
             myRead_buf[i] = 0xFF;
           }
           read_status = FTFC_EEP_IP_STATUS_FAILED; /* return status as fail if read CRC not match with calculated CRC */
          }
          else
         {
          read_status = FTFC_EEP_IP_STATUS_OK;
         }
       }
       else
       {
           read_status = FTFC_EEP_IP_STATUS_OK;  /* 1st power on data will be all FF, read status =success */
       }
      }
       else
       {
         read_status = FTFC_EEP_IP_STATUS_FAILED;
       }
        for(i=0; i < size; i++)
        {
            read_buf[i] = myRead_buf[i];
        }
    return read_status;
}
 
So after that we added the CCIF checking for read, write and erase.
 
Regards,
  Archana 
0 Kudos

2,435 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @Archana_F,

Can you just read the status that the API returns:

danielmartynek_1-1673266670798.png

I think it requires some debugging on your side.

I would recommend stepping through the code and check the results until the WFI instruction is called.

Then, you can put an endless loop after the WFI instruction

uint32_t variable  = 1;
while(variable){} // clear variable by the debugger

So that you can attach the debugger again and check everything.

Similarly, after the soft reset, you can catch the execution in such a loop at the beginng of main() and step through the code.

 

BR, Daniel

 

 

 

 

0 Kudos

2,533 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello Jeff,

Can you initialize the EEPROM as it is shown in AN11893 Figure 12. EEE initialization flow chart including the Query command?

https://www.nxp.com/docs/en/application-note/AN11983.pdf

 

Thank you,

BR, Daniel

0 Kudos

2,481 Views
Archana_F
Contributor I

 

Hello Daniel,

 

Just provide us code which will break the while loop 

 

 

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @brief Wait for the CCIF flag to be set or exit with a given timeout.
*
* @details This function must not run from the DFLASH partition shared with EFLASH.
*
* @Param[in] TimeoutCounter given as a dummy counter that is decremented in a while loop of Ftfc_Eep_Ip_WaitCcifTimeout in Ftfc_Eep_Ip.c file.

If CCIF not set then it takes TimeoutCounter ticks and that much time it stuck in this loop. We changed the  default TimeoutCounter value from 268435456U to 2000U or 5000U but it not worked.

For normal operation write success it takes max 286 ticks but when it fails to write (CCIF not set), it takes complete 268435456U ticks and again it come again in loop as CCIF not set in previous cycle.

 

So we want such code which will break the loop and it will not impact other functionality. Right now due to this while other functionality improper working as code it stucks in while loop.


* @return the status of the flash operation
* @retval FTFC_EEP_IP_STATUS_OK the flash cmd/write has completed
* @retval FTFC_EEP_IP_STATUS_TIMEOUT a timeout has occurred
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static Ftfc_Eep_Ip_StatusType Ftfc_Eep_Ip_WaitCcifTimeout (uint32 TimeoutCounter)
{
Ftfc_Eep_Ip_StatusType Status = FTFC_EEP_IP_STATUS_OK;
uint32 counter = TimeoutCounter;

while (0U == (IP_EEPROM->FSTAT & FSTAT_CCIF_MASK))
{
--counter;
if (0U == counter)
{
Status = FTFC_EEP_IP_STATUS_TIMEOUT;
break;
}

/* feed the watchdog */
if (NULL_PTR != Ftfc_Eep_Ip_pxConfiguration->acCallBackPtr)
{
Ftfc_Eep_Ip_pxConfiguration->acCallBackPtr();
}
}

return Status;
}

 

Regards,

  Archana

0 Kudos