i.MX8M Nano Cortex-M7 is inactive in deep sleep

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX8M Nano Cortex-M7 is inactive in deep sleep

2,599 Views
l_madej
Contributor II

Dear Support Team,

I do not know how to force the system to keep C-M7 core active after entering suspend-to-RAM (deep sleep) in Linux. Could you please advise me what shall I configure to achieve the goal?

I'm using 8MNANOLPD4-EVK with image generated by latest Yocto release.
To confirm feasibility of my idea (waking-up Linux with C-M7 after reception of valid data from a I2C sensor) I have developed simple program for the C-M7 based on examples provided within a SDK.

Right now the C-M7 SW blinks LED and prints some strings on UART4 console periodically. It runs from the TCM. After calling:

"echo mem > /sys/power/state". 

Linux enters deep-sleep as expected but C-M7 core is also stopped (LED does not blink, no new output on UART4) but I need to keep it running. After restoring the system with ON/OFF button C-M7 SW continues its operation (does not reset, simply continues from where it ends).

I have went thorough Refference Manual and I did not found answer there so far. I have checked:

  • RDC configuration (if CM7 domain is 1),
  • CCM configuration for GPIO and UART (CCGR registers -> if value 3 is assigned for domain 1),
  • GPC_LPCR_M7 register (if something changes after setting of CPU_CLK_ON_LPM bit).

What is the missing puzzle here?

 

Thank you and kind regards,
Łukasz

Labels (2)
0 Kudos
Reply
8 Replies

937 Views
martmanmtx
Contributor I

not sure, but that will set down the cpu frequency of M7 from 800MHz to 24MHz, right?

 

I tried to uses s2idle instead of deep.that keeps M7 core running but as far does not save as much power (on my propietary iMX8MP board 500mW for s2idle compared to 1500mW in deep sleep).

0 Kudos
Reply

2,581 Views
l_madej
Contributor II

Hi Igor,

Thank you for quick reply. I went through application note and patches in SW pack and I recon that missing part is ATF code modification.
Am I right?

Unfortunately the patches are for older release and for different platform (imx8mq) and will not apply to platform imx8mn in current BSP.
Moreover part of fixes provided within a patch (like MU interrupts activation) are already included in the latest BSP.
Last but not least not all registers accessed by ATF are documented in Refference Manual (e.g. SRC_GPR9 0x30390094)

Could you please provide direct guidelines what shall be modified in the ATF to keep M7 active in sleep?

Thank you,
Łukasz

0 Kudos
Reply

2,551 Views
waseem
Contributor I

Hi,

 

I had this problem, but found a way around it Writing my solution here. Hope it works for you.

 

1. Patches basically enable or keep running PLL clocks when linux sleeps. If you manage to add them, it is good, but if you don't manage to add the pacthes mentioned in the application note, you could try using 24MHz clock instead of PLL for M7. This clock is not diabled by linux (I have a development board and Yocto/Linux variant from Digi)

2. In addition to switching M7 to 24 MHz oscillator, you need to run/enable ALL PLLs from M7 side. Use this application note and reference code from the application note to see what I mean by enabling ALL PLLs. https://www.nxp.com/docs/en/application-note/AN13201.pdf

4. If you not using RDC and assign peripherals to specific domains, linux kernel will crash. E.g. if UART4 is used by M7, you must disable the UART4 in linux device tree.

3. Finally you also need ServiceBusy (0x5555U) and other macros mentioned at page 4 of the applciation note above (AN13201).

Start with UART at M7 first. Implement the RDC assignment and disable the UART in the linux device tree. Aftewards, you can add more peripherals at M7 side and remove them from linux device tree.

 

-Waseem

0 Kudos
Reply

2,507 Views
l_madej
Contributor II

Hi Waseem,

Thank you for the input. I will study your hints.

Regards,
Łukasz

 

0 Kudos
Reply

1,859 Views
arnoutdiels
Contributor III

The explanation of wasseem is overkill for the basic scenario.

