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.

SDRAM powerdown on DA830/OMAP-L137

Other Parts Discussed in Thread: OMAPL138, SYSBIOS, OMAP-L138

I am trying to put a custom DA830 board into a low power mode.  When low power is required, a standby micro asserts RESET to the DA830.  The reset is a so-called "power-on reset" because TRST is pulled low through 4.7K.

My problem is that the board seems to go into two different low power states with a 90 mW difference between them (as measured at the board's +5V input).  Whether the board powers down to X mW or X + 90 is apparently random.  The variation in power is on the +3.3V supply, not the +1.3V supply. Without an easy way to measure current drawn by the SDRAMs, I can only guess that the difference is in the SDRAM state when the DA830 is reset.

I have attempted to do the following to put the board into low power mode, but have not gotten rid of the randomness:

1)  The ARM, which is running Linux, resets other devices on the board, then sends a command to the DSP to request power down.

2)  The DSP, running code from L3RAM, clears the ARM's LRST bit in psc0->MDCTL[LPSC_ARM] to reset the ARM (to keep it from accessing the SDRAMs)

3)  (Additionally, I have tried adding lpscDisable to disable the ARM's power domain)

4) The DSP disables hardware interrupts, the idea being that an SDRAM access might reawaken the RAMs.

5)  The DSP sets the SR_PD bit in the SDRAM Refresh Control Register to select power-down as opposed to self-refresh.

6) The DSP sets the LP_MODE bit in the SDRAM Refresh Control Register to power down the RAMs.

7) The DSP drives a GPIO to request a reset from the micro.

8) The micro asserts reset to the DA830

