This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

FMSTAT = INVDAT | CSTAT on successive writes to bank 7 FEE on RM48x



I am looking for additional information on the INVDAT error status reported from FEE programming commands.

When I run the code below it will work once on clean EEPROM (0xFF'd). However, reset and run again and it will fail the program with INVDAT error registered in FMSTAT. Similar results if I change the values of some data values, reload and run - I get FMSTAT = INVDAT

Can someone help me understand what is meant by the INVDAT error and why I am getting inconsistent results when writing to memory that already has some data values that match.

My ultimate goal is to use the FEE driver to save fault registers from my application across powercycles and some simple configuration data.

Thanks in advance

Jamie

<code>

/** @file sys_main.c
*   @brief Application main file
*   @date 29.May.2013
*   @version 03.05.02
*
*   This file contains an empty main function,
*   which can be used for the application.
*/

/* (c) Texas Instruments 2009-2013, All rights reserved. */

/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "sys_common.h"
#include "system.h"

/* USER CODE BEGIN (1) */
#include "f021.h"
#include "het.h"

/* Local function prototypes */
static void use_Fapi(void);
static void use_Registers(void);
/* USER CODE END */

/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/

/* USER CODE BEGIN (2) */
/* USER CODE END */

void main(void)
{
/* USER CODE BEGIN (3) */

    hetInit();
    use_Fapi();
    //use_Registers();
    while(1);
/* USER CODE END */
}

/* USER CODE BEGIN (4) */
static void use_Fapi(void)
{
    /*FEE ROUTINE */

    Fapi_StatusType oReturnCheck = Fapi_Status_Success;
    uint32 u32StartAddress = 0xF0200020U;
    uint8 au8MainDataBuffer[16] = {0x21, 0x21, 0x21, 0x21, 0x0A, 0xB9, 0x11, 0x70, 0x5F, 0xC1, 0x9C, 0xFD, 0x54, 0x51, 0xED, 0x86};


    REGISTER(0xfff87288) = 0x00000005; /* enable writes to EWAIT register */
    REGISTER(0xfff872B8) = 0x00040002; /* EWAIT=4 */
    REGISTER(0xfff87288) = 0x00000002; /* disable writes to EWAIT register */

    oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS,200);

    if((oReturnCheck == Fapi_Status_Success) && (Fapi_checkFsmForReady() != Fapi_Status_FsmBusy))
    {
        oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank7);

        oReturnCheck = Fapi_enableEepromBankSectors(0x000F,0x0);
        if(oReturnCheck == Fapi_Status_Success)
        {
            oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32StartAddress,au8MainDataBuffer,16,0,0,Fapi_AutoEccGeneration);
        }
        else
        {
            gioSetBit(hetPORT1,31,1);
        }

        /* Wait for FSM to finish */
        while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
        uint32 fsmstatus = Fapi_getFsmStatus();
        /* Check the FSM Status to see if there were no errors */
        if (Fapi_getFsmStatus() != 0)
        {
            gioSetBit(hetPORT1,31,1);
        }
    }
    else
    {
        gioSetBit(hetPORT1,31,1);
    }
}/* end useFapi */

