Skip to main content
Visitor II
October 16, 2009
Question

STR912FA Sleep Mode - Hangs!

  • October 16, 2009
  • 11 replies
  • 2221 views
Posted on October 16, 2009 at 21:35

STR912FA Sleep Mode - Hangs!

    This topic has been closed for replies.

    11 replies

    aledAuthor
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    Using Segger JTrace and IAR 4.41A. Clock source = 16Mhz (PLL), 8Mhz external osc.

    I'm having problems with the STR912FA CPU occasionally hanging when in sleep mode.

    I'm using a WIU line to wake the processor from sleep and configure its WIU->MR (mask) accordingly. When the cpu is in sleep mode then on a rising edge of the WIU the cpu will wakeup fine, however as the WIU line is volatile (as in most real time systems) if the WIU is triggered before the cpu enters sleep mode (i.e. WIU->PR and WIU->MR are set) then the CPU will still enter sleep mode but never respond to a subsequent wakeup signal.

    I have tried all the st examples, with the same problem. I have also tried clearing the pending bit with interrupt, but the CPU can still go to sleep before the interrupt is serviced and therefore still does not work.

    At the moment the best that I can do is to clear all pending registers before and after setting the sleep mode flag (after because CPU takes 12 clock cycles to switch everything off.) :

    WIU->PR = 0xFFFFFFFF; // Clear pending WIU interrupts

    SCU->PWRMNG |=0x2; // Enter sleep mode

    WIU->PR = 0xFFFFFFFF; // Clear again (incase of still running)

    asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop'');

    asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop'');

    asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop'');

    asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop''); asm(''nop'');

    But obviously this is still not a real solution. Has anyone else faced this problem? Can anyone suggest a solution? Please help.

    aledAuthor
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    Nobody fancies answering/investigating this one further?

    I'll just leave a warning to everone using un-deterministic wakeups on the STR912FA in sleep mode then - Don't use it! :p

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    Dear Aleh,

    Are you using a real 8Mhz Oscillator or it is a Quartz ?

    if it is a Quartz, the right sequence to enter Sleep mode is to switch the CPU clock to the RTC Clock , ensure that all Pending bits on the wake-up unit are cleared and then after system wake-up switch back to Your oscillator clock. It seems that you are facing The behavior described in the STR91x errata on Web. Let me know if the problem is still there ? ;)

    Regards,

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    HI,

    Im having the same problems you are having for 3 week now i have been trying every thing.

    TRC clk disaling WIU interrupts.

    it happent when i recive commands using 3 UARTs.

    i have a few timers running RTC Interrupt Enabled.

    ADC ON , after each command i reciver threw one of the UARTS I go to sleep.

    and every now and then cant wake up.

    Aparently there is a true problem and not an implimentation issue.

    if you have found a way to work this CPU hanging in sleep mode some how.

    Please let me know if you found a solution?

    please see below my implementation

    void Enter_Sleep_Mode()

    {

    U_INT CLKCNTR_Value_local;

    int delay_factor = g_Curr_CPU_Clk_Val>>2;//~2ms

    VIC_ITCmd(UART1_ITLine, DISABLE);

    #ifdef SLEEP_MODE

    //preparing data to write to the scu clk after cpu wakes up.

    //this is done prior to entering sleep mode to save time when

    // working at 32k After Waking UP.

    CLKCNTR_Value_local = SCU->CLKCNTR;

    Enable_WakeUp();// WIU->CTRL |= 0x02;

    SCU_MCLKSourceConfig(SCU_MCLK_RTC); /* Added by ST*/

    WIU->PR = 0XFFFFFFFF; //Clear all flags

    SCU->PWRMNG |=0x2;

    asm(

    ''NOP\n''

    ''NOP\n''

    ''NOP\n''

    );

    *(U_LONG *)(SCU_BASE) = CLKCNTR_Value_local;//return to

    // OSC SCU>CLKCNTR = CLKCNTR_Value;

    #endif

    while (delay_factor >0){delay_factor--;} // delay ~2 m

    WIU_Check_Flags();

    Disable_WakeUp();////WIU->CTRL &=0xFFFD;

    VIC_ITCmd(UART1_ITLine, ENABLE);

    return;

    }

    thanks mate,

    aledAuthor
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    baradkon,

    I have found if only one WIU is triggered before the sleep mode (in this small time frame) then all susequent WIU lines are ignored for wakeup as well. I believe this is due to all WIU lines being or-ed and wakeup only occurs on the rising edge of the result's latched transition. :-[

    aledAuthor
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    I'm using a real 8Mhz Oscillator. I've also tried manually switching to the RTC clock before entering sleep but the problem is still there.

    The real issue I think is trying to ensure that all Pending bits on the WIU are cleared before entering sleep. If any are set before the sleep mode starts then it is impossible to wakeup. Manually setting a pending bit before sleep is a good test to prove this.

    I can't figure out a way to ensure the clear of the WIU pending bits before sleep occurs. As the WIU bits can still trigger during the ''nop'' phase.

    BaradKon>>

    At the moment the best I can do is not to use the SCU->PWRMNG |=0x02; command and merely use the RTC as the clock source as my lowest power saving technique. I still use the WIU bits to switch back to the PLL, but manually poll them by running with the RTC:

    // Wait for WIU activity

    while ((PendingRegister & MaskRegister) == 0)

    {

    // Update the wakeup sources

    PendingRegister = WIU->PR;

    MaskRegister = WIU->MR;

    }

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    aleh,

    thanks for the idea.

    this will be my last resort because executing these few lines

    takes a very long time because of the TRC clock.

    But i am still not sure that this is the problem.

    I have used 3 different Wake ups pins.

    and even if one of them causes the handing others that have not ocured in the small time frame you are talking about should have Woken up the CPU because there WIU did not yet occure.

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    Dear aleh, baradkon,

    It seems that, you are experimenting the behavior described in STR91xF Erratasheet v5 - May 2007 : Page 14& 15 : Section Sleep and Idle Mode Timing Requierements - Then (2) - Time Required for Sleep Mode Entry :

    ''The Tsleep time required to enter Sleep mode depends on the frequency of the oscillator, the CPU clock and the slowest peripheral clock. If a wake-up event occurs within this Tsleep time, it will be ignored and the STR91x will not exit from Sleep mode.

    The Tsleep time can be expressed in term of the T period of these clocks:

    Tsleep = 17*(T_OSC) + 14*(T_Slowest_IP_CLK) + 6*(T_CPUCLK)

    Example to calculate Tsleep (CPU is running on RTC clock before entering Sleep mode, fCPUCLK = 32 kHz)

    T_OSC=40ns (fOSC=25 MHz)

    T_CPUCLK = T_RTC = 31,250ns (fCPUCLK=32 kHz)

    T_slowest_IP_CLK = 2*31,250ns

    Assume all clock dividers are at the default state of 1 except APB clock divided by 2.

    The slowest peripheral clock is then = fCPUCLK/2

    Tsleep = 17*40ns + 14*(2*31,250ns) + 6*31,250ns ~ 1.06 ms

    Workarounds for Rev B and Rev D

    Take account of the maximum time required to enter Sleep mode (Tsleep) in your specific application.

    This limitation will not be fixed in future silicon revisions''. :o

    Looking at AN2523 ''Migrating from STR91xF to STR91xFA'' rev2 - May 2007 Page 11/23

    ''Functional Fix: Entering Idle and Sleep Mode

    Description: After the Sleep mode or Idle mode bit is set in the SCU_PWRMNG register, the Power Management Unit requires a period of time to switch off all the CPU and peripheral clocks safely before entering low power mode. Any wake up event occurring within this period of time is ignored. In STR91xFA device, this problem is fixed in Idle mode.

    The Sleep mode will still require a period of time to enter the mode.This time period is depending on the frequency of the CPU clock and the slowest Peripheral clock. Please refer to the reference manual for the Sleep Mode timing calculation.

    Impact: A wake up event that is activated during the Sleep Mode entry time will be ignored by the CPU.

    So, It looks for me as you have to ensure in the application design that during this Sleep timing there are no wake-up event coming to the WIU unit. Am I right ? I hope that this may help you.

    Regards, STOne-32

    [ This message was edited by: STOne-32 on 26-10-2007 21:33 ]

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    Hi STOne-32 & aleh.

    Aleh:

    Thanks for the info,

    STOne-32:

    1. i Need comfirmation or tranzlation for the AN you pointed to:

    ''A wake up event that is activated during the Sleep Mode entry time

    will be ignored by the CPU.''

    does it mean that wakeup will be ignored during SLEEP entry as well

    as after CPU has moved to sleep mode.

    meaning CPU Hangs?

    2. comenting on your sagenstion:

    ''It looks for me as you have to ensure in the application design that

    during this Sleep timing there are no wake-up event coming to the WIU

    unit. Am I right ? I hope that this may help you.''

    I use one of the UARTS rx line for WIU.

    My product is a slave and I can't block the Master from sending me

    any data when ever it needs to.

    does this mean i can't use the sleep mode becuase there is a chance

    CPU will hang?

    3. the time that CPU is expoised to the failure is ~1ms.

    because in the STRF errata sheet ST says it is madatory to move to

    32k to prevent CPU handing becuase of different reasons.

    in fact it expoised the user to a different issue with is the 1ms

    time frame of a posible jamming.

    any other sagenstions by ST to work aroung this problem?

    B.R

    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 09:47

    I face the same problem

    in Rev H.

    code like this: (used in uCOS2)

    RTC_SetAlarm(alarm); /*set alarm*/

    RTC_AlarmCmd(ENABLE); /* enable alarm */

    /*The system clock source switched to the RTC clock */

    OS_ENTER_CRITICAL(); // this disables interrupts globally before enter sleep mode

    RTC_ITConfig(RTC_IT_Per | RTC_IT_Tamper, DISABLE);

    RTC_ClearFlag(RTC_FLAG_Alarm | RTC_FLAG_Per | RTC_FLAG_Tamper); /* clear RTC flag*/

    RTC_ITConfig(RTC_IT_Alarm, ENABLE); /*Enable RTC alarm interrupt*/

    VIC_ITCmd(WIU_ITLine, DISABLE);

    y = SCU_GetMCLKFreqValue() / 1000;

    SCU_MCLKSourceConfig(SCU_MCLK_RTC);

    SetLED(1); // show the system status, just GPIO operations

    WIU->PR = 0xFFFFFFFF; // Clear pending WIU interrupts

    /*Enter Sleep mode*/

    SCU_EnterSleepMode();

    WIU->PR = 0xFFFFFFFF;

    /* Dummy instructions

    Execution of N=12 dummy instructions. This number depends on

    the ratio between CPU clock frequency and the oscillator input

    frequency(Please refer to the STR91xFA reference manual).

    For fcpuclk = 32.768Khz, N=3 */

    __nop(); __nop(); __nop();

    /*Switch to oscillator as clock source after wake up*/

    if (y > 25)

    { // MCLK by PLL

    while(!(SCU->SYSSTATUS&SCU_FLAG_LOCK)); /*Wait PLL to lock*/

    SCU_MCLKSourceConfig(SCU_MCLK_PLL); // restore clock, if it woke up...

    } else SCU_MCLKSourceConfig(SCU_MCLK_OSC);

    SetLED(0);

    // clear RTC alarm and enable WIU interrupt

    RTC_ITConfig(RTC_IT_Alarm, DISABLE);

    RTC_AlarmCmd(DISABLE);

    RTC_ITConfig(RTC_IT_Per, ENABLE);

    VIC_ITCmd(WIU_ITLine, ENABLE);

    OS_EXIT_CRITICAL(); // enabled interrupts globally

    XXX codes: following some codes here will sometimes not run?

    the problem is: CPU cannot wakup up or after OS_EXIT_CRITICAL, the system hang.

    PS:OS_EXIT_CRITICAL set CPSRE reg to enable int.:

    OS_CPU_SR_Save

    MRS R0, CPSR

    ORR R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts.

    MSR CPSR_c, R1

    BX LR ; Disabled, return the original CPSR contents in R0.

    OS_CPU_SR_Restore

    MSR CPSR_c, R0

    BX LR

    any suggest? or what code can be used as common purpose?

    :(