AM64x MCU+ SDK  09.02.00
Graceful shutdown of remote cores from Linux

Introduction

Linux running on A53 core can load the fimrware to the remote cores. Refer Linux Academy for AM64X for more details on how to boot the remotecores. This section explains how to add support for graceful shutdown on the remotecore.

Implementing graceful shutdown on remotecore

  • When the following command is used on the Linux to shutdown the remotecore, an IPC message is send to the remote core before shutting it down.
echo stop > /sys/class/remoteproc/remoteproc0/state
  • To receive and handle this IPC message, register a callback as shown below.
/* Register a callback for the RP_MBOX messages from the Linux remoteproc driver*/
IpcNotify_registerClient(IPC_NOTIFY_CLIENT_ID_RP_MBOX, &ipc_rp_mbox_callback, NULL);
  • On the callback unblock the RPMessage for all the RPMsg objects used in the code.
    volatile uint8_t gbShutdown = 0u;
    volatile uint8_t gbShutdownRemotecoreID = 0u;
    void ipc_rp_mbox_callback(uint16_t remoteCoreId, uint16_t clientId, uint32_t msgValue, void *args)
    {
    if (clientId == IPC_NOTIFY_CLIENT_ID_RP_MBOX)
    {
    if (msgValue == IPC_NOTIFY_RP_MBOX_SHUTDOWN) /* Shutdown request from the remotecore */
    {
    gbShutdown = 1u;
    gbShutdownRemotecoreID = remoteCoreId;
    RPMessage_unblock(&gIpcRecvMsgObject[0]);
    RPMessage_unblock(&gIpcRecvMsgObject[1]);
    }
    }
    }
  • On the main thread where the IPC is happening, break all the loops when gbShutdown == 1
/* wait for messages forever in a loop */
while(1)
{
/* set 'recvMsgSize' to size of recv buffer,
* after return `recvMsgSize` contains actual size of valid data in recv buffer
*/
recvMsgSize = IPC_RPMESSAGE_MAX_MSG_SIZE;
status = RPMessage_recv(pRpmsgObj,
recvMsg, &recvMsgSize,
&remoteCoreId, &remoteCoreEndPt,
if (gbShutdown == 1u)
{
break;
}
/* send ack to sender CPU at the sender end point */
status = RPMessage_send(
recvMsg, recvMsgSize,
remoteCoreId, remoteCoreEndPt,
}
  • Then follow the below sequence to go to WFI
    • Close all the drivers used
    • Send acknowledgement to Linux core that the core is ready for shutdown
    • Deinit system (It will disable the interrupts and stops the tick timer)
    • Go to WFI / IDLE
/* Close the drivers */
Drivers_close();
/* ACK the suspend message */
IpcNotify_sendMsg(gbShutdownRemotecoreID, IPC_NOTIFY_CLIENT_ID_RP_MBOX, IPC_NOTIFY_RP_MBOX_SHUTDOWN_ACK, 1u);
/* Deinit System */
System_deinit();
/* For ARM R and M cores*/
__asm__ __volatile__ ("wfi" "\n\t": : : "memory");

This is implemented on IPC RP Message Linux Echo

RPMessage_recv
int32_t RPMessage_recv(RPMessage_Object *obj, void *data, uint16_t *dataLen, uint16_t *remoteCoreId, uint16_t *remoteEndPt, uint32_t timeout)
Blocking API to wait till a message is received from any CPU at the specified local end point.
RPMessage_unblock
void RPMessage_unblock(RPMessage_Object *obj)
Unblocks RPMessage_recv, for the input object, if it is blocked waiting on messages and users want to...
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 ...
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.
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
RPMessage_getLocalEndPt
uint16_t RPMessage_getLocalEndPt(const RPMessage_Object *obj)
Return local end point of a RPMessage_Object.
SystemP_SUCCESS
#define SystemP_SUCCESS
Return status when the API execution was successful.
Definition: SystemP.h:56
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:177
RPMessage_send
int32_t RPMessage_send(void *data, uint16_t dataLen, uint16_t remoteCoreId, uint16_t remoteEndPt, uint16_t localEndPt, uint32_t timeout)
Send a message to a remote core at a specified remote end point.