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.

CC3200: Implementing Power Management

Part Number: CC3200

Hello,

I am looking to add power management to my application with a CC3200. My application has a main loop that I execute every 100ms to handle local updates, and is sending data over WiFi every 30s.  I simply want to put the processor to sleep for 100ms in-between these loops to save power.  From my research, it seems that LPDS is what I want, but I'm having trouble bringing code from the idle_profile example into my code (note I am using FreeRTOS). 

I have read documentation, browsed the forums, and looked through several SDK examples(power_measurement, idle_profile, idle_profile_nonos), but still do not have a good grasp of how to implement sleep. From my understanding, TI recommends using the Power Management Framework (PMF) found in the SDK’s “middleware” library rather than following the PRCM API found in the CC3200 Technical Reference Manual. This makes sense, but I am having trouble finding documentation/API on how to implement the PMF.

Can you point me towards any documentation outside of the above mentioned examples and this wiki link: http://processors.wiki.ti.com/index.php/CC32xx_Power_Management_Framework?

 Here are some of the questions that seem to have fallen in the gaps between all the various documentation I've read:

  1. Is TI’s recommendation to copy files from idle_profile into the example (lp3p0_board.c, lp3p0_plat_ops.c, and user_app_config.h)? Is there any further information on what should be customized within these files?
  2. What is the difference between using API set_rtc_as_wk_src and idle profile’s SetTimerAsWkUp (this calls cc_rtc_set, cc_timer_create, and cc_timer_start)? Which should be used?
  3. What makes the application go to “vApplicationIdleHook”? (This is where idle_profile calls cc_idle_task_pm). Where does code resume after exiting this hook?
  4. Does the osi_Sleep(x) function have any relation to the application processor’s low power mode? Or is it only the rtc/gpio/host irq that control when the processor will exit low power mode?
  5. Is it possible to use rtc as wakeup source without modifying the RTC value? I am using RTC to keep real-time (NTP), and I don’t want to affect this counter when entering low power mode.
  6. My understanding is the network processor’s power mode is completely separate from PMF.  It seems the only control for network processor is the sl_WlanPolicySet(SL_POLICY_PM ,xxxx,…) function. Is this correct?  If so, is there any detailed documentation on differences between ‘Normal’, ‘Low Power’, and ‘Long Interval’ options? (I can only find that they are options, not what they actually do)
  7. Where does PMF handle the CPU/Peripheral context save/restore and how much RAM is retained? I’d like to better understand what default settings are so I know what I need to do in addition to what PMF already handles (e.g. GPT, ADC, I2C, and global variables/RAM addresses).

 I am hoping this thread can clear up my questions and also serve as a go-to reference for others trying to implement sleep with the CC3200.

Kind Regards,

-Jon

  • Hi

    1. lp3p0_plat_ops.c and user_app_config.h, are used for setting I/O parking, list of GPIOs used, peripheral settings
    2. set_rtc_as_wk_src is for non-OS applications
    3. vApplicationIdleHook is called when all threads are idle
    The OS resumes wherever it left off before entering sleep
    4. osi_Sleep(x) puts a thread to sleep, and if all threads are sleeping, it should enter low power mode
    5. Yes, you do not have to set the RTC time every time.
    6. The network processor’s power mode is somewhat separate from PMF. Hibernate means Hibernate for both cores, and
    For sl_WlanPolicySet:
    SL_NORMAL_POLICY - Use this for high responsiveness, maximum reliability
    SL_LOW_LATENCY_POLICY - Not used. We need to update our documentation
    SL_LOW_POWER_POLICY - Only should be used in transceiver mode
    SL_ALWAYS_ON_POLICY - This keeps the receiver always on. Very power hungry, with a tiny increase in throughput
    SL_LONG_SLEEP_INTERVAL_POLICY - Uses LSI for AP connection. See NWP manual for use
    7. lp3p0_plat_ops.c

    -Aaron
  • Aaron,

    Thank you for the quick response, but I still have many questions.

    1: So the recommendation is indeed to copy the lp3p0 and user_app files into my application? Is there any documentation on how to adjust these files? I am having trouble as when I try to follow the code and understand what I should modify for my application and what I should leave alone.

    2: Your response to set_rtc_as_wk_src vs. SetTimerAsWkUp is very clear, thank you.

     3/4: I am having trouble getting the application to sleep for 100ms. I still do not understand the relation between osi_sleep(x) and time passed into cc_timer_start (inside SetTimerAsWkUp). I tried totest using idle_profile application, removing UDP server task so only TimerTask is running. Before while(FOREVER) loop in TimerTask, I added this simple loop:

    while(1){
         UART_PRINT("loop\n\r");
         osi_Sleep(...);
    }

    I found the following results when modifying the osi_Sleep value as well as the timer for cc_timer_start:

    Osi_Sleep(2), rtc at 5s: every 5s, 3 loops are executed
    Osi_Sleep(10), rtc at 5s: 15s/loop
    Osi_Sleep(100), rtc at 1M ns: ~.36s/loop (current stays high, debugger never disconnects)

    My intention is to sleep the processor for 100ms inbetween loops, and I'm not making any sense of interaction between osi_sleep time and rtc period.  It also seems like the nsec parameter of the rtc interval timer doesn't work as the processor never enters sleep when LPDS_DUR_SEC = 0.  I am hoping since RTC runs off 32.768kHz timer there is indeed a way to let processor sleep for <1s.

     5: I’m still confused on how SetTimerAsWkUp interacts with PRCMRTCSet. My application currently updates NTP time every 6 hours, and updates RTC with PRCMRTCSet. From your response, it sounds like as long as I take out the cc_rtc_set call in SetTimerAsWkUp I can update set the interval without messing with the RTC value. Is my understanding here correct that cc_timer_create and cc_timer_start do not mess with settings updated by PRCMRTCSet?

     6: Based on your response to setting network processor power, the only connection policy that really applies for low power in Station mode is SL_NORMAL_POLICY, correct?

     7: For save/restore, I see functions in lp3p0_plat_ops.c. Looks pretty straightforward, but I can’t find information about what RAM columns mean. How can I find out what PRCM_SRAM_COL_x my application is using?

    I apologize for these long questions, but do appreciate your responses.  Again, if there is any further documentation that I can look at to help me figure out these questions on my own please tell me where I can find these.

    Kind Regards,
    -Jon

  • 1. The only documentation so far is in the Wiki and the SDK application documents. We do recognize the need for more of this for the PMF
    3/4. I'm a little confused as what the structure of your code looks like here...
    5. You are correct in your assumptions. Setting these timers should not change the RTC time
    6. SL_NORMAL_POLICY or use long sleep intervals
    7. RAM columns simply divide the RAM into equal size sections which can be powered down. Honestly not much power is saved this way, and you should probably just keep them all on.

    -Aaron
  • Aaron,

    The structure of my code has three modifications from the idle_profile example (SDK 1.2.0). My goal here was to have a simple code that did nothing except loop a sleep command and print out a debug message so I could understand how timing works with osi_Sleep(x). Here are the three things I removed:
    1. In order to ensure only 1 loop was running, I commented out the Task creation for UDP server task in main()(osi_TaskCreate(UDPServerTask,...)
    2. In order to ensure I was only seeing current draw from processor running/sleeping, I removed starting simplelink and connecting to station from TimerGPIOTask() (sl_Start(), SwitchToStaMode(), sl_WlanPolicySet(), and WlanConnect() )
    3. I added my own while(1) loop just above the example's while(FOREVER) that performed osi_MsgQRead() in TimerGPIOTask().

    I then attempted adjusting the LPDS_DUR_xxx defines and the osi_Sleep time, but as mentioned above the results did not make any sense and it does not seem NSEC works at all.

    Again, my goal here is just to create a loop that sleeps for 0.1s. If there's something I should call rather than osi_Sleep that would be fine.
  • Any update on how to get CC3200 to sleep for a period of less than 1 second using RTC as wakeup source with FreeRTOS?
  • After further investigation, I believe the issue here is that osi_Sleep function gets its tick from the 80MHz clock, which gets shut down when sleeping. This seems to be the root cause of timing issues, and I'm wondering if anyone has come up with a solution? Why isn't osi_Sleep using the RTC rather than the 80MHz clock?
  • hi
    i want to implement power management - always connected profile(lpds mode) in my TIRTOS project(RTSC project).
    To port the idle profile example to my code what are the steps i should follow??
    these are the only lines i found in the documentation

    Porting to TI-RTOS
    For porting this application on TI-RTOS, please refer to Steps to build a new application on CC3200 with
    TI-RTOS: and Notes section on CC32xx_TI-RTOS page. cc_idle_task_pm() is the function needed to be hooked to
    the idle task.

    To hook the cc_idle_task_pm() to idle task, is it enough to call this function in a task of priority 1.like below..

    void task_1()
    {
    while(1)
    {
    cc_idle_task_pm() ;
    task_sleep(500);
    }
    }


    Thanks a lot

    av
  • av,

    I'm not working with TI-RTOS, and I'm also not getting any responses here, so I'd suggest you post this as a new thread.

    Note when using FreeRTOS you can't put the cc_idle_task_pm() directly into the code; you have to have it in the "idle task hook", which is vApplicationIdleHook for FreeRTOS.  Did you read the Notes section on CC32xx_TI-RTOS page?  At the bottom of that page it explains how to create an idle hook function with xdc.useModule and Idle.addFunc.

    Also note that you very well may need to change the task_sleep function.  As mentioned above, I couldn't get FreeRTOS's task sleep function to work as it was linked to the main oscillator which shuts down in sleep.  I couldn't figure out a good way to work with simple code, so I ended up putting a bogus msgQ into my code as idle_profile has it.  The osi_MsgQRead function stalls code until timer expires.  Not sure how this relates to TI-RTOS.

    Good Luck,
    -Jon

  • Have you tried setting a timer and waiting for the event? You call osi_MsgQRead to wait for it while sleeping. See SetTimerAsWkUp in idle_profile.
  • To clarify, the solution I ended up with was using osi_MsgQRead to halt the loop until timer woke up and this is indeed working. I was initially trying to avoid this as I don't have any use for a Queue in my application. I wanted to simply run my loop and go to sleep, letting the timer wake up and run the loop again. osi_Sleep(x) has funky operation due to clock source and I couldn't find any other FreeRTOS functions to do what I wanted, so I made a Queue that is doing nothing other than allowing me to use the osi_MsgQRead function.
  • Hi
    e2e.ti.com/.../581136

    I went through the uart_power example of tirtos and implemented power policy by calling a single function before bios start and including respective headers.

    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC3200.h>

    Power_enablePolicy();

    i hope this is the right method

    Thanks
    av