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.

Problems entering PM2 sleep mode, voltage regulator not shutting down

Other Parts Discussed in Thread: CC2541

I have been experiencing a problem in which my application will not enter power mode 2 sleep (using sleep timer or input interrupt to wake) . This application is the second I've build and is based upon and shares much code with a previous application that correctly entered PM2.

I am using a CC2541 with BLE 1.4 and IAR 8.20.1 (I have replaced PCON = halSleepPconValue with asm("MOV 0x87,halSleepPconValue") in hal_sleep.c). I am using an external 32MHz crystal and the internal 32kHz RC oscillator (when sleeping). My application periodically awakes from sleep every 2 seconds to make measurements. I can see this happening by placing a scope probe on the XOSC pins - the crystal oscillates for the few milliseconds while measurements occur, and then it stops while sleeping for the remainder of the 2 seconds. The problem seems to be that the core voltage regulator is not shutting down, as a result the power draw is about 2-3mA instead of microamps (I can see the 1.85V regulator holding constant, instead of turning off in unison with the crystal oscillations). As I mentioned previously, my other app behaves as expected, with the crystal and the regulator shutting down for the majority of the 2 second poll loop.

Using the debugger, I can see the code enter halSleep() with halPwrMgtMode getting set to 2 (PM2) and halSleepPconValue getting set to 1. Before the call to HAL_SLEEP_SET_POWER_MODE() (which calls halSetSleepMode()), the power mgmt registers are as follows:

SLEEPSTA = 0x2D, SLEEPCMD = 0x06, CLKCONSTA = 0xC9, CLKCONCMD = 0xC9, PCON = SRCRC = CLD = 0x00

I can't seem to figure out what is going wrong here, as everything seems to be correct, yet the regulator is not turned off (I guess it is entering PM1 instead of PM2). Is there so key setting I am missing that is keeping it from entering PM2? It doesn't seem like my application code should be causing this issue, and the fact that one of the two extremely similar apps sleeps correctly and the other doesn't means I must have some interrupt, pin, timer, etc configured differently between the two and that is the hangup.

Any help here would be greatly appreciated.

Thanks,

