AM62x MCU+ SDK  10.01.00
Low power mode implementation of remote cores

Introduction

Linux running on A53 core can load the firmware to the remote cores. MCU M4F core incase of AM62X. Refer Linux Academy for AM62X for more details on how to boot the remotecores. This section explains how to add support for low power mode aware firmware on the remotecore.

Implementing low power mode aware remotecore firmware

  • Suspend task is created to enable graceful suspend in low power mode.
  • An IPC message is sent to remotecore by Remoteproc driver running on linux to query about the next state that core is going to enter.
  • To receive and handle IPC messages, register a callback as shown below.
/* Register a callback for the RP_MBOX messages from the Linux remoteproc driver*/
  • On the callback, post the suspend thread.
    volatile uint8_t gbSuspended = 0u;
    volatile uint8_t gbSuspendRemotecoreID = 0u;
    void ipc_rp_mbox_callback(uint16_t remoteCoreId, uint16_t clientId, uint32_t msgValue, void *args)
    {
    {
    if (msgValue == IPC_NOTIFY_RP_MBOX_SUSPEND_SYSTEM) /* Suspend request received from linux during LPM suspend */
    {
    gbSuspendRemotecoreID = remoteCoreId;
    SemaphoreP_post(&gLpmSuspendSem);
    }
    }
    }
  • On the suspend thread, query the next state from device manager.
uint8_t nextHostState;
/* Wait for suspend from linux */
{
DebugP_log("[IPC RPMSG ECHO] Failed to get next system state. Canceling suspend.\r\n");
continue;
}
DebugP_log("[IPC RPMSG ECHO] Next MCU mode is %d\r\n", nextHostState);
  • The response can be OFF or ON.

ON - MCU only LPM

Attention
This Low power mode is supported only by MCU remote cores.
  • ON state will be responded. As the core has to stay ON, send SUSPEND_AUTO to remoteproc driver.
gbSuspended = 1u;
/* Print before sending ACK, otherwise IO isolation is enabled while printing */
DebugP_log("[IPC RPMSG ECHO] Suspend request to MCU-only mode received \r\n");
DebugP_log("[IPC RPMSG ECHO] Press a single key on this terminal to resume the kernel from MCU only mode \r\n");
lpm_mcu_wait_for_uart();
gbSuspended = 0u;
  • MCU core then waits for key to be pressed at MCU UART. UART callback has to be enabled for resume support from MCU UART.
  • Wait for key to be pressed on MCU UART / any other system interrupt.
while (gNumBytesRead == 0u && gbSuspended == 1u)
{
}

Wakeup from MCU UART

  • If the key is pressed on MCU UART, the callback sets gNumBytesRead.
  • The remotecore performs IPC to trigger system resume.
if (gNumBytesRead != 0)
{
DebugP_log("[IPC RPMSG ECHO] Key pressed. Notifying DM to wakeup main domain\r\n");
/* Wait for resuming the main domain */
DebugP_log("[IPC RPMSG ECHO] Main domain resumed due to MCU UART \r\n");
}
  • The linux resumes and remoteproc sends ECHO_REQUEST message to remote core.
  • On the callback, post the resume thread.
void ipc_rp_mbox_callback(uint16_t remoteCoreId, uint16_t clientId, uint32_t msgValue, void *args)
{
{
if (msgValue == IPC_NOTIFY_RP_MBOX_ECHO_REQUEST) /* This message is received after resuming from the MCU only LPM. */
{
gbSuspended = 0u;
if (gNumBytesRead != 0u)
{
/* post this only for MCU UART Wakeup */
SemaphoreP_post(&gLpmResumeSem);
}
}
}
}
  • Remote core is out of low power mode.

Wakeup from any other wakeup source

  • The linux resumes and remoteproc sends ECHO_REQUEST message to remote core.
  • On the callback, clear the gbSuspended variable.
  • Cancel UART Read and remote core exits low power mode.
if (gbSuspended == 0u)
{
UART_readCancel(gUartHandle[CONFIG_UART0], &trans);
DebugP_log("[IPC RPMSG ECHO] Main domain resumed from a different wakeup source \r\n");
}

OFF - Deep Sleep / IO Only plus DDR LPM

  • OFF state will be responded. As the core has to be shutdown, send SUSPEND_ACK to remoteproc driver to initiate shutdown of this core.

This is implemented on IPC RP Message Linux Echo

status
uint32_t status
Definition: tisci_lpm.h:1
IpcNotify_registerClient
int32_t IpcNotify_registerClient(uint16_t localClientId, IpcNotify_FxnCallback msgCallback, void *args)
Register a callback to handle messages received from a specific remote core and for a specific local ...
DebugP_shmLogWriterResume
void DebugP_shmLogWriterResume(void)
Resumes shared memory log writer for this core.
NULL
#define NULL
Define NULL if not defined.
Definition: csl_types.h:100
SOC_triggerMcuLpmWakeup
void SOC_triggerMcuLpmWakeup()
Generates the MCU IPC interrupt to DM R5 to wakeup the main domain from MCU only LPM mode.
IpcNotify_sendMsg
int32_t IpcNotify_sendMsg(uint32_t remoteCoreId, uint16_t remoteClientId, uint32_t msgValue, uint32_t waitForFifoNotFull)
Send message to a specific remote core and specific client ID on that remote core.
IPC_NOTIFY_RP_MBOX_ECHO_REQUEST
@ IPC_NOTIFY_RP_MBOX_ECHO_REQUEST
Definition: ipc_notify.h:143
SystemP_WAIT_FOREVER
#define SystemP_WAIT_FOREVER
Value to use when needing a timeout of infinity or wait forver until resource is available.
Definition: SystemP.h:83
DebugP_log
#define DebugP_log(format,...)
Function to log a string to the enabled console.
Definition: DebugP.h:227
IPC_NOTIFY_RP_MBOX_ECHO_REPLY
@ IPC_NOTIFY_RP_MBOX_ECHO_REPLY
Definition: ipc_notify.h:144
UART_readCancel
int32_t UART_readCancel(UART_Handle handle, UART_Transaction *trans)
Function to perform UART canceling of current read transaction.
SystemP_SUCCESS
#define SystemP_SUCCESS
Return status when the API execution was successful.
Definition: SystemP.h:56
IPC_NOTIFY_RP_MBOX_SUSPEND_CANCEL
@ IPC_NOTIFY_RP_MBOX_SUSPEND_CANCEL
Definition: ipc_notify.h:149
IPC_NOTIFY_CLIENT_ID_RP_MBOX
#define IPC_NOTIFY_CLIENT_ID_RP_MBOX
Client ID used for remoteproc (RP_MBOX) related messages, this client ID should not be used by other ...
Definition: ipc_notify.h:71
IPC_NOTIFY_RP_MBOX_SUSPEND_SYSTEM
@ IPC_NOTIFY_RP_MBOX_SUSPEND_SYSTEM
Definition: ipc_notify.h:147
SemaphoreP_post
void SemaphoreP_post(SemaphoreP_Object *obj)
Post a semaphore object or unlock a mutex.
IPC_NOTIFY_RP_MBOX_SUSPEND_AUTO
@ IPC_NOTIFY_RP_MBOX_SUSPEND_AUTO
Definition: ipc_notify.h:146
IPC_NOTIFY_RP_MBOX_SUSPEND_ACK
@ IPC_NOTIFY_RP_MBOX_SUSPEND_ACK
Definition: ipc_notify.h:148
Sciclient_lpmGetNextHostState
int32_t Sciclient_lpmGetNextHostState(uint32_t timeout, uint8_t *hostState)
Message to get the next host state.
SemaphoreP_pend
int32_t SemaphoreP_pend(SemaphoreP_Object *obj, uint32_t timeToWaitInTicks)
Pend on a semaphore object or lock a mutex.