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.

C6748 Sleep Constraints

Other Parts Discussed in Thread: OMAP-L138, SYSBIOS

Hi There

I have followed the guide at location http://processors.wiki.ti.com/index.php/Power_Module_for_C6748_and_OMAP-L138 

to put the C6748 to various sleep modes.  I have used the example code on the C6748 LCDK board ant this works fine.  When I hook this example into my own project on a custom board I have an issue when it comes to specifying this in the .cfg file

   Program.sectMap[".text"] = "L3_CBA_RAM";
  Program.sectMap[".bss"] = "L3_CBA_RAM";
  Program.sectMap[".vecs"] = "L3_CBA_RAM";
  Program.sectMap[".far"] = "L3_CBA_RAM";

It appears when I compile that these files are too large to store in L3 cache....compiler output:

<Linking>
"./configPkg/linker.cmd", line 275: error #10099-D: run placement fails for
object ".far", size 0x1b5ef2 (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0xb138 max hole: 0xb134
"./configPkg/linker.cmd", line 258: error #10099-D: placement fails for object
".text", size 0x44b81 (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x18 max hole: 0x14
"./configPkg/linker.cmd", line 270: error #10099-D: placement fails for object
".const", size 0x60fb (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x8 max hole: 0x4
"./configPkg/linker.cmd", line 260: error #10099-D: run placement fails for
object ".stack", size 0x2000 (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x8 max hole: 0x4
"./configPkg/linker.cmd", line 279: error #10099-D: placement fails for object
".vecs", size 0x5ff (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x8 max hole: 0x4
"./configPkg/linker.cmd", line 273: error #10099-D: placement fails for object

".switch", size 0x236 (page 0). Available ranges:
>> Compilation failure
L3_CBA_RAM size: 0x20000 unused: 0x8 max hole: 0x4
"./configPkg/linker.cmd", line 261: error #10099-D: run placement fails for
object "GROUP_1", size 0x188 (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x8 max hole: 0x4
"./configPkg/linker.cmd", line 277: error #10099-D: run placement fails for
object ".cio", size 0x123 (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x8 max hole: 0x4
"./configPkg/linker.cmd", line 267: error #10099-D: placement fails for object
".cinit", size 0x1156 (page 0). Available ranges:
L3_CBA_RAM size: 0x20000 unused: 0x4 max hole: 0x4
error #10010: errors encountered during linking; "icl_interrogator.out" not
built
gmake: *** [icl_interrogator.out] Error 1

The guide states that this data must reside on L2/L3 cache when bypassing the PLL1.  Have you any suggestions as to what I could do to get around this?

All help appreciated,

Tony

  • Tony,

    From those link errors it looks like the sizes of those sections for your particular application are much too big to fit into the L3 RAM. 

    In your custom board design do you have external static memory (that is usable when PLL1 is bypassed) that can be used instead?  On the standard development boards this external RAM is dynamic and can’t be access with PLL1 bypassed, so that is why those sections are pushed on-chip to the L3 region for access during the sleep transitions.

    Scott

  • Hi Scott

    No the Ram is mDDR, there is Flash and SD in a similiar layout to the EVM/LCDK boards.  I'm guessing its not possible to use these?  Does this effectively rule out Deep sleeping the device?

    Regards

    Tony

  • Tony,

    OK, thanks.  No, I don’t think this effectively rules out deep sleep.  But it may be the case that you need to take some special steps before/after invoking the API. 

    Or, it might just work, without following all the guidelines listed on the wiki.  Did you try invoking deep sleep on your custom board without these additional memory placement steps?  What is absolutely necessary depends upon your application and placement of code and data in memory.  The recommendations are general, intended to cover a broad set of use cases.

    I need to review the code and list of constraints and get back to you...  Hopefully later today...

    Scott

  • Hi Scott

    I did try to deep sleep the device after pulling in the example code to my project.  I didn't see any drop in current when I ran the Deep Sleep sequence.  I haven't played around with it much though as I didn't really want to have the deep sleep routine in place not knowing the consequences of not being able to move the data to local memory.  A later scan of the tech ref manual for the C6748 doesn't mention the need to move this data locally before deep sleep.  Maybe it is a SysBios requirement, but I cant be sure.  I will spend a few more hours at it today and see how I go.

    Regards

    Tony

  • Tony,

    OK, thanks.

    Regarding the placement constraints… the type of failure I would see if there were an issue with DDR access during PLL bypass would be a catastrophic application crash due to corrupted data reads.  Not the case where I didn’t see a current drop as expected.

    Have you tried running that simpler and smaller example you’d run on the TI EVM directly on your custom hardware?  If it fit on-chip on the EVM, it will fit on your custom hardware too.  Then you can see if you measure the expected current drop or not.  And if the deep sleep wakeup via RTC or external pin is configured correctly.  Once that works, then look at relaxing the placement constraints?...

    Regarding the constraints, I looked over the code again, and for invoking PWRM_DEEPSLEEP specifically, I think you can:

    1) Place the stack of the TSK that is calling PWRM_sleepDSP() somewhere in on-chip memory.  For example, to place all TSK stacks on-chip you can specify this in the configuration file:
    bios.TSK.STACKSEG = prog.get("IRAM");

    2) Be sure to specify that PWRM’s section with code that must reside on-chip gets placed on-chip.  For example, specify:
    bios.PWRM.ONCHIPMEMSEG = prog.get("IRAM");

    3) Call HWI_disable() before PWRM_sleepDSP(), and HWI_restore() after the sleep API returns.

    It has been a few years since I was in this code originally, but I think this should be sufficient for invoking PWRM_DEEPSLEEP…

    Scott

  • Hi Scott

    Thanks for the response.  The commands you mentioned "bios.TSK.STACKSEG = prog.get("IRAM");" & "bios.PWRM.ONCHIPMEMSEG = prog.get("IRAM");" dont work in my SysBios config file.  are these valid commands?  


    I Did run the example on my custom board but I need to work on it a little as all the other on board devices will be all over the place from not being initialised, leaving current consumption at the max the board can supply.



    Regards


    Tony

  • Hi Scott

    I did some more work on this today using my custom board.  I have isolated the DSP supplies from everything else.  I have tested out the SLEEP, DEEPSLEEP and STANDBY modes and they all reduce the current to expected levels when run from main (before the call to Bios Sart).

    After Bios Start, and running from a task I note the following:

    I can enter and recover from Standby mode and resume normal operations after without any issues .  I am using the call Power_sleepDSP(Power_STANDBY, 0, 0); for this.

    I haven't located any documentation on this call.  The wiki that outlines its example use shows that it goes to standby for one clock tick.  How do I make it go to sleep for longer than this?  I tried extending the clock tick period but this messes up SD card file IO.  For using this standby function I may be able to dynamically extend the clock tick period before going to standby and restore the standard 1000uS tick once I get out.  Maybe you guys know a better way to Standby for more than one clock tick.

    Entering Sleep or DeepSleep causes issues and once I get in there I cant get back out.  Current consumption doesn't drop at all like it did when run from main.  Maybe the whole thing crashes before it even gets to low power mode.  I want to try moving the task stacks to local memory to see if this solves anything for me.  Any further information on how to do this would be great.

    Many thanks

    Tony

  • Hi Tony,

    Sorry, I accidentally sent you DSP/BIOS config snippets instead of SYS/BIOS.  

    For SYS/BIOS, you can place Power’s section using this:

    Power.onChipRegion = "L3_CBA_RAM";

    To default to having all Task stacks in L3 you should be able to do something like this:

    Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
    Program.sectMap[Task.defaultStackSection].loadSegment = "L3_CBA_RAM";

    Also, you can control the placement of an individual task’s stack (versus all tasks) via the “stackSection” creation parameter for the task.

    You can find detailed API documentation within the SYS/BIOS installation.  You can open the “BIOS_APIs.html” file in the “docs” subdirectory of the SYS/BIOS install, and then navigate to the ti.sysbios.family.c674.Power module.  Or, you can open the “index.html” file from the “cdoc” subdirectory, and navigate to the Power module.  For example (using your SYS/BIOS version number): C:\ti\bios_6_34_01_14\docs\cdoc\index.html

    You can also find all the sources for Power and PMI and PSCL within the SYS/BIOS installation.  For example:

    Power: C:\ti\bios_6_34_01_14\packages\ti\sysbios\family\c674

    PMI: C:\ti\bios_6_34_01_14\packages\ti\sysbios\family\c674\pmi

    PSCL: C:\ti\bios_6_34_01_14\packages\ti\sysbios\family\c674\pscl

    For both STANDBY and SLEEP, the CPU will be awoken out of the power saving mode by the next enabled interrupt that occurs.  In the sample projects we leverage the Clock tick interrupt to conveniently do this wakeup, to move on to the next step of the example.  

    If it isn't appropriate to slow the Clock ticks, and you want to temporarily disable the Clock module ticks during STANDBY, and instead wakeup upon another interrupt source, you can call Clock_tickStop() before the Power call, and then Clock_tickStart() afterwards.

    For DEEPSLEEP the CPU doesn’t use an enabled interrupt for wakeup, but a special mechanism that wakes based upon RTC_ALARM or external pin assertion.  After initiating DEEPSLEEP, PMI_sleepCPU() goes into a spin loop checking for a sleep completion bit, and the device automatically powers down after all the necessary internal handshaking.  When the CPU wakes again from either RTC or external pin assertion, the spin loop continues, and the sleep completion bit is now asserted, so the CPU falls out of the spin loop.  This special behavior for DEEPSLEEP is what allows the calls to disable/restore interrupts around the Power_sleepDSP() call that I’d recommended.  This interrupt disabling limits the CPU activity such that the necessary on-chip constraints are observed.  

    For STANDBY you will need to leave interrupts enabled before the Power_sleepDSP() call.  But there are no memory placement constraints in this mode because it is only the CPU subsystem that is affected, and the PLLs are left locked.

    For SLEEP you will also need to leave interrupts enabled before the Power_sleepDSP() call, or the CPU won’t wakeup.  But it means that the CPU could take an interrupt during the transitions, which may cause an off-chip access (e.g., if interrupt vectors are off-chip).  For SLEEP I don't think you'll be able to avoid most of the documented memory placement constraints and still be able to reduce voltage and enable PLL bypass.  You'll probably need to disable both of these steps via a SleepOverride structure as the sleepArg parameter for Power_sleepDSP().  (Please see the above referenced API documentation.)  DEEPSLEEP should be doable, but SLEEP functionality will be limited.

    Hope this helps…

    Scott