Flash erase/write fails after deep sleep wakeup

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

Flash erase/write fails after deep sleep wakeup

1,361 Views
renjithks
Contributor I

For my Kinetis K21 project, after deepsleep wakeup(lls)( Before going to sleep erase/write flash is working without any problem ), any try to erase/write flash sector from software is giving hard fault. Even if we do software reset, still problem persists. While issuing the command for sector erase the controller is giving hard fault. But after a power on reset it is possible to erase/write the flash.  Please help me to narrow down the issue and solve it.

Tags (1)
0 Kudos
8 Replies

862 Views
renjithks
Contributor I

I could get the reason for failure, but couldn't fix the issue still. SCB_SFSR shows its an "instruction bus error" and SCB_BFAR shows the bus fault address as 0xe000edf8( debug core register DCRDR ). RDCOLERR is set in  FSTAT register at the hard fault.

I am clearing FSTAT_CCIF to initiate the operation in RAM( SpSub ), and also wait there for completion before returning.

I tried to disable cache also, but even that didn't help.

FMC_PFB0CR &= 0xFFFFFFE0;

FMC_PFB1CR &= 0xFFFFFFE0;

0 Kudos

862 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi RENJITH KS,

    How did you test it?

    If the K21 in the LLS mode, the Debugger will be disconnected.

    Now I use your flash erase code in our KSDK1.3.0, and test it on my TWR-K21F120M board, after I wakeup from the LLS mode, then do the flash sector erase, and printf the according address data, I find the flash is erased correctly.

    Attached code is my test code, I just modify the KSDK1.3.0 k21 code:C:\Freescale\KSDK_1.3.0\examples\twrk21f120m\demo_apps\power_manager_hal_demo

    Please check the ksdk1.3.0 code on your side at first!

If you still have question with my code, please let me know~


Have a great day,
Jingjing

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

862 Views
renjithks
Contributor I

/** Macro to enable all interrupts. */

#define EnableInterrupts asm ("CPSIE  i")

/** Macro to disable all interrupts. */

#define DisableInterrupts asm ("CPSID  i")

/**

* @brief erase a sector of the flash

*/

int flash_sectorErase( unsigned int* FlashPointer )

{

    int Return = E_FLASH_SUCCESS;

    uint32_t FlashPtr = (uint32_t)FlashPointer;

   

    /* checking access error */

    if ( FTFE_FSTAT & ( FTFE_FSTAT_ACCERR_MASK |

                       FTFE_FSTAT_FPVIOL_MASK  |

                       FTFE_FSTAT_RDCOLERR_MASK ) )

    {

        /* clear error flag */

        FTFE_FSTAT |= ( FTFE_FSTAT_ACCERR_MASK |

                        FTFE_FSTAT_FPVIOL_MASK |

                        FTFE_FSTAT_RDCOLERR_MASK );

    }

   

    FTFE_FCNFG &= ~(FTFE_FCNFG_RDCOLLIE_MASK);

    DisableInterrupts;

   

    /* Allocate space on stack to run flash command out of SRAM */

    /* wait till CCIF is set*/

    while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK));

    /* Write command to FCCOB registers */

    FTFE_FCCOB0 = FlashCmd_SectorErase;

    FTFE_FCCOB1 = (uint8_t)(FlashPtr >> 16);

    FTFE_FCCOB2 = (uint8_t)((FlashPtr >> 8) & 0xFF);

    FTFE_FCCOB3 = (uint8_t)(FlashPtr & 0xFF);

    // Execute the Flash write

    SpSub(); 

   /* checking access error */

    if (FTFE_FSTAT & FTFE_FSTAT_ACCERR_MASK)

    {

        /* clear error flag */

        FTFE_FSTAT |= FTFE_FSTAT_ACCERR_MASK;

        /* update return value*/

        Return |= E_FLASH_FACCERR;

    }

    /* checking protection error */

    else if (FTFE_FSTAT & FTFE_FSTAT_FPVIOL_MASK)

    {

        /* clear error flag */

        FTFE_FSTAT |= FTFE_FSTAT_FPVIOL_MASK;

        /* update return value*/

        Return |= E_FLASH_FPVIOL;

    }

    else if (FTFE_FSTAT & FTFE_FSTAT_RDCOLERR_MASK)

    {

        /* clear error flag */

        FTFE_FSTAT |= FTFE_FSTAT_RDCOLERR_MASK;

        /* update return value*/

        Return |= E_FLASH_RDCOLERR;

    }

    /* checking MGSTAT0 non-correctable error */

    else if (FTFE_FSTAT & FTFE_FSTAT_MGSTAT0_MASK)

    {

        Return |= E_FLASH_MGSTAT0;

    }

       

    EnableInterrupts;

    FTFE_FCNFG |= FTFE_FCNFG_RDCOLLIE_MASK;

    /* function return */

    return  Return;

}