static void use_Registers(void)
/*
 * Using the SPNA148 application report. Section 3.2.2 on the understandign that the
 * RM48x has ECC protected Bank 7. See FADDR guidance of section 2.1 for instruction to use the ECC method
 * for addressing 0xF02x_xxx of bank 7.
 */
{

    Fapi_StatusType oReturnCheck = Fapi_Status_Success;

    FwpWriteByteAccessorType * oFwpWriteByteAccessor = FWPWRITE_BYTE_ACCESSOR_ADDRESS;
    FwpWriteByteAccessorType * oFwpEccByteAccessor = FWPWRITE_ECC_BYTE_ACCESSOR_ADDRESS;
    FwpWriteDWordAccessorType * oFwpWriteDWordAccessor = FWPWRITE_DWORD_ACCESSOR_ADDRESS;

    uint8 au8MainDataBuffer[16] =     {0xAA, 0xBB, 0xAC, 0xAD,
                                     0xAE, 0xAF, 0x12, 0x34,
                                     0x57, 0xBA, 0xBB, 0xBC,
                                     0xBD, 0xBE, 0xBF, 0x21};

    uint32 u32Index = 0;


    oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS,180);  /* Example code is assuming operating frequency of 180 MHz */
    if((oReturnCheck == Fapi_Status_Success) &&
       (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
    {


        oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank7);
        Fapi_enableEepromBankSectors(0x000F,0x0);

        FLASH_CONTROL_REGISTER->Fbse.u32Register = 0x000F;         /* enable sector 0, 1, 2, 3, 4 */
        FLASH_CONTROL_REGISTER->Fbprot.u32Register = 0U;         /* enable level 1 protection */
        FLASH_CONTROL_REGISTER->FsmWrEna.u32Register = 0x5U;    /* unlock FSM registers for writing */
        FLASH_CONTROL_REGISTER->FsmCommand.FSM_COMMAND_BITS.FSMCMD = Fapi_ClearStatus; /* Clear the status register */
        FLASH_CONTROL_REGISTER->FsmExecute.FSM_EXECUTE_BITS.FSMEXECUTE = 0x15U;    /* execute the clear */
        FLASH_CONTROL_REGISTER->Faddr.u32Register = 0xF0200000U;

        for(u32Index=0;u32Index<16;u32Index++)
        {
            oFwpWriteByteAccessor[u32Index] = au8MainDataBuffer[u32Index];
        }
        FLASH_CONTROL_REGISTER->FemuAddr.u32Register = 0xF0200000;
        /* Little Endian so lower first then upper */
        FLASH_CONTROL_REGISTER->FemuDlsw.u32Register = oFwpWriteDWordAccessor[1];
        FLASH_CONTROL_REGISTER->FemuDmsw.u32Register = oFwpWriteDWordAccessor[0];
        oFwpEccByteAccessor[EI8(0)] = FLASH_CONTROL_REGISTER->FemuEcc.FEMU_ECC_BITS.EMU_ECC;

        FLASH_CONTROL_REGISTER->FemuAddr.u32Register = 0xF0200008;
        /* Little Endian so lower first then upper */
        FLASH_CONTROL_REGISTER->FemuDlsw.u32Register = oFwpWriteDWordAccessor[2];
        FLASH_CONTROL_REGISTER->FemuDmsw.u32Register = oFwpWriteDWordAccessor[3];
        oFwpEccByteAccessor[EI8(0)] = FLASH_CONTROL_REGISTER->FemuEcc.FEMU_ECC_BITS.EMU_ECC;

        FLASH_CONTROL_REGISTER->FsmCommand.FSM_COMMAND_BITS.FSMCMD = Fapi_ProgramData;
        FLASH_CONTROL_REGISTER->FsmExecute.FSM_EXECUTE_BITS.FSMEXECUTE = 0x15U;

        FLASH_CONTROL_REGISTER->FsmWrEna.u32Register = 0x2U;

        while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);

        if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
        {
             gioSetBit(hetPORT1,31,1);
        }
    }

}/* end useRegisters */


  • Hi Jamie,

    You are getting INVDAT because you are expected to erase the sectors before programming any data. Please refer to the recommended programming flow in the Flash API reference guide(SPNU501D):

     "5.3   Recommended Program Flow:
    The following diagram describes the flow for programming a device. This flow assumes the user has
    already erased all affected sectors or banks following the Recommended Erase Flow...."

    Please try erasing the sector each time before you program and let us know.

    Regards,

    Praveen

  • Hi Praveen,

    OK, I can try to do that but can you answer the following

    1. why I sometimes do not get the INVDAT error status?

    2. why the programming API function does not include an erase prior to writing?

    3. does an erase command reduce the life of the FEE?

    4. does this mean that I have to erase a whole sector even if I am only writing one byte of data? this seems very inefficient.

    thanks

    Jamie

  • Hi Jamie,

    You will not get INVDAT error if you are programming a 1 to a 0. Can you check if that is the case, when you are not seeing the INVDAT error?

    The programming API doesnot include erase because, erase is required only if the flash is already programmed. If the flash is already in erased state, erase is not required prior to programming.

    There is a limit to the number of write/erase cycles for a device.  Please refer to the TRM for the number of the cycles the device supports.

    Yes, you have to erase the sector, if the byte you are going to write is already programmed(to 0)

    Regards,
    Praveen

  • Hi Praveen,

    I cannot recall the values I was using but I am sure the byte was not 0, it is likely that a bit was 0 though. Perhaps that was the problem. From memory I believe I was changing the values in the byte array from say 0x21 to 0x29 and getting INVDAT errors. I don't get any such errors if I do a sector erase beforehand. Of course I don't want to be doing full sector erases if only a couple of bytes need changed.

    From the other points you make, I assume it would be sensible for me to verify the values before attempting the write with new values. This is standard practice as I recall from serial EEPROM drivers to ensure you don't unneccessarily use up a write/erase cycle.

    Jamie