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.

L138 Power Down

Other Parts Discussed in Thread: SYSBIOS, OMAP-L138

I am trying to use IDLE istruction as per section 9.25 of SPRUFK5A and have the following code

executed after BIOS_START

void dsp_sleep()


{

  HWREG(PDCCMD) = 0x0001FFFF;

 HWREG(SYSCFG0_CHIPSIG) = 0x00000004;

  asm("IDLE");

}

where

#define PDCCMD 0x01810000

#define SYSCFG0_CHIPSIG 0x01C14174

 

The function does get called but I do not see any change in the value of the above registers.

Wanted to know if the above code is correct.Do i need any additions to the cfg file  ?

Any help will be highly appreciated.

Our application uses syslink (MessageQ) tto exchange data between Arm and DSP (L138)

-Vikas Sharma

 

 

 

  • Vikas Sharma,
    Your piece of code seems ok. Can you debug like using Break Point(BP) via CCS.
    Is that function get execute each line and verify the value at watch window.
    The following software sequence is required to power-down the C674x megamodule:
    1. Enable power-down by setting the MEGPD field in the PDCCMD register to 1.
    2. Enable the CPU interrupt(s) that you want to wake the megamodule up; disable all others.
    3. Execute an IDLE instruction.

    If You like to make DSP idle case via ARM, you can use the below code.
    In you application using the messageQ for communicate between ARM and DSP.
    Here provide the command to call this function at DSP side via syslink.
    If you have queries on SysLink are best handled by TI-RTOS  Forum.

    // This can be added to any task executed in idle context
    #pragma CODE_SECTION(sleep_delay,".sleep_delay")
    #pragma DATA_SECTION(jdelay,".jdelay")
    #pragma DATA_SECTION(idelay,".idelay")
    // ensure that these sections are in IRAM

    int jdelay;
    volatile int  idelay;
    #include <ti/bios/include/tsk.h>
    #include <ti/bios/include/hwi.h>

    void sleep_delay(int milliseconds)
    {
    unsigned int oldReg;
    TSK_disable();
    oldReg=HWI_disable();
    // In case of ARM + DSP system wait for specified milliseconds while ARM
    // does clock chnage  For ex.
    for(jdelay=0;jdelay<milliseconds;jdelay++)
    {
    // this loop runs for 1 ms // TODO: calibrate for customer system, build config etc ..
     for(idelay=0;idelay<13640;idelay++);
    }
    HWI_restore(oldReg);
    TSK_enable();
    }

  • Pubesh,

    The code gets executed and we have verified the same, but the DSP does not get powered down and we have verifying the same by measuring the current consumption with and without the above code.

    I did have one question regarding the PDCCMD register, I don't see the same under core registers. I would like to make sure that the MEGPD bit is set to 1 

    Can you please let me know where can I read the value of the same in Code composer studio, I do see other 

    registers.

    Thanks,

    -Vikas Sharma

  • Vikas,

    At CCS:
    Click View-->Registers. Here you can find the all the registers. If not, you can read the value as per below.

    View Memory at Address
    Shows the memory with the address of the selected register in a Memory View.
     
    View Memory at Value
    Shows the memory with the value of the selected register in a Memory View.

  • Hi Pubesh,

    I am aware of how to see the registers and have been using the procedure you described in the previous post however a mentioned earlier I do not see the PDCCMD register in the list of registers. The power down sequence we are trying to implement doesn't seem to work. At this point not sure what I am missing as I am following the procedure mentioned in section 9.25 of SPRUFK. 

    Thanks,

    -Vikas

  • Vikas,

    In addition, you can set the PWRD field in the Control Status Register(CSR). It may help you.
    Refer the TMS320C674x DSP CPU and Instruction Set Reference Guide to get more details.

  • Pubesh,

    Thanks for the info on PWRD, however I am not able to change the CSR fields. We are in supervisor mode and the only bit i can change is the bit which enables interrupts globally. Is there a need for nop or delay associated with writting to the CSR bits ?

    -vikas

  • Hi Vikas

    Since you are loosing SYSLINK etc, why not try the support available in the SYSBIOS, via the PWRM module?

    I want to make sure you are aware of the PWRM module and the features it supports

    http://processors.wiki.ti.com/index.php/Power_Module_for_C6748_and_OMAP-L138

    You should be able to use the sleep modes specified here to put the megamodule in IDLE state.

    After executing the instructions you snapshotted (assuming you are in supervisor mode) , what register value were you expecting to see change?

    The power savings from just executing PDCMD IDLE (megamodule idle) can be gauged from looking at the power estimation spreadsheet

    http://processors.wiki.ti.com/index.php/OMAP-L138_Power_Consumption_Summary


    If you configure the operating frequency etc to the operating frequency you are testing, you will see the relative power savings on the CVDD by seeing the difference between DISABLE mode (where ARM turns of the DSP clock via PSC) vs IDLE (Megamodule Sleep Mode) ,which is what you are doing  drop down menus.

    Hope this helps.

    Regards

    Mukul

  •  

    Hi Mukul,

    Thanks for the reply. I will try to use the power module. I did try it a while back  but got the following issues when linking  can't find package ti.sysbios.family.c64 when  I added the following to cfg file

    var Power = xdc.useModule('ti.sysbios.family.c674.Power');

    I didn't debug it much as we decided to use PDCCMD register to power down DSP, the thinkig was this would give maximum power savings.

    Thanks,

    -Vikas Sharma

     

     

  • Vikas

    The level of power savings can be gauged for the power estimation model, hopefully you already did that are ok with the level of savings that megamodule IDLE will provide.

    Apart from the suggestion to directly leverage the power management module from SYSBIOS, the only other suggestions i can make are

    1) Make sure that you are in supervisor mode (if you are using BIOS, you should always be in supervisor mode)

    2) Recommend just doing a read modify right to bit 16 of PDCCMD register , bit 0-15 are reserved read 1 only (should be ok with what you are doing too i guess)

    3) Try removing the chip sig write in between the PDCMD write and IDLE instruction

    4) If you are suspecting that you are not going in IDLE, please add a bunch of nops or have some LED function executing after IDLE instruction, to make sure that your PC has not moved beyond IDLE instruction etc.

    5) If the concerns are that you are not seeing noticeable power delta, make sure what you are expecting or observing is not in alignment with what you see in the power estimation spreadsheet.

    If you did get into issues with using the PWRM module, I do recommend posting your follow up questions on the BIOS forum. The BIOS forum team is very proactive, and hopefully will be able to resolve any issues you see w.r.t package mismatch etc (make sure to provide the complete version of SYSBIOS etc being used).

    Hope this helps.

    Regards

    Mukul

  • The version of BIOS you are using (6.32.05.54) does not have ti.sysbios.family.c674.Power support

    hence the reason it did not work for us.At this point I will try to add some delay after IDLE to see if we achieve

    any reduction in power. I had tried few nops of no avail earlier


    Thanks,

    -vikas

  • Hi Mukul,

    As mentioned in the previous post we were not using the right BIOS version so the sysbios.family.c674.power support was missing. I decided to go to the BIOS version supporting the power module. I decided to test the basic MessageQ example provided in the examples filders (ex02_messageq) and have no issues with it. On top of the examples I added the power module and in doing so I get the following errors :

    start callback failed.

    Not sure why I am gettign this as the memory regions are not changed, unless the power module does not agree with shared memory region.

    The config.bld file is as follows ( we had to modify it as we needed contiguous block of memory on Linux)


     *  ======== config.bld ========
     *
     */

    var Build = xdc.useModule('xdc.bld.BuildEnvironment');

    /*  Memory Map for ti.platforms.evmOMAPL138
     *
     *  C000_0000 - C7FF_FFFF   800_0000  ( 128 MB) External Memory
     *  ------------------------------------------------------------------------
     *  C000_0000 - C1FF_FFFF   200_0000  (  32 MB) Linux
     *  C200_0000 - C200_FFFF     1_0000  (  64 KB) SR_0 (ipc)
     *  C201_0000 - C202_FFFF     2_0000  ( 128 KB) SR_1 (MessageQ buffers)
     *  C203_0000 - C2FF_FFFF    FF_0000  ( ~15 MB) --------
     *  C300_0000 - C37F_FFFF    80_0000  (   8 MB) DSP_PROG (code, data)
     *  C380_0000 - C3FF_FFFF    80_0000  (   8 MB) --------
     *  C400_0000 - C7FF_FFFF   400_0000  (  64 MB) Linux
     */

    var SR0 = {
            name: "SR0", space: "data", access: "RWX",
            base: 0xC3800000, len: 0x10000,
            comment: "SR#0 Memory (64 KB)"
        };

    var SR1 = {
            name: "SR1", space: "data", access: "RWX",
            base: 0xC3810000, len: 0x20000,
            comment: "SR#1 Memory (128 KB)"
        };

    Build.platformTable["ti.platforms.evmOMAPL138:dsp"] = {
        externalMemoryMap: [
            [ SR0.name, SR0 ],
            [ SR1.name, SR1 ],
            [ "DSP_PROG", {
                name: "DSP_PROG", space: "code/data", access: "RWX",
                base: 0xC3000000, len: 0x800000,
                comment: "DSP Program Memory (8 MB)"
            }]
        ],
        codeMemory:  "DSP_PROG",
        dataMemory:  "DSP_PROG",
        stackMemory: "DSP_PROG",
        l1DMode: "32k",
        l1PMode: "32k",
        l2Mode: "32k"
    };

    /*
     *  ======== ti.targets.elf.C674 ========
     */
    var C674 = xdc.useModule('ti.targets.elf.C674');
    C674.ccOpts.suffix += " -mi10 -mo ";
    Build.targets.$add(C674);

    The Dsp.cfg file is as follows I added the power related stuff

    /*
     *  ======== Dsp.cfg ========
     *
     */

    /* root of the configuration object model */
    var Program = xdc.useModule('xdc.cfg.Program');

    /* application uses the following modules and packages */
    xdc.useModule('xdc.runtime.Assert');
    xdc.useModule('xdc.runtime.Diags');
    xdc.useModule('xdc.runtime.Error');
    xdc.useModule('xdc.runtime.Log');
    xdc.useModule('xdc.runtime.Registry');

    xdc.useModule('ti.sysbios.gates.GateHwi');
    xdc.useModule('ti.sysbios.knl.Semaphore');
    xdc.useModule('ti.sysbios.knl.Task');

    var BIOS = xdc.useModule('ti.sysbios.BIOS');
    BIOS.libType = BIOS.LibType_NonInstrumented;
    var Power = xdc.useModule('ti.sysbios.family.c674.Power');
    Power.idleCpu = true;
    Power.trackResources = true;
    //var Hwi = xdc.useModule('ti.sysbios.family.c64p.Hwi');
    //var Idle = xdc.useModule('ti.sysbios.knl.Idle');
    //Idle.addFunc("&idleDSP");

    /*
     *  ======== IPC Configuration ========
     */

    /* required because SysLink is running on the host processor */
    xdc.useModule('ti.syslink.ipc.rtos.Syslink');

    /* configure processor names */
    var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
    var procNameAry = MultiProc.getDeviceProcNames();
    MultiProc.setConfig("DSP", procNameAry);

    /* ipc configuration */
    var Ipc = xdc.useModule('ti.sdo.ipc.Ipc');

    /* ipc setup for SR0 Memory (host processor not running Sys/Bios) */
    Ipc.sr0MemorySetup = false;

    /* set ipc sync to pair, requiring Ipc_attach() call on all processors */
    Ipc.procSync = Ipc.ProcSync_PAIR;

    /* define host processor */
    Ipc.hostProcId = MultiProc.getIdMeta("HOST");

    /* shared region configuration */
    var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');

    /* configure SharedRegion #0 (IPC) */
    var SR0Mem = Program.cpu.memoryMap["SR0"];

    SharedRegion.setEntryMeta(0,
        new SharedRegion.Entry({
            name:           "SR0",
            base:           SR0Mem.base,
            len:            SR0Mem.len,
            ownerProcId:    MultiProc.getIdMeta("HOST"),
            cacheEnable:    false,
            isValid:        true
        })
    );

    /* configure SharedRegion #1 (MessageQ Buffers) */
    var SR1Mem = Program.cpu.memoryMap["SR1"];

    SharedRegion.setEntryMeta(1,
        new SharedRegion.Entry({
            name:           "MessageQ Buffers",
            base:           SR1Mem.base,
            len:            SR1Mem.len,
            ownerProcId:    MultiProc.getIdMeta("HOST"),
            cacheEnable:    false,
            isValid:        true
        })
    );

    /*  configure external memory cache property
     *
     *  C000_0000 - C7FF_FFFF   800_0000  ( 128 MB) Cache.MAR192_223
     *  ----------------------------------------------------------------------------
     *  C000_0000 - C1FF_FFFF   200_0000  (  32 MB) --------    don't care
     *  C200_0000 - C202_FFFF     3_0000  ( 192 KB) SR_0, SR-1  no-cache      MAR194
     *  C203_0000 - C2FF_FFFF    FD_0000  ( ~15 MB) --------    no-cache      MAR194
     *  C300_0000 - C37F_FFFF    80_0000  (   8 MB) DSP_PROG    cache enable  MAR195
     *  C380_0000 - C3FF_FFFF    80_0000  (   8 MB) --------    cache enable  MAR195
     *  C400_0000 - C7FF_FFFF   400_0000  (  64 MB) --------    don't care
     */

    Cache = xdc.useModule('ti.sysbios.family.c64p.Cache');
    Cache.MAR192_223   = 0x00000000;  /* xxxx xxxx xxxx xxxx xxxx xxxx xxxx 10xx */


    /*
     *  ======== Operating System Configuration ========
     */

    /* no rts heap */
    Program.heap = 0;
    Program.argSize = 100;  /* minimum size */
    Program.stack = 0x4000;

    /* create a default heap */
    var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
    var heapMemParams = new HeapMem.Params();
    heapMemParams.size = 0x4000;

    var Memory = xdc.useModule('xdc.runtime.Memory');/* configure System module */
    var SysMin = xdc.useModule('xdc.runtime.SysMin');
    SysMin.bufSize = 0x1000;
    SysMin.flushAtExit = false;

    var System = xdc.useModule('xdc.runtime.System');
    System.SupportProxy = SysMin;

    /* configure SysBios to use the lower half of Timer 1 */
    var Timer = xdc.useModule('ti.sysbios.timers.timer64.Timer');
    var Clock = xdc.useModule('ti.sysbios.knl.Clock');
    Timer.timerSettings[2].master = true;
    Timer.defaultHalf = Timer.Half_LOWER;
    Clock.timerId = 2;


    /*
     *  ======== Miscellaneous Configuration ========
     */

    /* set default diags mask */
    var Diags = xdc.useModule('xdc.runtime.Diags');
    var Defaults = xdc.useModule('xdc.runtime.Defaults');

    Defaults.common$.diags_ENTRY     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_EXIT      = Diags.ALWAYS_OFF;
    Defaults.common$.diags_LIFECYCLE = Diags.ALWAYS_OFF;
    Defaults.common$.diags_INTERNAL  = Diags.ALWAYS_OFF;  /* needed for asserts */
    Defaults.common$.diags_ASSERT    = Diags.ALWAYS_OFF;  /* development only   */
    Defaults.common$.diags_STATUS    = Diags.RUNTIME_ON;
    Defaults.common$.diags_USER1     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_USER2     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_USER3     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_USER4     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_USER5     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_USER6     = Diags.ALWAYS_OFF;
    Defaults.common$.diags_INFO      = Diags.ALWAYS_OFF;
    Defaults.common$.diags_ANALYSIS  = Diags.ALWAYS_OFF;

    /* override diags mask for selected modules */
    xdc.useModule('xdc.runtime.Main');
    Diags.setMaskMeta(
        "xdc.runtime.Main",
        Diags.ENTRY | Diags.EXIT | Diags.INFO,
        Diags.RUNTIME_ON
    );

    var Registry = xdc.useModule('xdc.runtime.Registry');
    Registry.common$.diags_ENTRY = Diags.RUNTIME_OFF;
    Registry.common$.diags_EXIT  = Diags.RUNTIME_OFF;
    Registry.common$.diags_INFO  = Diags.RUNTIME_OFF;
    Registry.common$.diags_USER1 = Diags.RUNTIME_OFF;

    /* create a logger instance */
                                                                         
    Memory.defaultHeapInstance = HeapMem.create(heapMemParams);

    Thanks,

    -Vikas Sharma