Do you see anything wrong with my understanding?  Is there anything else I need to do to make sure the SDRAMs are in a low power state when the DA830 is held in reset?  Or is the 90 mW variation (measured at +5VIN) unlikely to be due to the SDRAMs?

  • Hi,
    Can you consider DEEPSLEEP mode in linux ?
    You want low power mode with processor reset ?
  • Hello Debora,

    To put the device in low power mode, you may not need to reset (POR) the device instead you could use the sleep modes available in Power and Sleep Controller. Please refer section 9 Power and Sleep Controller (PSC) in the TRM for more clarity.

    You can also refer the power consumption summary of OMAPL137 in the following wiki.

    processors.wiki.ti.com/.../OMAP-L137_Power_Consumption_Summary

    Regards,
    Senthil
  • Titus and SenthilKumar, thanks for responding. Can you point me to example code that shows how to put the whole DA830 subsystem - ARM, DSP, and SDRAMs - into a low power sleep mode? My recollection was that it existed for the DA850 but not the DA830. That is why I am using the power-on reset.

    Regards,
    Debora
  • More detail after consulting a coworker:

    No, we can't do deep sleep in Linux as the version of Linux we've got for the DA830 does not support deep sleep. The last time we looked in detail, we understood that the DA830/L137 has a less sophisticated power controller than the L138 and deep sleep was only developed/deployed/supported on the L138. If someone knows otherwise, please do share!

    We remember once seeing an example of the ARM doing a complete power down. It was a simple ARM program. Can anyone find that example?
  • Debora
    I think we communicated everything we knew on this topic to Chuck and crew.
    As you mentioned DA830 family does not support deep sleep mode.
    So I think the best power down you can accomplish, with processor alive would be

    1) The SoC running in bypass mode (CLKIN frequency)
    2) DSP clocked off via ARM
    3) ARM executing WFI
    4) All clocks to peripherals disabled via PSC
    5) SDRAM in self refresh

    You should be able to deduce the power for this looking at the OMAPL137 Power Consumption Summary
    processors.wiki.ti.com/.../OMAP-L137_Power_Consumption_Summary
    Look for the Standby Button macro and associated power consumption

    Code example for putting SDRAM in self refresh (which i assume you are already doing correctly) is available here
    processors.wiki.ti.com/.../0x_IO_Buffer_Premature_Aging_Assessment

    Titus and team can help you find ARM WFI code, this should be standard and hopefully not require too much work on your side.

    DSP clock off is some times not trivial, but can be managed by the sequence available in the TRM
    You might also be able to find low level functions in the PWRM (SYSBIOS) offering for OMAPL138/c6748
    processors.wiki.ti.com/.../Power_Module_for_C6748_and_OMAP-L138
    The code sequence will be same for OMAPL137/DA830.

    I do not recommend keeping device in reset, we do not characterize power of the part "in reset" , as you are seeing variation on 3.3V, i expect possibly board IOs or processors IO not in the right state during reset.
    Proper power down is to do it in software and keep the processor alive.

    Hope this helps.
    Regards
    Mukul
  • Thank you, Mukul. I look forward to receiving the ARM WFI code from Titus.
  • Hi Debora,
    I'm working on this.
    How about the wakeup process ?
    i.e how do you wish to wake up the board from sleep mode ?
    Any interrupt events ?
    I have implemented and tested the WFI code in bare metal code not with Linux.
  • Hi Titus,

    Thanks for the update and for all your help.  I'll be very interested to see the WFI code in Linux.

    I can think of two ways to wake the DA830 up from sleep mode.

    1)  One way is with a power-on reset, since our hardware already supports this.  The standby micro can pulse the DA830 reset when it's time to wake the 830.  For this to work on our board, the DA830 has to drive an internally-pulled up GPIO low while it's sleeping.  (This GPIO controls some reset enable logic.)

    2) The other way is more conventional.  There's another GPIO connected between the micro and the DA830.  It  happens to be internally pulled down in the 830.  The micro can switch it as the wake-up interrupt to the 830.

    Regards,

    Debora

  • Debora

    I don't understand #1 option. If you are going to assert a reset to device, it is going to start from its power on reset state, not your previously saved state etc. 

    So it is likely #2.

    My intent was to ask Titus to point you to the relevant DA850/OMAPL138 code on WFI/Idle

    This may not be available on OMAPL137/DA830. However it is the same ARM9 core, and very similar device family - so hope was that you could use this as reference?

    Regards

    Mukul 

  • Hi Mukul,

    We don't need to start from a saved state. We are OK with rebooting the DA380 to wake it up. Since the DA830 does not support deep sleep mode, our intended "low power" mode was to hold the DA830 in reset. This works fine except that we are not consistently achieving the low power level we would like. There is a random 90 mW variation in standby power (as measured at our board's 5V input). The standby power is acceptable in the lower state we measure, but not in the low state + 90 mW.

    We appreciate this information: "I do not recommend keeping device in reset, we do not characterize power of the part 'in reset' , as you are seeing variation on 3.3V, i expect possibly board IOs or processors IO not in the right state during reset. " But instead of holding the device in reset, we're fine with pulsing reset when we want to wake the board up. Or we can wake on an interrupt, which is perhaps more conventional.

    Regards,
    Debora
  • If "pulsing reset" means resetting DA830, it will not be retaining the ARM WFI state you put it in.
    The lowest power state that DA830 can achieve is with voltage applied, no reset assert/deassert, clocks maximally disabled via PSC, unused core (DSP) clocked off too.
    If the power consumption in this state is still too much or the software complexity is high (given there is no code available for this SoC) , you could see if you could just power off the DA830 completely (all supplies removed) and just start again (will incur power supply ramp time, boot init and all other software init time etc) - instead of holding it in reset (we don't characterize power in reset and i dont know if you are going to run into any other reliability issues if the 3.3V supplies other components on the board).
    Hope this helps.

    Regards
    Mukul
  • Hi Mukul,

    You say "the software complexity is high (given there is no code available for this SoC)." I'm trying to assess how high the software complexity is.

    I just recompiled the kernel with the cpuidle driver included. Can you tell me how to tell this driver to put the ARM in WFI? It's not obvious to me from the Wiki page how to trigger the cpuidle state0 to put the ARM into the WFI state, or if it even works on the 830. The Wiki page says "The cpuidle driver in Linux kernel allows CPU to idle efficiently by moving to a state with lower power consumption during idle. Once built in cpuidle driver works automatically and does not require any user intervention. OMAP-L138 cpuidle driver implements two states..." (processors.wiki.ti.com/.../OMAP-L1_Linux_Drivers_Usage)

    Then there's the job of turning off the DSP and putting the clocks in their lowest power state. As you said, "DSP clock off is some times not trivial, but can be managed by the sequence available in the TRM ." So it looks like my only hope is to try to write my own code that follows the TRM, if I can't find anything in SYSBIOS? Are you aware of anything in SYSBIOS for the 830?

    I don't care if the DA830 retains its WFI state or not. I understand that I shouldn't hold it in reset because that state is not characterized, but I don't mind resetting it when I wake it up. I can accept the boot init and software init time. I'm just trying to find a way to put it in a low power state without a significant hardware change.

    Regards,
    Debora
  • Hi Mukul-
    We are coming back on this now. I dug around and I found the stuff you gave me 2 years ago. It's an example of the DSP putting the RAM in low power mode as found in the premature aging post. Based on your advice we are planning to write a simple ARM program that will aim to put the system in one of its lowest power states. We'll experiment with standby and static, as shown in the spreadsheet.

    Can you possibly find a simple ARM example for an L137 sort of part that puts the system into these states? It would save us some time to recreate it.
  • Hi Chuck
    Unfortunately I don't have anything tailored to ship out for OMAPL137/DA83x family.
    All relevant examples that exist online are in context of OMAPL138 - and with the exception of the deep sleep feature , similar concepts will apply to OMAPL137.

    Regards
    Mukul
  • I understand. An L138 example would be great. I see examples of putting the DSP in a low power state, but I understand that it's better to clock off the DSP and leave the ARM in a low power state. I see the L138 Linux drivers given as examples. I've been in them and they're not really simple. If this is the extent of what's available, we can take it and run. I just thought it would be good to ask one more time whether anyone has a simple ARM example.
  • Hi Chuck
    From ARM side it is really just the Linux cpuidle that you will see available on OMAPL138.
    There is no bare metal or Starterware type example for this.
    Do note that when we tested (say for power characterization) all it needs is the ARM WFI instruction, as I can make use of the power on default states of the peripherals which is primarily PSC clock off and PLLs in bypass. The complexity of implementation in real world is the handshake required to put the processor in idle state prior to executing WFI/IDLE instructions etc and disabling clocks to various peripherals and putting DDR in self refresh etc, which is what the Linux PM or SYSBIOS PM (PWRM) will take care of in OMAPL138 world.

    I will check with Titus if he started constructing anything simpler based on Debora's previous emails.

    Regards
    Mukul
  • Hi Chuck,

    I have taken some simple ARM code for OMAPL137.

    C:\ti\quickStartOMAPL1x_rCSL\OMAPL1x\rCSL_examples\evmOMAPL137\ARM_examples\gpio\GPIO_multi_led_interrupt_armL137

    I have used the ARM WFI instruction to put the ARM to WFI mode.

    This "arm_wfi" function will put the ARM into low power by executing this ASM.

    I have tested this on OMAPL137 SDI EVM board, it will blink the DS1 when you interrupt (also emulation debug interrupt suspend/resume) through SW3:0.

    I'm also checking the Linux power management for OMAPL137.

    I think, it needs some driver development, DSP power off, clock gating etc.,

    For linux, is it okay for you the following power save mode (combination) ?

    i) DSP power off(DSP mega module & DSP core).

    ii) Frequency scaling

    iii) Gating Module clocks via LPSC

    How do you want to initiate low power mode ?

    Giving any input to driver from user space ?

    Ex:

    echo 1 > /sys/kernel/power_custom/low_power

    /*-----------------------------------------------------------------------------
     * Project: GPIO_multi_led_interrupt_armL137
     * File: main.c
     *
     * This file contains the test / demo code to demonstrate basic GPIO 
     * operations using the Regsiter CSL macros.
     *
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     *-----------------------------------------------------------------------------
     * 
     * GPIO_multi_led_interrupt_armL137
     * --------------------------------
     * 	Purpose: Demonstrate usage of GPIO rCSL
     * 
     *	Example Description:
     *   	This example initializes the GPIO peripheral using the rCSL macros to
     * 		configure six pins as GPIO and bring the GPIO clock out of the sleep
     * 		mode. Once initialized, the user turns on the LED display by toggling
     * 		SW3-1 and turns off the LED display by toggling SW3-2. Once the LED
     * 		display has been disabled, the program finishes execution and exits.
     * 		The LED display consists of a sequential pattern of enabling each
     * 		LED (DS1-DS4) in an ascending order where a delay is implemented in
     * 		between each successive call to enable the next LED. This delay has
     * 		been implemented to ensure visibility of the LED display to the user.
     *
     *	-> SEE README IN PROJECT FOLDER FOR DETAILS AND STEPS TO RUN EXAMPLE <-
     *
     *---------------------------------------------------------------------------*/
    #include <GPIO_multi_led_interrupt_armL137.h>
    
    void arm_wfi(void);
    
    /*-----------------------------------------------------------------------------
     *
     * 				BEGIN EXAMPLE: GPIO_multi_led_interrupt_armL137
     * 
     *---------------------------------------------------------------------------*/
    void main (void)
    {
    	// Initialize OMAPL137 EVM (Configure User LEDs/Switches with the GPIO)
    	init_OMAPL137();
    	
    	// Enable Peripherals (GPIO)
    	enable_module_clocks();
    	
    	// Setup Peripherals; Run Example
    	if(modulesEnabled)
    	{
    		// Configure LEDs/switches as output/input; Enable GPIO interrupts
    		setup_GPIO();
    
    		LED_display();
    
    		// Map system interrupts to the ARM interrupt controller
    		setup_ARM_INTC();
    		
    		// Pending "Passing" Status of Setup, Run Example
    		GPIO_multi_led_interrupt_ARMexample();
    	}
    }/* End of main */	
    
    
    /*-----------------------------------------------------------------------------
     *
     * 						Internal Functions Defined
     * 
     *---------------------------------------------------------------------------*/
    static void init_OMAPL137 (void)
    {
    	// Intrinsic Function; Gain 'supervisor' privileges
    	_call_swi(ARM_PRIV_MODE_KEY);
    	
    	// Open Permissions to SYSCFG Registers
    	CSL_FINS(sysRegs->KICK0R, SYSCFG_KICK0R_KICK0, KICK0_KEY);
    	CSL_FINS(sysRegs->KICK1R, SYSCFG_KICK1R_KICK1, KICK1_KEY);
    	
    	// Configure DS1 - DS4 (User LEDs) with GPIO
    	CSL_FINST(sysRegs->PINMUX15, SYSCFG_PINMUX15_PINMUX15_11_8, GPIO0_12);
    	CSL_FINST(sysRegs->PINMUX15, SYSCFG_PINMUX15_PINMUX15_15_12, GPIO0_13);
    	CSL_FINST(sysRegs->PINMUX15, SYSCFG_PINMUX15_PINMUX15_19_16, GPIO0_14);
    	CSL_FINST(sysRegs->PINMUX15, SYSCFG_PINMUX15_PINMUX15_23_20, GPIO0_15);
    	
    	// Configure SW3-1 & SW3-2 (User Switches) with GPIO
    	CSL_FINST(sysRegs->PINMUX14, SYSCFG_PINMUX14_PINMUX14_27_24, GPIO0_8);
    	CSL_FINST(sysRegs->PINMUX14, SYSCFG_PINMUX14_PINMUX14_31_28, GPIO0_9);
    	
    	// Close Permissions to SYSCFG Registers
    	CSL_FINS(sysRegs->KICK0R, SYSCFG_KICK0R_KICK0, KICK_LOCK);
    }/* init_OMAPL137 */
    
    /*---------------------------------------------------------------------------*/
    
    static void enable_module_clocks (void)
    {
    	modulesEnabled = FALSE;
    	
    	// Ensure previous initiated transitions have finished 
    	if(check_psc_transition(CSL_PSC_1) == pscTimeout)
    		return;
    	
    	// Enable peripherals; Initiate transition
    	CSL_FINST(psc1Regs->MDCTL[CSL_PSC_GPIO], PSC_MDCTL_NEXT, ENABLE);
    	CSL_FINST(psc1Regs->PTCMD, PSC_PTCMD_GO0, SET);
    	
    	// Ensure previous initiated transitions have finished
    	if(check_psc_transition(CSL_PSC_1) == pscTimeout)
    		return;
    	
    	// Ensure modules enabled
    	if(check_psc_MDSTAT(CSL_PSC_1, CSL_PSC_GPIO, CSL_PSC_MDSTAT_STATE_ENABLE)
    			== pscTimeout)
    		return;
    	
    	modulesEnabled = TRUE;
    }/* enable_module_clocks */
    
    /*---------------------------------------------------------------------------*/
    
    static void setup_GPIO (void)
    {
    	// Configure DS1 - DS4 (User LEDs) as output
    	CSL_FINS(gpioRegs->BANK[GP0].DIR, GPIO_DIR_DIR12, CSL_GPIO_DIR_DIR_OUT);
    	CSL_FINS(gpioRegs->BANK[GP0].DIR, GPIO_DIR_DIR13, CSL_GPIO_DIR_DIR_OUT);
    	CSL_FINS(gpioRegs->BANK[GP0].DIR, GPIO_DIR_DIR14, CSL_GPIO_DIR_DIR_OUT);
    	CSL_FINS(gpioRegs->BANK[GP0].DIR, GPIO_DIR_DIR15, CSL_GPIO_DIR_DIR_OUT);
    	
    	// Turn off LEDs (Desired initial state)
    	gpioRegs->BANK[GP0].SET_DATA = (GP0P12 | GP0P13 | GP0P14 | GP0P15);
    	
    	// Configure SW3-1 & SW3-2 (User Switches) as input
    	CSL_FINS(gpioRegs->BANK[GP0].DIR, GPIO_DIR_DIR8, CSL_GPIO_DIR_DIR_IN);
    	CSL_FINS(gpioRegs->BANK[GP0].DIR, GPIO_DIR_DIR9, CSL_GPIO_DIR_DIR_IN);
    	
    	// Enable Bank 0 Interrupts
    	CSL_FINST(gpioRegs->BINTEN, GPIO_BINTEN_EN0, ENABLE);
    	
    	// Clear Bank 0 Falling/Rising Edge Triggers
    	gpioRegs->BANK[GP0].CLR_FAL_TRIG = BANK0_ALL_PINS;
    	gpioRegs->BANK[GP0].CLR_RIS_TRIG = BANK0_ALL_PINS;
    	
    	// Enable Interrupt Trigger on SW3-1 Rising/Falling Edge (Initial state)
    	gpioRegs->BANK[GP0].SET_RIS_TRIG = GP0P8;
    	gpioRegs->BANK[GP0].SET_FAL_TRIG = GP0P8;
    }/* setup_GPIO */
    
    /*---------------------------------------------------------------------------*/
    
    static void setup_ARM_INTC (void)
    {
    	// Reset AINTC
    	aintcRegs->ECR1 = AINTC_SYSINT_0_31_ALL;
    	aintcRegs->ECR2 = AINTC_SYSINT_32_63_ALL;
    	aintcRegs->ECR3 = AINTC_SYSINT_64_91_ALL;
    	aintcRegs->SECR1 = AINTC_SYSINT_0_31_ALL;
    	aintcRegs->SECR2 = AINTC_SYSINT_32_63_ALL;
    	aintcRegs->SECR3 = AINTC_SYSINT_64_91_ALL;
    	
    	// Assign GPIO ISR to GPIO System Interrupt
    	sysISRtbl[AINTC_EVENTID_GPIO_B0INT] = GPIO_BNK0_isr;
    	
    	// Assign the ISR Table Address to VBR
    	aintcRegs->VBR = (unsigned int) sysISRtbl;
    	
    	// Declare ISR Size (Function Pointer = 4 bytes)
    	aintcRegs->VSR = 0;
    	
    	// Map GPIO Bank 0 Interrupts to Channel 2
    	CSL_FINS(aintcRegs->CMR10, AINTC_CMR10_CHNL_NPLUS2, 2);
    	
    	// Enable GPIO Bank 0 Interrupts
    	CSL_FINS(aintcRegs->EISR, AINTC_EISR_INDEX, AINTC_EVENTID_GPIO_B0INT);
    	
    	// Enable IRQ Interrupts
    	CSL_FINS(aintcRegs->HIEISR, AINTC_HIEISR_INDEX, 1);
    	
    	// Enable Interrupts
    	CSL_FINS(aintcRegs->GER, AINTC_GER_ENABLE, 1);
    }/* setup_ARM_INTC */
    
    /*---------------------------------------------------------------------------*/
    
    static void LED_display (void)
    {
    	// Turn on LED DS1
    	gpioRegs->BANK[GP0].CLR_DATA = GP0P12;
    	dummyDelay(2000);
    	
    	// Turn on LED DS2
    	gpioRegs->BANK[GP0].CLR_DATA = GP0P13;
    	dummyDelay(2000);
    	
    	// Turn on LED DS3
    	gpioRegs->BANK[GP0].CLR_DATA = GP0P14;
    	dummyDelay(2000);
    	
    	// Turn on LED DS4
    	gpioRegs->BANK[GP0].CLR_DATA = GP0P15;
    	dummyDelay(2000);
    	
    	// Turn off LEDs
    	gpioRegs->BANK[GP0].SET_DATA = (GP0P12 | GP0P13 | GP0P14 | GP0P15);
    	dummyDelay(2000);
    }/* LED_display */
    
    /*---------------------------------------------------------------------------*/
    
    static void GPIO_multi_led_interrupt_ARMexample (void)
    {	
    	printf("Example: GPIO_multi_led_interrupt_armL137\n"
    		   "Scope: User toggles SW3-1 to begin a simple "
    		   "LED display and toggles SW3-2 to exit.\n"
    		   "Begin...\n\tWaiting for user to configure SW3-1...\n");
    	
    	runExample = 0;
    	
    	// Intrinsic Function to Enable Interrupts
    	_enable_IRQ();
    	
    	printf("Before ARM WFI\n");
    
    	arm_wfi();
    
    	printf("After ARM WFI\n");
    
    	// Wait for User to Configure SW3-1
    	while(!runExample);
    
    	printf("\tGPIO interrupt occured, begin LED toggle!\n"
    		   "\tWaiting for user to configure SW3-2...\n");
    
    	// Wait for User to Configure SW3-2; Toggle LEDs
    	while(runExample)
    		LED_display();
    	
    	// Intrinsic Function to Disable Interrupts
    	_disable_IRQ();
    	
    	printf("End of Example!\n\n");
    }/* GPIO_multi_led_interrupt_ARMexample */
    
    
    /*-----------------------------------------------------------------------------
     *
     * 							Interrupt Functions
     * 
     *---------------------------------------------------------------------------*/
    void GPIO_BNK0_isr (void)
    {
    	// Disable Interrupt Trigger on SW3-1 Rising/Falling Edge
    	gpioRegs->BANK[GP0].CLR_RIS_TRIG = GP0P8;
    	gpioRegs->BANK[GP0].CLR_FAL_TRIG = GP0P8;
    	
    	// runExample either Enabled or Disabled (Due to Logical AND Function)
    	runExample++;
    	runExample &= 0x01;
    	
    	// Enable Interrupt Trigger on SW3-2 Rising/Falling Edge
    	gpioRegs->BANK[GP0].SET_RIS_TRIG = GP0P9;
    	gpioRegs->BANK[GP0].SET_FAL_TRIG = GP0P9;
    	
    	// Acknowledge GPIO Bank 0 Interrupt
    	CSL_FINS(aintcRegs->SICR, AINTC_SICR_INDEX, AINTC_EVENTID_GPIO_B0INT);
    }/* GPIO_BNK0_isr */
    
    
    void arm_wfi(void)
    {
        //Titus : ARM WFI code
    
    		// Open Permissions to SYSCFG Registers
    	CSL_FINS(sysRegs->KICK0R, SYSCFG_KICK0R_KICK0, KICK0_KEY);
    	CSL_FINS(sysRegs->KICK1R, SYSCFG_KICK1R_KICK1, KICK1_KEY);
    
    
        asm ( "    mcr p15, #0, r3, c7, c0, #4\n\t" );
    
    
        //Here, code get stuck due to WFI and it resume when GPIO interrupt (SW3:0) raised.
    
    	// Close Permissions to SYSCFG Registers
    	CSL_FINS(sysRegs->KICK0R, SYSCFG_KICK0R_KICK0, KICK_LOCK);
    
    }
    

  • Hi Mukul and Titus,

    Thank you very much for the guidance and for the ARM WFI example.  With your help I now have a solution working that meets my standby power goals.

    It was easy to do this in UBL before Linux runs.  My standby micro controls reset to the DA830 and also controls a GPIO to tell the DA830 whether to boot into normal or low power mode.

    The DSP UBL is modified to do the following:

    1. enable the GPIO LPSC
    2. read the GPIOs to detect the desired power state
    3. start the ARM
    4. if the GPIO state indicates standby is requested:
    5. write 0x00015555 to the PDCCMD register
    6. asm( "IDLE" );
    7. (loop on 5 and 6 in case anything goes wrong; I haven't tried it without the loop, nor have I tried it yet from an ISR)

    The ARM UBL is modified to do the following: 

    1. read the GPIOs to detect the desired power state.  If the GPIOs indicate that standby is requested:
    2. call DEVICE_disable_DSP(), which executes the ARM side of the DSP shutdown sequence described in the technical reference manual.  It waits until the status bits indicate completion of the transition.
    3. put the SDRAMs into self refresh mode with MCLK stop enabled
    4. call DEVICE_LPSCTransition to put power domains (GPIO, EMIFB, and others) into SWRSTDISABLE mode
    5. unlock the KICK registers, put the PLL into bypass mode, and power it down
    6. enter WFI mode with asm ( "    mcr p15, #0, r3, c7, c0, #4\n\t" );

    At this point the device is shut down.  However the power consumption on my board was still 200 mW above my target.  I have not yet taken the time to experiment with what other domains I might be able to shut down or to move the DSP's IDLE instruction into an ISR as described in the documentation.  Instead, I discovered that if my micro now asserts RESET again and holds it low, the board is held in a consistent low power state that is 125 mW below my target.  This is good enough to satisfy the needs of the project.

    When it's time to bring up the DA830 for normal operation, the micro switches the GPIO that signals power state, then releases reset.  The 830 boots normally.

    Regards,

    Debora

  • An addendum:

    After further experimentation I find that the ARM WFI instruction asm ( " mcr p15, #0, r3, c7, c0, #4\n\t" ); is not having any effect on the power.
    The technical reference manual says in section 10.6.1 that this instruction only works if the ARM is in supervisor mode. But I have to assume that the ARM is in a privileged mode when executing UBL because other parts of the existing UBL code read the BOOTCFG register and write to the KICKR registers and the PINMUX registers.

    Is there some other reason why the WFI instruction would fail to have an effect on the current draw? If WFI worked, I might be able to avoid having to hold the part in reset.
  • Debora
    Did you put the PLLs in bypass mode? Did you put the SDRAM in power down/self refresh mode? Did you ensure that all peripherals are clocked off via PSC?

    If you are only doing ARM WFI , the power savings for a 300 MHz @ 1.2V CVDD operation is going to be in the range of ~14 mW
    You can deduce this from the power estimation model/xls
    processors.wiki.ti.com/.../OMAP-L137_Power_Consumption_Summary
    Look at the ARM row and it will you the power for ARM running high (Dhrystone), low, ARM WFI , and ARM clock disabled

    If you are measuring the at the input or output of the total board, I wonder if you will not see significant overall drop , just doing WFI.

    If you are getting consistent results now , between run to run and board to board while holding the device in RESET , perhaps its ok, but again we don't characterize power while the processor is in reset and I don't really know what might be causing the variability previously (intuitively you are now with a better power down procedure are putting the processor in a more graceful software state, prior to asserting reset and that might be helping).

    Hope this helps.
    Regards
    Mukul
  • Hi Mukul,

    Thanks for your continued support.

    Yes, I put the PLLs in bypass mode. If I comment out the PLL bypass code, I see a 275 mW increase. (Note that this is measured at the board's 5V input so it includes inefficiencies in the switching regulators.)

    I put the SDRAMs in self-refresh mode. I did not measure the difference with the SDRAM self-refresh code commented out, but will give it a try.

    I put the following domains into SWRSTDISABLE mode using the DEVICE_LPSCTransition() function: EMIFA, SPI0, MMCSD0, UART0, USB0, USB1, UHPI0, EMAC, EMIFB, McASP0, McASP1, McASP2, SPI1, I2C1, UART1, UART2. I did not measure the difference with this code commented out.

    But with the ARM WFI line commented or uncommented, the result is the same.

    Regards,
    Debora
  • Follow-up

    Commenting out only the PLL bypass code makes a big difference, 275 mW
    Commenting out only the SDRAM self-refresh code and the LPSC EMIFB SwRstDisable transition makes a very small difference, about 40 mW
    Commenting out only the LPSC SwRstDisable transitions for all the domains listed above makes a tiny difference, about 15 mW
    Commenting out only the ARM WFI line makes no difference I can detect.

    But the workaround is to hold the part in reset, which makes an additional difference of about 295 mW. This gets the job done; I was just curious whether I was missing something else obvious.

    Thanks.

    Regards,
    Debora
  • Debora,
    Can you please tabulate these results with the exact total power and power savings?
    1) What is the total power with PLL bypass + SDRAM self refresh + LPSCs + ARM WFI
    2) What is the total power with above + Reset

    From your emails it appears that total power goes down by another 295 mW - which is not jiving well with what is the total power of the DA8x , as in state 1, if done right , the total power of the DA8x device should be in ~ 70-80 mW range.

    So i dont know if holding it in reset is causing some other on board components shutting down etc.

    Regards
    Mukul
  • Hi Mukul,

    Your comment gave me the insight I needed to find the problem.

    What I had not kept in mind is that the RBL sets the pinmux registers from the boot flash before UBL runs. In my modified UBL I was careful to set the peripheral power domains to SwRstDisable, but didn't think of restoring all the pinmux registers to their default state.

    I added this little bit of code after doing the LPSC transitions and before turning off the PLL:

    for (i = 0; i < 20; i++)
    DEVICE_pinmuxControl(i,0xFFFFFFFF,0);

    And now the board consistently powers down to just 15 mW above what I was measuring with it held in reset. So there is now no need to hold reset. Must be that the pins are somehow affecting the power consumption of the SDRAMs or flash or whatever if they are not restored to their reset pinmux state.

    Thank you for all your help on this!

    Regards,
    Debora
  • Thanks for the update. Glad to this working.

    Regards

    Mukul

  • Hi Mukul,

    May I bother you with one more question?  Does it matter to the health of the chip which order I power down the LPSCs versus set the PINMUX registers to 0?

    When I'm shutting down the GPIO registers should still be at their reset defaults (inputs).  The EMIFB,  SPI0, UART2, and possibly others, however, would have been configured by the boot code.

    Debora

  • I would say disable the clocks first and then configure the pinmux as needed to tri state the ios etc. Minor note, on your disabling the clocks - I would recommend just using LPSC disable instead of SwrstDisable. You will see in our PSC chapter that SWRSTDISABLE is typically not a state we expect software to invoke.

    Since you are not powering down the supplies to the device, I am not sure if there should be any concerns to reliability (assuming that is what you meant by health of the device).

    It was unclear how much difference you were seeing on reset vs w/o IO tristate vs your latest tristate configuration (which is now 15 mW higher than when held in reset). Technically when you held the device in reset, it should've been tristating the IOs too. Do you know if it is a specific set of IOs that is making your results more consistent or closer to the device in reset power?

    Regards
    Mukul