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.

Occasional faults after waking from deep sleep

Other Parts Discussed in Thread: TM4C1231D5PZ, TM4C1236H6PM, SEGGER

Hello,

I am using IAR 6.60.1 and a custom control with a TM4C1231D5PZ revB1 (aka rev6).

In rare cases, a precise bus fault occurs when accessing peripheral registers after coming out of deep sleep.  It occurs on the first peripheral that was not enabled during deep sleep, even with a fairly long delay beforehand (10ms).  I have only seen this happen with Medium optimization, so it seems to be a timing issue.

Please help me understand what's happening.

This problem can be recreated using the code below (and sticking it in a TivaWare example project).  Make sure to add wakeHandler to the interrupt vector and set optimization to medium.  The fault should occur within several minutes.

#include <stdbool.h>
#include <stdint.h>
#include <driverlib/gpio.h>
#include <driverlib/interrupt.h>
#include <driverlib/sysctl.h>
#include <driverlib/timer.h>
#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_nvic.h>
#include <inc/hw_sysctl.h>
#include <inc/hw_types.h>

void wakeHandler(void)
{
    TimerIntClear(WTIMER5_BASE, TIMER_TIMA_TIMEOUT);                            /*Clear the timer interrupt             */
}

void safeWFI(void)
{
    __asm(  "wfi\n"
            "mov r0,#0\n"
            "bx lr\n"           );
}

void main(void)
{
    uint32_t milliseconds = 10;                                                 /*Set sleep duration                    */

    HWREG(SYSCTL_PBORCTL) = SYSCTL_BOR_RESET;                                   /*Reset MCU during Vcc brownout events  */

    SysCtlClockSet( SYSCTL_OSC_MAIN     |                                       /*Configure system clock to 50MHz       */
                        SYSCTL_USE_PLL      |                                   /*  using 200 MHz PLL                   */
                        SYSCTL_SYSDIV_4     |                                   /*  divided by four                     */
                        SYSCTL_XTAL_16MHZ   );                                  /*  clocked from 16MHz external crystal */

    IntEnable(FAULT_USAGE);                                                     /*Enable fault interrupts for debugging */
    IntEnable(FAULT_BUS);                                                       /*  (If these are not enabled, all of   */
    IntEnable(FAULT_MPU);                                                       /*  these interrupts will will escalate */
    IntEnable(FAULT_SYSTICK);                                                   /*  to a hard fault and call the hard   */
    IntEnable(FAULT_PENDSV);                                                    /*  fault interrupt handler instead of  */
    IntEnable(FAULT_SVCALL);                                                    /*  the one assigned to it in the       */
    IntEnable(FAULT_NMI);                                                       /*  interrupt vector)                   */
    IntEnable(FAULT_DEBUG);

    //
    //Use PIOSC as a workaround for deep sleep errata
    //
    SysCtlDeepSleepClockSet(SYSCTL_DSLP_OSC_INT);                               /*Configure Deep Sleep Mode to use the  */
                                                                                /*  Precision Internal Oscillator       */

    SysCtlPeripheralClockGating(true);                                          /*Enable peripheral clock gating        */
                                                                                /*  (halts peripheral clocking in sleep */
                                                                                /*  modes)                              */

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                                /*Enable GPIO peripheral                */

    GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_0);                          /*Configure PA0 as an input             */

    for(;;)
    {
        //
        //Call a peripheral-related command to randomly cause faults (there is nothing special about this
        //  particular function call)
        GPIODirModeSet(GPIO_PORTA_BASE, GPIO_PIN_0, GPIO_DIR_MODE_IN);          /*Set pin direction                     */

        //
        //Install wakeup timer
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER5);                          /*Enable timer peripheral               */
        SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_WTIMER5);                 /*Enable timer in sleep                 */
        TimerConfigure( WTIMER5_BASE, TIMER_CFG_PERIODIC);                      /*Configure timer to auto-reload        */
        TimerLoadSet(WTIMER5_BASE, TIMER_A, 16000000 / 1000 * milliseconds);    /*Set the load time to the specified    */
                                                                                /*  number of milliseconds              */
                                                                                /*  (clocked from PIOSC in deep sleep so*/
                                                                                /*  base timing on a 16MHz clock rate)  */
        IntEnable(INT_WTIMER5A);                                                /*Enable the peripheral interrupt       */
        TimerIntEnable(WTIMER5_BASE, TIMER_TIMA_TIMEOUT);                       /*Enable the timer timeout interrupt    */
        TimerEnable(WTIMER5_BASE, TIMER_A);                                     /*Enable the timer                      */

        //
        //Put to deep sleep (using erratum workaround)
        //
        HWREG(NVIC_SYS_CTRL) |= NVIC_SYS_CTRL_SLEEPDEEP;                        /*Enable deep sleep                     */
        safeWFI();                                                              /*Put MCU in a wait-for-interrupt state */
        HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP);                     /*Disable deep sleep                    */

        //
        //(Same problem occurs with TivaWare call rather than workaround used above)
        //
