1 2 Previous Next 21 Replies Latest reply on Sep 24, 2017 3:00 PM by AndyMarder

    Problems with WDT in low power mode

    AndyMarder

      I have a project for a  CYBLE-022001-00 on a custom  board.(attached)

      It has  WDT and a button interrrupt

      Both work fine when low power mode is disabled

      When it is enabled ( function EnterLowPowerMode is called in main.c) the counters main_loop_count   and _isr_count  never increment.

      The EnterLowPowerMode function was copied from e.pratt's post for the similar issue so I have no doubts that it works

      Any ideas ?

      Thanks

      Andy

        • 1. Re: Problems with WDT in low power mode
          e.pratt_1639216

          I believe your button ISR might be declared incorrectly for the format (c++ syntax is fine, just the cypress syntax )

          Use:

           

          CY_ISR(Btn_Isr) {

          //Code for ISR here

              _check_btn_state = TRUE;

              Button_Isw_ClearInterrupt();

          }

           

          Potentially, the compiler is behaving differently if it is not declared as a Cypress Interrupt? I know there is the interrupt handler hardware, but I don't remember what needs to be done to configure that if any.

          The component declarations in the TopDesign look okay to me.

          • 2. Re: Problems with WDT in low power mode
            AndyMarder

            Both WDT and Button interrupts fire just fine when low power mode code  is disabled

            WDT ISR is declared using Cypress syntax and the button is not

            Both do not fire when power mode is enabled.I'll try changing the button declaration and will let you know if that helped.

            I suspect something else is going on here.

            Thank you

            Andy

            • 3. Re: Problems with WDT in low power mode
              AndyMarder

              Using the Cypres syntax in the button ISR did not help

              3 things I'm noticing:

              1. No matter how long I let the program run it stops at the same place when I pause it.(image below)

              2. The device is visible in CySmart and the RSSI values change which indicates that at least the BLE stack is running

              However none of my breakpoints are reached and the main loop and the  WDT ISR counters do not increment

              3. The WDT ISR did fire 4 times and then stopped. Sometimes it does not fire at all, sometimes fires 2-3 times. It should fire every 800 ms

              and I don't see that. The issue is strangely reminiscent of the problem I had with ISR from an external part. There too the ISR was firing sporadically. I abandoned that method in favor of a WDT which worked great until I enabled low power mode.

              Don't know if these issues are related,just pointing it out.

              debug-pause.png

              • 4. Re: Problems with WDT in low power mode
                e.pratt_1639216

                1. The stop location likes like it is something to do with the RTC; Do you have the RTC running and working properly without low power mode? Is it always running? Or just mostly?

                2. Are you able to connect  to the BLE with CySmart? Can you read/write/notify values etc.?

                3. Odd that it fires some number of times then fails...If the RTC systick needs to fire each 100 ms to work properly, but then the unit goes to sleep and doesn't fire the RTC systick in time... That could be causing issues, like a runaway program or messing up timers/WDT.

                • 5. Re: Problems with WDT in low power mode
                  AndyMarder

                  I do have the RTC in  the component declaration  but it is not running in this project

                  Yes I can connect to the device with  CySmart and broadcasing works because the RSSI changes

                  What do you make of the fact that the stack trace is always the same and the first function is __sy_stack_limit?

                  It appears that the app crashed but BLE is running

                  The code does not really do much so I'm beginning to wonder if this is related to my hardware

                  Andy

                  • 6. Re: Problems with WDT in low power mode
                    AndyMarder

                    Digging deeper.

                    I commented out CyBle_Start and CyBle_ProcessEvents

                    So all the code is doing in the main loop is incrementing the counter, resetting the WDT and entering the low power mode.

                     

                    Found the IntDefaultHandler code that appears in the stack trace. It is in Cm0Start.a and there is a comment

                    We must not get here. If we do, a serious problem occurs, so go into an infinite loop.

                     

                    The culprit seems to be the function CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO) that gets called from EnablePowerMode()

                    The comment in this  function describes the clkSelect parameter as follows

                     

                    CY_SYS_CLK_HFCLK_IMO     IMO.

                    CY_SYS_CLK_HFCLK_EXTCLK  External clock pin.

                    CY_SYS_CLK_HFCLK_ECO     External crystal oscillator. Applicable for

                                              PSoC 4100 BLE / PSoC 4200 BLE / PSoC 4200L.

                    CY_SYS_CLK_HFCLK_PLL0    PLL#0. Applicable for PSoC 4200L.

                    CY_SYS_CLK_HFCLK_PLL1    PLL#1. Applicable for PSoC 4200L.

                     

                    So it appears that in my case CY_SYS_CLK_HFCLK_ECO  clkSelect parameter causes the code to get into an infinite loop and end up in the IntDefaultHandler

                    Any ideas what clock select should I use  and possible cause?

                    Thanks

                    Andy

                    • 7. Re: Problems with WDT in low power mode
                      e.pratt_1639216

                      Depending on how much power you are trying to save, you will want to turn off as many clocks as you can that you don't need running while in sleep mode. I believe in my project I used ECO, as that was required for bluetooth; Thus I set the HFCLK to use it as well, and turned off the IMO to save power. The clock you select has to be running for it to not crash; Otherwise, it comes down to clock speed, and usage of the clock. My guess would be that unless you really need that little bit of extra power saving, it might be easier to just comment out the clock setting functions and let the unit leave IMO clock running.

                      • 8. Re: Problems with WDT in low power mode
                        e.pratt_1639216

                        PLL0, PLL1, EXTCLK are used for specific cases, and the ECO only runs if you have the ECO for the BLE running I think, otherwise just leave it on the IMO left running would be my advice. Glad you figured out it was the clock setting function

                         

                        Epratt

                        • 9. Re: Problems with WDT in low power mode
                          AndyMarder

                          Did I understand you correctly, if the clock is not running, trying to write to it it causes a crash? This is what it looks like to me  but I wanted to confirm. That brings a question how do I find out what clocks do I have running? I need all power savings I can get

                          I commented out the CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO)   and tried to execute the following

                                    CySysClkImoStop();

                                     CySysPmSleep();

                                    SysClkImoStart();

                          But debugger lost connection after  CySysClkImoStop() call

                          The only way it works on my system is when I have both SYsClokcIMOStop and  CySysClkWriteHfclkDirect calls commented out.

                          • 10. Re: Problems with WDT in low power mode
                            AndyMarder

                            Digging even deeper

                             

                            The LPM code is as follows:

                            CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP)

                                   intrStatus = CyEnterCriticalSection();

                                    blessState = CyBle_GetBleSsState();

                                    if((blessState == CYBLE_BLESS_STATE_ECO_ON ||

                                    blessState == CYBLE_BLESS_STATE_DEEPSLEEP))

                                    {

                                        CySysPmDeepSleep();

                                    }

                                    else if(blessState != CYBLE_BLESS_STATE_EVENT_CLOSE)

                                    {

                                        //CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO);

                                       // CySysClkImoStop();

                                        CySysPmSleep();

                                       // CySysClkImoStart();

                                       // CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO);

                                    }

                                    CyExitCriticalSection(intrStatus);

                                      CyBle_ExitLPM()

                             

                            -. When all calls that manupulate clocks arre commendted out  and only CySysPmSleep is called the WDT counter increments  all the time  but the main loop counter does not.. When I pause execution the stack trace is always the same, so it appears that the code is stuck in Cyble_ExitLPM() which calls CySysPmSleep. The stack trace in this case is always like this:

                             

                            0 CySysPmSleep() Generated_Source\PSoC4\cyPm.c 44 0x00002C02 (All)

                             

                            1 ll_wait_to_exit_dsm() ?????? ?????? 0x0000661C (All)

                            2 ll_exit_low_power_mode() ?????? ?????? 0x00005DB4 (All)

                            3 CyBleController_ExitLowPowerMode() ?????? ?????? 0x0000588E (All)

                            4 CyBle_ExitLPM() ?????? ?????? 0x000039A2 (All)

                            5 EnterLowPowerMode() main.c 94 0x000002DC (All)

                            6 main() main.c 117 0x00000314 (All)

                             

                            -  When I  remove the CyBle_ExitLPM the main loop counter the program gets stuck in CyBle_ProcessEvents.

                            The stack trace always looks like this on execution pause

                             

                            0 CySysPmSleep() Generated_Source\PSoC4\cyPm.c 44 0x00002BFE (All)

                             

                            1 ll_wait_to_exit_dsm() ?????? ?????? 0x00006614 (All)

                            2 ll_exit_low_power_mode() ?????? ?????? 0x00005DAC (All)

                            3 ll_task_handler() ?????? ?????? 0x0000AD54 (All)

                            4 llft_service_queue() ?????? ?????? 0x0000B8A6 (All)

                            5 llf_task_start_routine() ?????? ?????? 0x0000B7FE (All)

                            6 CyBle_StackTaskHandler() ?????? ?????? 0x000043C8 (All)

                            7 OS_scheduler() ?????? ?????? 0x0000538E (All)

                            8 CyBleStackMgr_ProcessBleEvents() ?????? ?????? 0x00003E5A (All)

                            9 CyBle_ProcessEvents() ?????? ?????? 0x000039A2 (All)

                            10 main() main.c 108 0x000002F4 (All)

                             

                            -. With both CyBle_EnterPLM and  CyBle_ExitLPM commented out the blessState is always CYBLE_BLESS_STATE_EVENT_CLOSE and neither CySysPmSleep or  CySysPmDeepSleep are called.

                            Any ideas what's  going on and how to fix this?

                            Thanks

                            Andy

                            • 11. Re: Problems with WDT in low power mode
                              AndyMarder

                              OK, some progress (I guess)

                              This works on my board  (meaning that both the main loop counter and the ISR counter increment)

                               

                                     CyBle_EnterLPM(CYBLE_BLESS_SLEEP); <---  instead of CYBLE_BLESS_DEEPSLEEP 

                                      intrStatus = CyEnterCriticalSection();

                                      blessState = CyBle_GetBleSsState();

                                      if((blessState == CYBLE_BLESS_STATE_ECO_ON || blessState == CYBLE_BLESS_STATE_DEEPSLEEP))

                                      {

                                          CySysPmDeepSleep(); <--- never executes

                                      }

                                      else if(blessState != CYBLE_BLESS_STATE_EVENT_CLOSE)

                                      {        

                                          CySysPmSleep();   

                                      }

                                      CyExitCriticalSection(intrStatus);

                                  }

                                  CyBle_ExitLPM();

                              So I cannot stop  any clocks it seems. Would appreciate some insights and ideas.. As I mentioned I need all the power savings I can get.

                              Another weirdness

                              -No matter what sleep interval  I set in the  WDT it always fires about every second

                              My expectation was that  with the sleep interval set to 5 seconds the ISR counter would  be 4 after 20 seconds of exectuion. But it was about 20+  which indicates that the WDT fires about every second.

                              I wonder why.

                              The watchdog timer code is from another sample and it uses the  ILO_FREQ define set to 32000 in the call that sets the timer interval:

                              CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, ((uint32)(sleep_interval * ILO_FREQ) / 1000));

                              Perhaps this ILO frequency is not correct for my part. Where do I look to find the correct one for my part?

                              Thanks

                              Andy

                              • 12. Re: Problems with WDT in low power mode
                                e.pratt_1639216

                                After catching up on reading your three comments :

                                           //CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO);

                                The above function will change the high frequency clock to the clock passed as the parameter: In this case, I was setting chip CPU clock from the IMO to the ECO to save power; I leave the ECO running for BLE and watchdog timer usage, but turn off the IMO to save power.

                                           // CySysClkImoStop();

                                The above function will stop the IMO clock. Note, if you don't change the CPU clock (HFCLK) to a clock that is going to be running, then turning off the clock that the CPU is running off of will essentially halt the CPU.

                                 

                                 

                                Thankfully, you were able to determine this with trial and error already

                                 

                                Looking at your code to set the WDT, it looks like you might be misunderstanding what the CySysWdtWriteMatch() is doing?

                                The WDT0 has a maximum value of 65536 (uint16). If the clock you are using for WDT0 runs at say 32 kHz, then setting a match value of 32000 will cause an interrupt every second. Then, adjusting your sleep time to different intervals, using only WDT0 you will be able to get an interval from 31.2 us to 2 seconds. So, trying to input a value of 5 seconds is rolling over for the uint32 to 1 second, which explains why you are getting an interrupt every one second.

                                 

                                In order to get a longer WDT sleep time, you will need to use the WDTs cascaded together; Chapter 12 of the TRM http://www.cypress.com/documentation/technical-reference-manuals/psoc-4000-family-psoc-4-architecture-technical-referenc…  will show you how to cascade the two watch dog timers together. This will allow a longer period than the 2 seconds of the WDT0.

                                 

                                (If you still can't get the timers working correctly, setting up a RAM variable to hold the timer counts to multiply the number of "sleep" cycles before turning back on will also work. E.G. Every time we wake up increment sleepCount until sleepCount = 20, then we know we have been asleep for 1*20 seconds or 20 seconds total.)

                                 

                                As far as why you can't turn off the clocks, try configuring the clocks with only the ones you want turned on in deep sleep mode; If the IDE lets you do it, then it is definitely possible with code. However, if you are unable to do it with the IDE, then you still might be able to configure the clocks with code; At least one clock needs to be on and set to run the HFCLK, and one clock needs to be on and running the LFCLK for the BLE chip. For me, I was able to get the ECO and WCO working for this.

                                • 13. Re: Problems with WDT in low power mode
                                  AndyMarder

                                  Thank you so much for clarifying the CySysWdtWriteMatch for me - that was very helpful

                                  As for the clocks-

                                  Looking at the clocks page I see that there are high and low  frequency clocks configured. SInce I didn't change anything on that page I assume these are the defaults.

                                  Could you take a look ( you have the project ) and suggest how the configuration can be changed?

                                  Thanks

                                  Andy

                                  • 14. Re: Problems with WDT in low power mode
                                    e.pratt_1639216

                                    Well, since you are using the BLE, I would set the WCO clock on and use that for any LFCLK operations.

                                    And then use the ECO for any HFCLK operations.

                                    Here's what they would look like:

                                    LFCLK.PNGHFCLK.PNG

                                    Then, you shouldn't need to modify the clocks I think

                                    1 2 Previous Next