/**

* @brief         Execute the Flash write while running out of SRAM

*/

__attribute__ ((section(".mydata"))) void SpSub(void)

{

    /* Launch command */

    FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;   

    /* wait for command completion */

    while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK));

}

/* Leave this immediately after SpSub */

void SpSubEnd(void) {}

0 Kudos

862 Views
bobpaddock
Senior Contributor III

I don't know that this is related to your problem or not however not having the Interrupt Enable and Disable instructions marked as Volatile can result in hair pulling debugging sessions with some compilers as optimizer reorder code (Code Motion).

What I use for GCC:

#define ATTR_NO_INSTRUMENT_FUNCTION __attribute__( ( no_instrument_function ) )
/*

* This is the only method available in the ARMv6-M architecture

* (Cortex-M0/M0+)

*

* In normal applications there is no need to add any barrier

* instruction after using a CPS instruction to enable an interrupt.

*

* If an interrupt was already in the pending state, the processor

* accepts the interrupt after the “CPSIE I” is executed. However,

* additional instructions can be executed before the processor enters

* the exception handler:

*

*  For Cortex-M3 or Cortex-M4, the processor can execute up to TWO

*  additional instructions before entering the interrupt service

*  routine.

*

*  For Cortex-M0, the processor can execute up to ONE additional

*  instruction before entering the interrupt service routine.

*

*/

static inline ATTR_NO_INSTRUMENT_FUNCTION void irq_enable( void )

{

  __asm__ __volatile__ ("cpsie i"); /* Clear PRIMASK */

}

/*

* The CPSID instruction is self-synchronized to the instruction

* stream and there is no requirement to insert memory barrier

* instructions after CPSID.

*/

static inline ATTR_NO_INSTRUMENT_FUNCTION void irq_disable( void )

{

  __asm__ __volatile__ ("cpsid i");

}

0 Kudos

862 Views
renjithks
Contributor I

Problem Description: Facing problem in Write/Erase Flash, after wake-up from sleep.

Environment : Kinetis K21(K21FN1M0M12)

Tool: CodeWarrior for MCU - Version 10.5

Detailed Description:

For the Kinetis K21 project, we are facing issues with in-software flash write.

Flash operations (Read, Write and Erase) are working fine always when you boot the device.

Only after deep-sleep(using enter_lls API) wakeup, in few devices the flash erase/write is failing, and we have noticed FTFE Read Collision Error Flag RDCOLERR of FTFE_FSTAT register is getting set while initiating the flash erase command.

In debug mode if we execute the same code for flash operations step by step, the issue is not reproducible.

Even with a software reset flash is not accessible for erase/write. Only after a power on reset it is possible to erase/write the flash. 

0 Kudos

862 Views
renjithks
Contributor I

Interrupts are disabled in my code before doing the flash operation. Before going to sleep all the flash operations are working fine with the same code. Only after sleep wake-up it's giving the issue, and will start working if we do a power-on reset.

0 Kudos

862 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi RENJITH K S,

   Please attach your test project, and tell me the full name of your chip, I need to check it on my side.

Waiting for your reply!

Jingjing

0 Kudos

862 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi RENJITH K S,

      When you wakeup from the LLS mode, did you disable the global interrupt before doing the flash erase/write operation?

    Normally, the hardfault is caused by the interrupt when doing the flash operation.

    So, please check your flash operation code at first, you disable the global interrupt before flash operation, after the flash operation is finished, then enable the global interrupt again!

Wish it helps you!


Have a great day,
Jingjing

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos