Problems with WDT in low power mode

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

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

0 Likes
1 Solution
Anonymous
Not applicable

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-architectur...  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.

View solution in original post

0 Likes
21 Replies
Anonymous
Not applicable

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.

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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.

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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

Anonymous
Not applicable

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.

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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.

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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-architectur...  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.

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

Awesome!

When I configured the clocks per your images  I can now call this sequence without crashing

  CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO);

  CySysClkImoStop();

  CySysPmSleep();

   CySysClkImoStart();

   CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO);

Since I don't have IMO configured now I think the CySysClkImoStop function will just disable the WCO clock - at least the comment in the function suggest that.

The only thing I still don't understand is whether the last call ( CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO)) has any effect since I'm not using IMO

And now that  there is some progress.. another problem..This is in the main project, not in the stripped down version that  I  gave you.

-The WDT timer does not fire. If I start the program and set the breakpoint in the WDT timer it never stops there.

Howeever if I halt the execution and then continue the breakpoint is reached. The RTC timer that fires every 100 ms still works

Intersetingly, if I call  CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP) instead of  CYBLE_BLESS_SLEEP, the WDT fires every time but the main loop is stuck..

Any ideas?

Thank you so much for your help!

0 Likes
Anonymous
Not applicable

Well, in my project I actually have both ECO and IMO enabled to start with, so that I can get the 48 MHz for the IMO clock (ECO is fixed at 24 MHz). Then, when I go to sleep I switch the HFCLK to the ECO, turn off the IMO clock, then sleep/deepsleep. Once the unit wakes up from an interrupt, I then turn on the IMO and set it back as the main HFCLK for running the CPU. (The SYSCLK is run from the HFCLK)

The ...IMOStop() function will only disable the WCO if the unit is a 4200M or one of the other devices listed (according to the comment). Thus, if you are using say a 4200S or 4200L I wouldn't think that it applies. (My unit shows it disabled for the constant declaration, so I would assume the CYBLE-022001-00 is not a 4200M). One way to check is to look at the function itself and see if:

    #if (CY_IP_IMO_TRIMMABLE_BY_WCO)

        CySysClkImoDisableWcoLock();

    #endif  /* (CY_IP_IMO_TRIMMABLE_BY_WCO) */

is enabled, and if so then it will turn off the WCO.

If you are not using the IMO clock at all, then the CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO); line won't change anything, and the line CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO); should be crashing the unit, since it is setting the SYSCLK to run off of the IMO, which is turned off.

For the WDT, you will need to make sure you do the WDT initialization (...start_ex(), and have the wdt isr function being handled and checked)

When the WDT ISR is called, make sure to handle the interrupts with clearing the interrupts for the associated watchdog timers:

WDT_ISR_StartEx(WDT_Int_Handler);//setup WDT interrupt ISR

CY_ISR(WDT_Int_Handler) {

    uint32 WDT_IF = CySysWdtGetInterruptSource();

    if(WDT_IF & CY_SYS_WDT_COUNTER0_INT) {

          //Handle WDT0 interrupt

        CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER0_INT);

    }

    if(WDT_IF & CY_SYS_WDT_COUNTER1_INT) {

          //Handle WDT1 interrupt

        CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER1_INT);

    }

    if(WDT_IF & CY_SYS_WDT_COUNTER2_INT) {

          //Handle WDT2 interrupt

        CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER2_INT);

    }

}

The difference between CYBLE_BLESS_DEEPSLEEP and CYBLE_BLESS_SLEEP is how the BLE stack behaves and how much power it uses. But I wouldn't expect it to be having a direct result/difference on the project. One thing to note, when you are setting the unit into low power modes, the debugger normally doesn't function properly (it can't talk to the CPU if the CPU is asleep...) So, I would suspect that the debugger isn't behaving correctly once you throw in the sleep modes

If you can get your project working without sleep mode (WDT interrupts, etc), and then get a project with the sleep portion working, then it just becomes a matter of combining the two. Also, having visual feedback on the power modes helps for debugging the power saving modes; E.g: One LED is whether the BLESS is in sleep/deepsleep mode, another is whether the CPU is in sleep or deep sleep mode, and another is toggled when the RTC counts, etc.

0 Likes
Anonymous
Not applicable

Thank you so much for the in-depth explanation!

Looks like in my project the #if (CY_IP_IMO_TRIMMABLE_BY_WCO) block is commented out

If you are not using the IMO clock at all, then the CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO); line won't change anything, and the line CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO); should be crashing the unit, since it is setting the SYSCLK to run off of the IMO, which is turned off.

I don' see crashing any more since I configured the clocks per images you sent, It appears that IMO is not enabled in my current configuration. However I don't see a crash calling CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO);

On WDT, I have the WDT configured and running properly without the sleep mode. I don't only rely on the debugger to verify - there is a counter that increments every time the ISR is called. I let the program run and then stop in the main loop and look at the counter. It does not increment when sleep mode is enabled and does when it is not.

I'll dig into it some more

0 Likes
Anonymous
Not applicable

You're welcome!

Odd; I would have expected changing the clock to an invalid source to mess things up...

For trying to figure out what you are missing for the WDT waking up from sleep/deep sleep: http://www.cypress.com/documentation/code-examples/ce95400-watchdog-timer-reset-and-interrupt-psoc-4...

Should have some useful information on the WDT usage. Project #2 is the one you want, as it is the wakeup that is causing problems.

I don' see crashing any more since I configured the clocks per images you sent, It appears that IMO is not enabled in my current configuration. However I don't see a crash calling CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO)

It could be that the failure for the WDT to wakeup the unit from sleep/deep sleep is the "crash" caused by setting the CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO)

I would try commenting out the lines that change the HFCLK unless you are planning on having the IMO running in your project (which it sounds like you can get away without doing so)

Also, creating a simple project that tests just the wakeup and interrupts together (WDT functionality essentially) would be helpful for debugging what is going wrong

Epratt

0 Likes
Anonymous
Not applicable

Yay, finally a breakthrough!

The reason the WDT did not fire in the main project was because the function that initialized the watchdog did not call CySysWdtLock() to prevent changes  to the WDT.

Once I added that call the WDT started to work as expected.

So now everything is working (fingers crossed)

There are some lingering questions

1. Apparently something was modifying the WDT  I wonder what it was.  I've looked at a lot of LPM samples  - some of them do call the lock function and some do not. Appears hardware secific, but probably a good practice to always call ?

2 The LPM code is as follows:;

           CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO);

            CySysClkImoStop();

            CySysPmSleep();          

            CySysClkImoStart();

            CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO);

What I don't understand is why the CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO); has no ill effect - the program runs just fine with or without that call,According to the clock configuration I do not have the IMO configured.

3  I have the RTC that runs every 100 ms . It appears that it is affected by the LPM

I ran  the following test

-Increment a counter every time the RTC handler is called.

-Run  the program for 30 seconds

-Pause the program

With LPM off the counter was around 300 which is what I expected: (30000/300 = 100 ms)

With LPM on it  was about 250.

This is understandable as the RTC handler only fires when the program is not in the sleep mode.

The question is what to do about it? Is there some API call to synchronize the RTC with the system clock? Or will I have to handle it in the code? The trick is that I don't know how long the sleep took.

Is there some sort of a System tick call that I can use before and after the sleep to determine how many ms the sleep really took?

Thank you so much again!

Your help is invaluable

Regards

Andy

-

Anonymous
Not applicable

1. Locking the WDT is similar to locking flash on other chips; So that you don't accidently modify things, and the code is more deliberate when it changes it (although this isn't fireproof either). One thing to note, is that it looks like that function also locks the ILO clock from being modified/changed...Perhaps this is the cause of your WDT failing to work/run?

2. If you are running the RTC clock, perhaps it is calling this function: CySysFlashClockConfig(void) which will change the IMO to be running?

Otherwise, I don't understand how it would be running either. I know that when I first messed with the clock settings, having IMO disabled when trying to run that caused problems... :3

3. The RTC looks like you can hardwire one of the WDTs to be used: You should read the datasheet for the RTC clock; Specifically page 4 mentions that you need to configure the clock setting under the clock selection page (where you enable/disable the ILO,IMO,WDT, etc.) There, you can set the RTC to use one of the WDT clocks. Reading through this, the RTC might actually fire when not in sleep mode? (Based on the update manually checkbox I think)

0 Likes
Anonymous
Not applicable

I simplified my code and got rid of the RTC clock. Instead I set the WDT to fire every 100 ms and increment a tick counter . That covers  my needs in terms of the clock for now and seems to be working well.

I can't think of anything else that may be enabling the IMO. so it still remains a mystery why this sequence does NOT crash

            CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO);

            CySysClkImoStop();

            CySysPmSleep();         

            CySysClkImoStart();

            CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO);

Oh well. will revisit later. moving on ..

Thank you so much for all your help

More questions  to follow