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.

How can I eliminate CC2540 UART power consumption during known long unused periods?

Other Parts Discussed in Thread: CC2540, CC2541

Hi -

I find that just setting HAL_UART = TRUE is enough to create a steady 2.5ma drain, even if I never initialize or open a UART.   (This is for the CC2540 in simpleBLEPeripheral and derivatives.  You have to tweak HAL_key.c a little to remove an interrupt conflict.)

My application generally requires less than 1 second of UART activity per day, and it seems there must be a way to kill this extra 2+ ma, when it's known there can't be any UART activity at all, until after the next connection starts hours in the future.

I have gotten my application to where it does everything I need, and limits the 8ma needed during actual UART operation to a few 20 millisecond bursts during that 1 second of contact.  But there's still a continuous background consumption of about 2.5ma that's there 24/7, because I simple said "UART".

Is there a solution to this?

Thanks for any thoughts / help.

  • Hello Jerry,

    If you notice the 2.5mA drain when you set HAL_UART = TRUE, then set it to FALSE right after you are finished reading from the port.

    Only set it to TRUE when you are going to take a reading. That is the simple solution.  You can always trace through the code to see exactly why the polling is consuming that amount of current.

    Thanks,

  • Set ihe TX/RX pin to GPI with tri-state once you do not need UART. Re-init UART when you want to use it.

  • greenja said:

    If you notice the 2.5mA drain when you set HAL_UART = TRUE, then set it to FALSE right after you are finished reading from the port.

    Only set it to TRUE when you are going to take a reading. That is the simple solution.  You can always trace through the code to see exactly why the polling is consuming that amount of current.

    Hi Green,

    HAL_UART is a preprocessor symbol, it is not a runtime variable.

  • YiKai Chen said:

    Set ihe TX/RX pin to GPI with tri-state once you do not need UART. Re-init UART when you want to use it.

    Hi YiKay,

    Is this packaged in a function somewhere that I can just borrow?  In hal_uart I see only 'Init' and 'HW_Init', but no 'de-Init' functions.

    Thanks!

  • You are correct.  Looks like you would have to disable the pins manually. That is done by changing the PxINP and setting the MDPx_ bit to 1.

    Thanks,

  • YiKai Chen said:

    Set ihe TX/RX pin to GPI with tri-state once you do not need UART. Re-init UART when you want to use it.

    Is the power really related just to the pin configuration?  I'm not loading the Tx at all, and Rx sits at a clean high.  I'm wondering if I should try "disarming" the DMA.   Is there something that keeps running as long as the Rx and Tx DMA channels are armed?

    Thanks.

  • Single-stepping through HalUARTPollDMA, I see that HAL_UART_DMA_RDY_IN() prevents the cc2541 to go to sleep mode, because my application processor holds CTS high.

  • Hi YiKay,

    Is this packaged in a function somewhere that I can just borrow?  In hal_uart I see only 'Init' and 'HW_Init', but no 'de-Init' functions.

    Thanks!

    No, there is no such de-init API. The only thing you need to do is to set registers PxINP and PxSEL correctly and you can wrap them in a de-init function API by yourself.

  • To Jerry,

    Set PxSEL to disable peripheral function will disable DMA also. So you need to set both PxSEL and PxINP registers.

  • Thanks, YiKai --

    It will be awhile before I have a chance to test this, but I'm pretty sure you've put me on the right track.  One final point you might be able to clarify:  There seems to be absolutely no place in simpleBLEPeripheral or it's supporting code where software touches P0INP (my PxINP) directly.  Does hardware change it when P0SEL enables UART control?  Is setting it back to tri-state then just power minimization, or is it functional?

    Thanks again.

  • You can add settings of P0INP right after InitBoard() in your main function. Except setting P0SEL to peripheral function, you still need to initialized related register to enable UART control. To close it, just set P0SEL to GPIO and UART function will be turn off. Then, you set tri-state of related PIN for power minimization.

  • Can someone from TI please answer this thread. None of the above suggestions are correct.

    If you start with SimpleBLEPeripheral and simply add the following preprocessor definitions: HAL_UART=TRUE, HAL_UART_DMA=2. Load it into the TI KeyFob, then the current shoots up to 8mA.

    You do not have to do any other changes - not even initialise the UART.

    How do you shutdown the DMA UART?

    How would you then re-start the DMA UART?

  • Try to define DMA_PM.

  • No, that is not the problem. DMA_PM is already defined.

    POWER_SAVING is defined in the SimpleBLEPeripheral project properties. In _hal_uart_dma.c it has:

    #if !defined( DMA_PM )
    #if defined POWER_SAVING
    #define DMA_PM 1
    #else
    #define DMA_PM 0
    #endif // POWER_SAVING
    #endif // !DMA_PM

    Still no correct answer yet.

  • Can someone from TI please respond. It has been 6 months with no answer.

  • Hi Jerry,

    Have you solved the issue? I face the same problem now. And it seems the current is always high if set Hal_uart=true in the preprocess.

    StevenSu

  • No the problem was never solved.

    When we finished the connection, we reset the processor get the CC2540 back to low power.

    Chris

  • Hi Chris,

    Oh, so when you need the UART in the connection,  do you need to change the preprocessor and reset the CC2540 again?

    Jiankun

  • Sequence we used was to go to sleep at startup:

    #define DBG_LOW_POWER_STARTUP 1
    ...

    if ( events & SBP_START_DEVICE_EVT )
    {
    ...
    // Start Bond Manager
    VOID GAPBondMgr_Register( &VSSWindscreen_BondMgrCBs );

    #if DBG_LOW_POWER_STARTUP
    #else
    // Set timer for first periodic event
    osal_start_timerEx( VSSWindscreen_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
    #endif

    #if DBG_LOW_POWER_STARTUP
    halSleep(0);
    #endif

    return ( events ^ SBP_START_DEVICE_EVT );
    }

    After reset, the processor calls the above and goes to low power at halSleep(0);
    We wake the CPU using the button to advertise which exits the halSleep(0) routine - and so power goes up.
    We do our processing, and when done reset the processor which causes the above to be run again and stop at halSleep(0).

    I absolutely furious with TI for not responding to this after 2 years!
    We gave up and now use Nordic Semiconductor for all BLE.
  • Oh, you make the chip sleep but not broadcast firstly?
    When you use the button, how do you change the DBG_LOW_POWER_STARTUP back to 0 to turn on the osal ?It seems that it always go to halsleep(0).

    :) TI's enginners are all busy ,maybe they hope we can use nordic instead.
    Do you use nor51822? It is told that the power is less. Can it turn off the UART ? It seems it is not good to discuss the nordic at the TI's forums.