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.

DM368 can not jump back to C code after deep sleep

Hi,

If I comment out lines about deep sleep, the assembler code returns well. But when DM368 fall deep sleep and back, system will halt. I add some lines to light a LED after recover from deep sleep and it works. I think system stopped when it go back to C code.

The original PM patch comes here: http://linux.omap.com/pipermail/davinci-linux-open-source/2008-January/004918.html

ENTRY(davinci_cpu_suspend)
      stmfd sp!, {r0 - r12, lr}      //  save registers on stack

tci_loop:
      mrc     p15, 0, r15, c7, c14, 3  //  test clean and invalidate DCache
      bne     tci_loop

      mov   r0, #0x0           //  clear for mrc call
      mcr   p15, 0, r0, c7, c10, 4   //  drain write buffer,
                               //  hope SDR/DDR finished
      nop
      nop

       /* ToDo: Currently, we only switch SDRAM to self refresh here. To
       *       save even more power, we should gate input clocks to the
       *       memory controller module off. See TI document SPRUE22C
       *       section 2.15 "Power management" for more details.
       */

       /* Switch SDRAM to selfrefresh */
      ldr     r0, ddr2_ctrl_base
      ldr     r1, self_refresh
      ldr     r2, [r0]
      orr     r2, r2, r1
      str     r2, [r0]

       /* ToDo: Wait T_CKE+1 cycles */
      mov   r2, #0x1000
loop1:
      subs  r2, r2, #0x1
      bne   loop1

       /* Sleep */