As https://www.nxp.com/docs/en/application-note/AN13400.pdf explains, there are 2 ways of doing this.

Option 1 does not require any changes to the ATF, manual PLL enabling etc, and is way easier. It just requires you to select the 24Mhz oscillator clock, which is not disabled by default in DSM. 

Option 2 requires you to do all that stuff in SW, but thats alot of work.

 

Just tested here with an IMX8MP, and modifying the default "hello world" application (which echoes back UART characters) still keeps echoing even with the A53 in suspend, after doing the patch:

```

hello_world/clock_config.c

- CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll1); /* switch cortex-m7 to SYSTEM PLL1 */
+ CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M); /* switch cortex-m7 to SYSTEM PLL1 */

 

-
- CLOCK_SetRootMux(kCLOCK_RootUart2, kCLOCK_UartRootmuxSysPll1Div10); /* Set UART source to SysPLL1 Div10 80MHZ */
+ CLOCK_SetRootMux(kCLOCK_RootUart2, kCLOCK_UartRootmuxOsc24M); /* Set UART source to SysPLL1 Div10 80MHZ */

 

hello_world/board.c

- uint32_t uartClkSrcFreq = BOARD_DEBUG_UART_CLK_FREQ;
+ uint32_t uartClkSrcFreq = 24*1000*1000;

```

 

0 Kudos
Reply

2,589 Views
igorpadykov
NXP Employee
NXP Employee

Hi Lukasz

 

one can look at M7 low power demo (../demo_apps/sai_low_power_audio) included in

SDK available on  https://mcuxpresso.nxp.com/en/welcome

Additional details can be found in AN12195   Implement Low-Power Audio on i.MX8M

AN12195SW

 

Best regards
igor

0 Kudos
Reply

1,752 Views
k_specka
Contributor II

I'm using the imx8mn evk and trying to get the M7 running when A53 is suspended.
Using some logging and a blinking LED at gpio to see it running.

Actual after 'echo mem > /sys/power/state' the board goes to suspend and led and logging stops on M7, after resume it is running again.

As we don't need high performance AN13400 4.3.1 to set the 24MHz should be OK.

Changed the following parts of the config like seen above (using uart4 instead of 2):

MCUXpresso SDK /core/boards/evkmimx8mn/board.c
@ BOARD_InitDebugConsole
//uint32_t uartClkSrcFreq = BOARD_DEBUG_UART_CLK_FREQ;
uint32_t uartClkSrcFreq = 24*1000*1000;

MCUXpresso SDK /core/boards/evkmimx8mn/clock_config.c
@ BOARD_BootClockRUN

// CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxSysPll3); /* switch cortex-m7 to SYSTEM PLL3 */
CLOCK_SetRootMux(kCLOCK_RootM7, kCLOCK_M7RootmuxOsc24M); /* stay on PLL1 for suspend */

// CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxSysPll1Div10); /* Set UART source to SysPLL1 Div10 80MHZ */
CLOCK_SetRootMux(kCLOCK_RootUart4, kCLOCK_UartRootmuxOsc24M); /* Set UART source to SysPLL1 Div10 80MHZ */

Is there something I'm missing? Is a kernel patch needed for this? Much code is unavailable as it was on codeaurora...

0 Kudos
Reply

1,699 Views
k_specka
Contributor II

Found the problem, got following code missing in my main c file.

    /*
     * In order to wakeup M7 from LPM, all PLLCTRLs need to be set to "NeededRun"
     */
    for (i = 0; i != 39; i++)
    {
        CCM->PLL_CTRL[i].PLL_CTRL = kCLOCK_ClockNeededRun;
    }
    CLOCK_SetRootMux(kCLOCK_RootGpt1, kCLOCK_GptRootmuxOsc24M); /* Set GPT source to Osc24 MHZ */
    CLOCK_SetRootDivider(kCLOCK_RootGpt1, 1U, 1U);
0 Kudos
Reply