Mark

  • Hi Mark,

    I'm not sure what's going on but I'd like to share the information that you must have an external sleep XTAL in order to meet the Bluetooth low energy specification with +/-500ppm. If you are using the internal RC oscillator for sleep while maintaining a connection, you will probably experience an unwanted disconnect after not so long time.

    Best Regards

    Joakim

  • Joakim,

    Thank you for this information. In my application, this is not an issue - the device only advertises/connects on demand (button press) and stays connected very briefly and then disconnects.

    I am still stumped about what could be going with sleep not working as expected. I am hoping someone out there could tell me if there is some register setting/combination that is keeping the system from going into PM2. I guess my next step if to run the app/design that work and the other that doesn't and compare as many register settings as I can.

    Best,

    Mark

  • The problem definitely follows the firmware image. If I flash the product that doesn't correctly enter PM2 with the firmware image from the product that does (I/O mapping has slight, but harmless differences), that product does successfully enter/exit PM2 mode (I can observe the core LDO output at 1.85V while awake and measuring, and then sag while sleeping). Vice versa is also true - the firmware image from the product that doesn't enter PM2 can be loaded on the product that normally does and it then stops entering PM2 (LDO output is held steadily at 1.85V).

    The hardware and code base between the two products are very similar, so there is no obvious cause for this discrepancy. I did verify (using the debugger to examine the assembly) that both images have the MOV PCON,halSleepPconValue located at 0x7FF8 and are both 3 bytes long.

    I have compared all register values between the two firmware image (stopping the debugger while sleeping at the return from halSetSleepMode()); the Power Mgmt and Clocks registers are identical, the Sleep Timer registers are identical (except for the count value), and the Interrupt and I/O registers are very much the same - except for the differences caused by external connections. One thing that is slightly different is that the offending product has and additional I/O input interrupt on P1_0 (the both have a button interrupt on P0_7). Is there something related to interrupts or pin configuration that would cause the app to not enter PM2?

    One other curiosity is that the offending product has Chip Info register CHVER of 0x13 and correctly behaving product has CHVER of 0x12. I don't believe this is significant, since swapping code images produces an effect that follows the code image and not the hardware. But I would be interested to know what the differences between versions might be.

    Pretty stumped here, so any help would be greatly appreciated. Thanks!

  • Ok, I have isolated this down to enabling/disabling P1IEN.0 - if I don't enable it (it is required in my system) then I observe full PM2 sleeping (HS oscillator stopped + digital regulator turns off). If I enable it, then I see "partial PM2" (HS oscillator stopped but digital regulator still on).

    I can't find any documentation related to this "partial PM2", nor any limitations or side-effects of setting P1IEN. Does anyone have a clue what's going on here?

    Thanks,

    Mark

  • HELP, I seem to have this problem again - partial PM2 sleep where where the digital regulator is still on. Does anyone out there know how this is possibly happening? What are the conditions that keep the regulator enabled? Do I need to ensure certain interrupts/flags are cleared before entering sleep in order to get fully into PM2 mode?

    I am really in a jam here - I don't know what is causing this and therefore don't know how to fix it.

    -Mark

  • Hi Mark,
    I'm glad you already checked that you have proper alignment for the PCON = 0x01 statement, because that would be my first guess here given the current consumption you are seeing.

    Given that the issue follows the P1_0 interrupt, there is another thing that comes to mind. The P1_0 and P1_1 are special in that they have high drive strength but no internal pullup capability contrary to the rest of the GPIOs. Any chance the interrupt gets triggered just as you are going into sleep? What's driving the pin level from the outside? Can

    I'm sure you're aware already, but if you have the debugger connected, the internal regulator (observed on DCOUPL pin) voltage will not drop down in PM2.

    Can you disable the clearing of halSleepPconValue in interrupts? It will give you some other issues, but it could tell you if that's somehow involved in the issue.

    Do you have a 32 kHz XTAL mounted? Try running from that instead. The other thing that could prevent the device going into sleep is if the calibration of the 32 kHz RCOSC (which per default runs every time you start the 32 MHz XOSC). It should finish after a couple of ms, unless there is some sort of deadlock... can't think of why, though. The other option is to set SLEEPCMD.OSC32K_CALDIS.

    Peder
  • Hi Peder,

    Thanks for the ideas here - you actually got me thinking about it more and I think I know what is going on. My P1_0 pin is performing double duty as a low battery indicator LED and an error condition interrupt. This pin has an LED and current limiting resistor connected from it to the chip supply voltage (the low battery indicator output), as well as a 9k pull up to the chip supply voltage with an open-collector output between it and ground (fault condition input/interrupt).

    Here is the system condition that causes this "partial sleep" - P1_0 is normally configured as an active low input interrupt, but when the battery level reaches low level, and the firmware disables the port interrupt (IE2.P1IE), then sets P1_0 low to turn on the low battery indicator LED. Once this happens, IRCON2.P1IF and P1IFG are both set (and P1IEN is still enabled). It seems that if these flags are set (perhaps it is just IRCON2.P1IF), then the internal regulator will not turn off for some reason. I can't find anything in the CC254x User's Guide that would indicate there is any dependency between interrupt flags and fully entering PM2 (I keep saying "fully enter" because I believe the CPU and perhaps peripherals are halted, but the internal regulator is definitely not turning off and the quiescent current is around 2.5mA).

    I had tried clearing IRCON2.P1IF and P1IFG before disabling IE2.P1IE and that still didn't fix things. What I realized is that because P1IEN was still enabled, then P1IF and P1IFG would still get set. When I finally stumbled upon this fact, I changed the code to first disable P1IEN, then clear P1IFG and P1IF, and finally disable IEN2.P1IE before setting the low battery indicator low. This sequence definitely fixes the sleep issue because P1IFG and P1IF get cleared and stay cleared. It is worth noting that at no time during this "battery goes low so indicated it" condition does the Port 1 interrupt get triggered.

    So I have a solution to my problem, but I am still curious about the apparent dependency between the internal regulator and P1IFG and/or P1IF being set. If there is some undocumented issue, it would be well worth an addendum to the User's Guide describing this dependency.

    Thanks again for your help.

    Mark