#if 1
      ldr   r3, system_ctrl_base
      ldr   r4, [r3, #0x4c]
      orr   r4, r4, #DEEPSLEEP_SLEEPENABLE_BIT
       /* System goes to sleep beyond after this instruction */
      str   r4, [r3, #0x4c]

      mov   r2, #1
wait_for_sleep:
      nop
      ldr   r4, [r3, #0x4c]
      and   r4, r4, r2, LSL #30
      cmp   r4, #0
      beq   wait_for_sleep

      ldr   r4, [r3]
      bic   r4, r4, #DEEPSLEEP_SLEEPENABLE_BIT
      str   r4, [r3]
#endif
       /* Exit SDRAM selfrefresh, r0 and r1 should be still valid */
      ldr     r2, [r0]
      bic     r2, r2, r1
      str     r2, [r0]

       /* ToDo: Wait T_SXNR+1 and/or T_SCRD+1 cylces */
      mov   r0, #0x1000
loop2:
      subs  r0, r0, #0x1
      bne   loop2

#if 0 // light LED, it works after recover from deep sleep
      ldr   r0, gpio_ctrl_base
      mov   r1, #0
      mov   r2, #1
      orr   r1, r2, LSL #29
      str   r1, [r0, #0x44]
#endif
       /* Resume*/
      ldmfd sp!, {r0 - r12, pc}      //  restore regs and return
  • Kenneth,

    Have you enabled a print or glowing LED after the davinci_cpu_suspend() call? If you can use a debugger, you can find out where exactly its going out from the routine.

  • Hi,

    We are having exact the same problem, when running almost identical code.

    In our setup PLL's and DDR mem are not modified (self refresh).

    We have used JTAG and found that the first instruction executed from DDR memory, after exit from DEEPSLEEP fails.

    Any solution to this problem?

    Best regads

    Jakob

  • Jakob,

    Which is the first instruction that you are running after sleep? What is the state of the processor when it fails?

    Are you running the code from IRAM? If not, you'll have to make sure that the i-cache is NOT flushed/invalidated before sleep.

  • Hi Renjith,

    Thank you very much for your reply, hope we can get this working.

    The ARM core is executing the following code from IRAM in ARM-mode:

     

                                 <snip>

                /* Go to deep sleep */

                ldr         ip, [r4]

                orr         ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT

                /* System goes to sleep beyond after this instruction */

                str         ip, [r4]

    zzz:

                ldr         ip, [r4]

                tst ip, #DEEPSLEEP_SLEEPCOMPLETE_BIT

                beq zzz

                /* Wake up from sleep */

     

                /* Clear sleep enable */

                ldr         ip, [r4]

                                 <snip>

     

    I don't think the ARM core stops executing during DEEPSLEEP?

    Note the code is not using "wait-for-interrupt" yet, but simply polls the SLEEP_COMPLETE bit. Please observe that execution continues just fine inside the IRAM.

    At the end of the IRAM routine, execution "returns" to DDR memory using the instruction:

                                 <snip>

                /* Restore registers and return */

                ldmfd   sp!, {r0-r12, pc}

     

    Jumps back to code in DDR ram (observed by inspecting pc after the load). I therefore conclude that the load-instruction succeeds. However the first instruction in DDR ram fails.

    Disassembly of the returned-to C-routine looks as follows:

                mov         lr, pc                   /* Setup for "return", this magically lets lr=pc+8 */

                ldr         pc, [r4, #4]             /* Jump to IRAM (function-pointer) */

                ldr         r3, [pc, #144]           /* Returned-to instruction, execution of this instruction fails (execution jumps to exception-vector) */

                ldr         r2, [r3, #76]            /* Never reached */

     

    Final observation: If either the DEEPSLEEP bit isn't set, or the GPIO0 is not toggled low, and the "zzz" loop is simply skipped (So system never really sleeps), execution resumes from DDR ram just fine, and Linux is up-and-running again.

     

     

  • Jakob,

    Is DDR up from self-refresh mode when you execute the first instruction?

  • Hi Renjith,

     

    Not sure if DDR is "up", is there a statusbit indicating this?

    The DDR PLL is not stopped in my test (X2_CLK), so its clock ought to remain stable even if DEEPSLEEP bit is set, right? The documentation is a little vague on this IMHO.

     

    Regarding DDR, the code executed from IRAM does the following:

    0) caches are flushed

    1) SDCR.SRPD bit is cleared and SDCR.LPMODEN is set

    2) SDCR.MCLKSTOPEN bit is set

    3) DDR2 LPSC is disabled

    4) System enters DEEPSLEEP

    5) DDR2 LPSC is re-enabled

    6) SDCR.MCLKSTOPEN is cleared

    7) SDCR.LPMODEN is cleared

    execution then "returns" to DDR a few instructions later.

     

    However, according to SPRUF12 section 2.9:

    "if a request for a memory access is received, the DDR2/mDDR memory controller services the memory access request"

    From this I concluded, that DDR memory would be accessible even if the controller is in self-refresh mode …

     

    Best regards,

    Jakob

  • Jakob,

    Sorry for the delayed response. What is the state of the processor when it fails? Is it in Abort mode? If so, you need to find out whether its pretetch abort or data abort. I feel that instruction fetch itself has failed.

  • Hi Jakob

    Did you ever manage to get deepsleep working on the dm365.

    I am also trying (for quite some time now) to get deep sleep working however, I am unable to wake up from deep sleep. The steps I followed are:

    • Put cpu pll into bypass (clear pllensrc and pllen in pllctl register)
    • Power down cpu pll (set pllpwrdwn in pllctl register)
    • Set deepsleep wakeup delay to 128
    • In SRAM:
      • Put ddr in self refresh (clear srpd and set lpmoden of sdrcr register)
      • Stop MCLK (set mclkstopen of sdrcr)
      • Disable DDR2 LPSC (Module 13 of PSC modules (table 39 of SPRUFG5A))
      • Disable clock to DDR PHY (clear plldiven of plldiv7 register)
      • Go into deep sleep (set deep sleep enable bit)
      • Poll sleep complete bit of deep sleep register (while in this loop the  a micro controller causes gpio0 to transition from high to low)
      • I am having an issue at this point as I am unable to wake up from sleep. I am using the micro controller to transition the gpio0 from low to high, which according to SPRUFG5A should wake it up from deep sleep.
      • If woken up, then remove deep sleep enable (clear deep sleep enable)
      • Enable clock to DDR PHY
      • Enable DDR LPSC
      • Start MCLK
      • Take ddr out of self refresh
    • Power up cpu pll (clear pllpwrdwn in pllctl)
    • Put cpu pll in bypass mode
    • Reset cpu pll
    • Do pllsecctl sequence 
    • Poll the lock bits of pllc2_config register 
    • Continue as normal...

    If I remove the step to poll the deep sleep complete bit in the deep sleep register, the arm does not receive the transition of gpio0 from high to low and hence does not go into deep sleep. In this case, the program continues as normal and restarts everything as expected.

    Any help/tips will be much appreciated.

    Arshad

  • As you know, davinci_cpu_suspend() is run in sram. After wakeup it can control LEDs within the block. But when jump out, the CPU halt. I have an xds560, I don't know how to debug Linux kernel. Someone tell me xds560 can not debug Linux.

  • Hey Everyone,

    Does anyone have a working link to the OP's mentioned patch: linux.omap.com/.../004918.html ? I keep getting 403 errors when trying to access the URL.

    Thanks,
    Dave
  • Has anyone resolved this issue? I am stuck in the same place right now. If I comment out the deep sleep enable and wait section it comes back fine, but after deep sleep it will run through the remainder of the assembly code in I-RAM then just stop. I have an LED on as the first instruction when returning to code in DDR2 RAM, and the LED never comes one. But if i do NOT flush the i-cache then the LED comes on, but i have a feeling that is just because it will run the code left in i-cache and then after that it just locks up because nothing else seems to happen after the LED comes on in that case.

    Just wondering if anyone has been able to get the thing to run from DDR RAM again after exiting deepsleep? I will try hooking in a debugger next, but i don't really know what that will tell me. Guess we will see.
  • I was finally able to get Deep Sleep working for the DM368.  See my other E2E post for the final solution/patch:  https://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/100/p/448309/1644628#1644628