//        SysCtlDeepSleep();

        //
        //Uninstall wakeup timer
        //
        TimerDisable(WTIMER5_BASE, TIMER_A);                                    /*Disable the timer                     */
        IntDisable(INT_WTIMER5A);                                               /*Disable the peripheral interrupt      */
        TimerIntDisable(WTIMER5_BASE, TIMER_TIMA_TIMEOUT);                      /*Disable the timer timeout interrupt   */

        SysCtlPeripheralDisable(SYSCTL_PERIPH_WTIMER5);                         /*Disable the timer peripheral          */

        SysCtlDelay(166666);                                                    /*Delay for about 10 milliseconds       */
    }
}

  • Ben H. said:
    In rare cases, a precise bus fault occurs when accessing peripheral registers after coming out of deep sleep.  It occurs on the first peripheral that was not enabled during deep sleep, even with a fairly long delay beforehand (10ms).  I have only seen this happen with Medium optimization, so it seems to be a timing issue.

    Please help me understand what's happening.

    This problem can be recreated using the code below (and sticking it in a TivaWare example project).  Make sure to add wakeHandler to the interrupt vector and set optimization to medium.  The fault should occur within several minutes.

    I tried to repeat this with a Tiva Launchpad, but can't get exactly the same symptoms.

    With the 10 millisecond delay couldn't get the problem (but maybe didn't wait long enough).

    When the 10 millisecond delay was commented out, got a bus fault within seconds of running. With the processor in the fault ISR the debugger showed the precise data bus fault occurred at address 0x40004400 , which is the GPIO Direction register for GPIOA.

    The System Control section of the datasheet contains the following:

    Caution – If the Cortex-M4F Debug Access Port (DAP) has been enabled, and the device wakes from a low power sleep or deep-sleep mode, the core may start executing code before all clocks to peripherals have been restored to their Run mode configuration. The DAP is usually enabled by software tools accessing the JTAG or SWD interface when debugging or flash programming. If this condition occurs, a Hard Fault is triggered when software accesses a peripheral with an invalid clock.

    A software delay loop can be used at the beginning of the interrupt routine that is used to wake up a system from a WFI (Wait For Interrupt) instruction. This stalls the execution of any code that accesses a peripheral register that might cause a fault. This loop can be removed for production software as the DAP is most likely not enabled during normal execution.

    Because the DAP is disabled by default (power on reset), the user can also power cycle the device. The DAP is not enabled unless it is enabled through the JTAG or SWD interface.


    I think this may explain the cause of the problem, although the datasheet doesn't specify how to determine the length of the delay required to avoid the problem!

  • Hi Chester,

    Thank you for the response.

    How long did you let the test run for?  The fault usually occurs within a few minutes, but sometimes can take longer (around 20 minutes).  I will try to get my hands on a Tiva Launchpad to confirm that this problem happens on that specific part as well.

    I've seen the datasheet section you posted, but am fairly confident that this is not the cause of my problem.  This fault is occurring in my full-blown application when then debugger is not attached, so the DAP should not be enabled.  I can setup a project to blink an LED on the launchpad so that the fault can be created and detected without attaching a debugger.

  • Ben H. said:
    How long did you let the test run for?  The fault usually occurs within a few minutes, but sometimes can take longer (around 20 minutes).  I will try to get my hands on a Tiva Launchpad to confirm that this problem happens on that specific part as well.

    This time I ran the test run for 1 hour, and the debugger still didn't indicate that any faults had occurred.

    However, I didn't read your initial post correctly in that I was trying (and failing) to repeat the problem with the code compiled with the TI ARM compiler whereas on re-reading your post realize you are using IAR.

    Edit: Am now downloading the size limited IAR Kickstart v6.60 for ARM to try that.

  • Chester Gillion said:
    ...I...compiled with the TI ARM compiler whereas on re-reading your post realize you are using IAR.

    Please take care to use Medium optimization as well.

    I have attempted to run this code on older sample parts (LX4F232H5QC rev A3) and could not reproduce the problem.  It is still unclear if this problem is general to the silicon revision or specific to my part.

    It looks like it may take some time before I can get a Tiva LaunchPad, so your assistance is greatly appreciated.

  • With IAR Kickstart 6.60 compiled for medium optimization on a Tiva Launchpad (TM4C1236H6PM Rev B1) haven't seen a failure in one hour. However, based upon your failure rate this is not conclusive.

  • Hi Ben,

    I'll see if I can recreate it here on my desk and update this thread with my results.

  • Update:

    I am able to create this problem with no optimization, as well.  Past attempts were a fluke--I was not patient enough to wait for it to occur.

  • Ben,

    I have not been able to reproduce this at my desk with multiple Tiva Launchpads.

    Are you seeing this on more than one device?

  • Chester Gillon said:
    With IAR Kickstart 6.60 compiled for medium optimization on a Tiva Launchpad (TM4C1236H6PM Rev B1) haven't seen a failure in one hour.

    Also ran the same program on a Stellaris Launchpad with a LX4F120H5QR rev A3, and didn't see any failure after 2 hours.

  • David Racine said:
    I have not been able to reproduce this at my desk with multiple Tiva Launchpads.

    Are you seeing this on more than one device?

    We have been able to create this problem on every rev B1 TM4C1231D5PZ (over ten) and rev A3 LM4X superset part (two) that we have tried.  I can test more, but thus far every device we've tried has eventually generated a fault.

    There are a few differences between your setups and mine:

    1. The LaunchPad and our custom control do not have the same micro.
    2. The LaunchPad and our custom controls have different circuits connected to and in close proximity to the micro.
    3. I am using a Segger J-Link to trap the faults, rather than the ICDI.  This problem was discovered in our full-blown application with no debugger attached, so I may simply need to make the example slightly more complicated to create whatever timing issue is causing problems when using the J-Link or our application.

    At this point, I will try to either get my local TI Field Applications Engineer on-site or ship him our custom control so he can create this problem.

    He is also working on finding us a Tiva LaunchPad, but it's taking too long and not looking promising.  Is there anyone at TI (or anyone else) that has a spare one they can sell us and ship immediately?