285 lines
8.9 KiB
C
285 lines
8.9 KiB
C
/** \file
|
|
* \brief This file implements messaging using inter-processor communication (IPC).
|
|
*
|
|
* \see https://community.cypress.com/thread/36182.
|
|
*/
|
|
|
|
/**
|
|
* \ingroup CONSOLE
|
|
*/
|
|
|
|
/* Include Files */
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <project.h>
|
|
|
|
#include "COMM_IPC_Messages.h"
|
|
|
|
/* Private Function Prototypes */
|
|
|
|
#if (__CORTEX_M == 0)
|
|
static void Message_Received_for_CM0(uint32_t * msg);
|
|
static void Message_Received_by_CM4(void);
|
|
#endif // (__CORTEX_M == 0)
|
|
|
|
#if (__CORTEX_M == 4)
|
|
static void Message_Received_for_CM4(uint32_t * msg);
|
|
static void Message_Received_by_CM0(void);
|
|
#endif // (__CORTEX_M == 4)
|
|
|
|
static void IPC_UserPipeInit(void);
|
|
static void IPC_UserPipeISR(void);
|
|
|
|
|
|
/* Local Definitions and Constants */
|
|
|
|
//! Number of clients supported on the user pipe.
|
|
#define CY_IPC_USRPIPE_CLIENT_CNT (uint32_t)(8u)
|
|
|
|
#define CY_IPC_CHAN_USRPIPE_CM0 (uint32_t)(8u)
|
|
#define CY_IPC_CHAN_USRPIPE_CM4 (uint32_t)(9u)
|
|
|
|
#define CY_IPC_INTR_USRPIPE_CM0 (uint32_t)(8u)
|
|
#define CY_IPC_INTR_USRPIPE_CM4 (uint32_t)(9u)
|
|
|
|
#define CY_IPC_EP_USRPIPE_ADDR_CM0_EP (uint32_t)(2u)
|
|
#define CY_IPC_EP_USRPIPE_ADDR_CM4_EP (uint32_t)(3u)
|
|
|
|
#if (CY_CPU_CORTEX_M0P)
|
|
#define IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_ADDR_CM0_EP
|
|
#else
|
|
#define IPC_EP_USRPIPE_ADDR CY_IPC_EP_USRPIPE_ADDR_CM4_EP
|
|
#endif /* (CY_CPU_CORTEX_M0P) */
|
|
|
|
/* User Pipe Configuration */
|
|
|
|
#define IPC_USRPIPE_CHAN_MASK_CM0 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM0)
|
|
#define IPC_USRPIPE_CHAN_MASK_CM4 (uint32_t)(0x0001ul << CY_IPC_CHAN_USRPIPE_CM4)
|
|
#define IPC_USRPIPE_INTR_MASK (uint32_t)( IPC_USRPIPE_CHAN_MASK_CM0 | IPC_USRPIPE_CHAN_MASK_CM4 )
|
|
#define IPC_INTR_USRPIPE_PRIOR_CM0 (uint32_t)(1u) /* Notifier Priority */
|
|
#define IPC_INTR_USRPIPE_PRIOR_CM4 (uint32_t)(1u) /* Notifier Priority */
|
|
#define IPC_INTR_USRPIPE_MUX_CM0 (uint32_t)(7u) /* IPC CYPRESS PIPE */
|
|
#define IPC_USRPIPE_CONFIG_CM0 (uint32_t)(IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos)\
|
|
|(CY_IPC_INTR_USRPIPE_CM0 << CY_IPC_PIPE_CFG_INTR_Pos )\
|
|
|(CY_IPC_CHAN_USRPIPE_CM0)
|
|
#define IPC_USRPIPE_CONFIG_CM4 (uint32_t)(IPC_USRPIPE_INTR_MASK << CY_IPC_PIPE_CFG_IMASK_Pos)\
|
|
|(CY_IPC_INTR_USRPIPE_CM4 << CY_IPC_PIPE_CFG_INTR_Pos )\
|
|
|(CY_IPC_CHAN_USRPIPE_CM4)
|
|
|
|
#define USRPIPE_CONFIG \
|
|
{\
|
|
/* .ep0ConfigData */ {\
|
|
/* .ipcNotifierNumber */ CY_IPC_INTR_USRPIPE_CM0,\
|
|
/* .ipcNotifierPriority */ IPC_INTR_USRPIPE_PRIOR_CM0,\
|
|
/* .ipcNotifierMuxNumber */ IPC_INTR_USRPIPE_MUX_CM0,\
|
|
/* .epAddress */ CY_IPC_EP_USRPIPE_ADDR_CM0_EP,\
|
|
/* .epConfig */ IPC_USRPIPE_CONFIG_CM0\
|
|
},\
|
|
/* .ep1ConfigData */ {\
|
|
/* .ipcNotifierNumber */ CY_IPC_INTR_USRPIPE_CM4,\
|
|
/* .ipcNotifierPriority */ IPC_INTR_USRPIPE_PRIOR_CM4,\
|
|
/* .ipcNotifierMuxNumber */ 0u,\
|
|
/* .epAddress */ CY_IPC_EP_USRPIPE_ADDR_CM4_EP,\
|
|
/* .epConfig */ IPC_USRPIPE_CONFIG_CM4\
|
|
},\
|
|
/* .endpointClientsCount */ CY_IPC_USRPIPE_CLIENT_CNT,\
|
|
/* .endpointsCallbacksArray */ ipc_pipe_CbArray,\
|
|
/* .userPipeIsrHandler */ &IPC_UserPipeISR\
|
|
}
|
|
|
|
//! Client ID for messages from the CM0 to the CM4
|
|
#define COMM_IPC_CM0_TO_CM4_CLIENT_ID 0
|
|
//! Client ID for messages from the CM4 to the CM0
|
|
#define COMM_IPC_CM4_TO_CM0_CLIENT_ID 1
|
|
|
|
|
|
/* Public Variables */
|
|
|
|
/* Private Variables */
|
|
|
|
#if (__CORTEX_M == 0)
|
|
static COMM_IPCMessage_T MessageBuffer =
|
|
{
|
|
.ClientID = _VAL2FLD(CY_IPC_PIPE_MSG_CLIENT, COMM_IPC_CM0_TO_CM4_CLIENT_ID) | _VAL2FLD(CY_IPC_PIPE_MSG_USR, 0) | _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, IPC_USRPIPE_INTR_MASK),
|
|
.MessageID = COMM_SMM_DefaultNoMessage,
|
|
.Data = NULL
|
|
};
|
|
|
|
static volatile bool OK_to_send_from_CM0_to_CM4 = true;
|
|
#endif // (__CORTEX_M == 0)
|
|
|
|
#if (__CORTEX_M == 4)
|
|
static COMM_IPCMessage_T MessageBuffer =
|
|
{
|
|
.ClientID = _VAL2FLD(CY_IPC_PIPE_MSG_CLIENT, COMM_IPC_CM4_TO_CM0_CLIENT_ID) | _VAL2FLD(CY_IPC_PIPE_MSG_USR, 0) | _VAL2FLD(CY_IPC_PIPE_MSG_RELEASE, IPC_USRPIPE_INTR_MASK),
|
|
.MessageID = COMM_SMM_DefaultNoMessage,
|
|
.Data = NULL
|
|
};
|
|
|
|
static volatile bool OK_to_send_from_CM4_to_CM0 = true;
|
|
#endif // (__CORTEX_M == 4)
|
|
|
|
|
|
/* Public Functions */
|
|
|
|
#if (__CORTEX_M == 0)
|
|
//! Initializes the inter-processor communications on the Cortex-M0 core.
|
|
/*!
|
|
* This should be called *before* calling Cy_SysEnableCM4().
|
|
*/
|
|
void COMM_InitIPCMessages(void)
|
|
{
|
|
IPC_UserPipeInit();
|
|
|
|
// Register a callback to handle messages from CM4.
|
|
Cy_IPC_Pipe_RegisterCallback(IPC_EP_USRPIPE_ADDR,
|
|
Message_Received_for_CM0,
|
|
CY_IPC_EP_CYPIPE_CM4_ADDR);
|
|
}
|
|
#endif // (__CORTEX_M == 0)
|
|
|
|
#if (__CORTEX_M == 4)
|
|
//! Initializes the inter-processor communications on the Cortex-M4 core.
|
|
void COMM_InitIPCMessages(void)
|
|
{
|
|
IPC_UserPipeInit();
|
|
|
|
// Register a callback to handle messages from CM0.
|
|
Cy_IPC_Pipe_RegisterCallback(IPC_EP_USRPIPE_ADDR,
|
|
Message_Received_for_CM4,
|
|
CY_IPC_EP_CYPIPE_CM0_ADDR);
|
|
}
|
|
#endif // (__CORTEX_M == 4)
|
|
|
|
|
|
//! Sends an inter-processor communication message to the other core.
|
|
bool COMM_SendMessageToOtherCore(COMM_IPCMessageID_T message_ID, void * message_data)
|
|
{
|
|
bool message_sent = false;
|
|
|
|
MessageBuffer.MessageID = message_ID;
|
|
MessageBuffer.Data = message_data;
|
|
|
|
#if (__CORTEX_M == 0)
|
|
if (OK_to_send_from_CM0_to_CM4 == true)
|
|
{
|
|
OK_to_send_from_CM0_to_CM4 = false;
|
|
uint32_t timeout_in_us = 2000;
|
|
cy_en_ipc_pipe_status_t ipcStatus;
|
|
|
|
do
|
|
{
|
|
ipcStatus = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_USRPIPE_ADDR_CM4_EP,
|
|
CY_IPC_EP_USRPIPE_ADDR_CM0_EP,
|
|
(uint32_t *) &MessageBuffer,
|
|
Message_Received_by_CM4);
|
|
Cy_SysLib_DelayUs(1u);
|
|
timeout_in_us--;
|
|
} while((ipcStatus != CY_IPC_PIPE_SUCCESS) && (timeout_in_us != 0));
|
|
|
|
message_sent = true;
|
|
}
|
|
#endif // (__CORTEX_M == 0)
|
|
|
|
#if (__CORTEX_M == 4)
|
|
if (OK_to_send_from_CM4_to_CM0 == true)
|
|
{
|
|
OK_to_send_from_CM4_to_CM0 = false;
|
|
uint32_t timeout_in_us = 2000;
|
|
cy_en_ipc_pipe_status_t ipcStatus;
|
|
|
|
do
|
|
{
|
|
ipcStatus = Cy_IPC_Pipe_SendMessage(CY_IPC_EP_USRPIPE_ADDR_CM0_EP,
|
|
CY_IPC_EP_USRPIPE_ADDR_CM4_EP,
|
|
(uint32_t *) &MessageBuffer,
|
|
Message_Received_by_CM0);
|
|
Cy_SysLib_DelayUs(1u);
|
|
timeout_in_us--;
|
|
} while((ipcStatus != CY_IPC_PIPE_SUCCESS) && (timeout_in_us != 0));
|
|
|
|
message_sent = true;
|
|
}
|
|
#endif // (__CORTEX_M == 4)
|
|
|
|
return message_sent;
|
|
}
|
|
|
|
|
|
/* Private Functions */
|
|
|
|
#if (__CORTEX_M == 0)
|
|
//! Callback for messages received by the CM0 core from the CM4 core.
|
|
/*!
|
|
* \note This code is executed inside an interrupt handler.
|
|
*/
|
|
static void Message_Received_for_CM0(uint32_t * msg)
|
|
{
|
|
switch (((COMM_IPCMessage_T *)msg)->MessageID)
|
|
{
|
|
default:
|
|
case COMM_SMM_DefaultNoMessage:
|
|
case COMM_SMM_NoMessage:
|
|
break;
|
|
|
|
case COMM_SMM_RebootImmediately:
|
|
// Perform a software reset of both cores.
|
|
NVIC_SystemReset();
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Message_Received_by_CM4(void)
|
|
{
|
|
OK_to_send_from_CM0_to_CM4 = true;
|
|
}
|
|
#endif // (__CORTEX_M == 0)
|
|
|
|
#if (__CORTEX_M == 4)
|
|
//! Callback for messages received by the CM4 core from the CM0 core.
|
|
/*!
|
|
* \note This code is executed inside an interrupt handler.
|
|
*/
|
|
static void Message_Received_for_CM4(uint32_t * msg)
|
|
{
|
|
switch (((COMM_IPCMessage_T *)msg)->MessageID)
|
|
{
|
|
default:
|
|
case COMM_SMM_DefaultNoMessage:
|
|
case COMM_SMM_NoMessage:
|
|
break;
|
|
|
|
case COMM_SMM_RebootImmediately:
|
|
// This message does nothing on CM4
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Message_Received_by_CM0(void)
|
|
{
|
|
OK_to_send_from_CM4_to_CM0 = true;
|
|
}
|
|
#endif // (__CORTEX_M == 4)
|
|
|
|
//! Initializes the IPC user pipe.
|
|
static void IPC_UserPipeInit(void)
|
|
{
|
|
static cy_ipc_pipe_callback_ptr_t ipc_pipe_CbArray[CY_IPC_USRPIPE_CLIENT_CNT];
|
|
static const cy_stc_ipc_pipe_config_t userPipeConfig = USRPIPE_CONFIG;
|
|
|
|
uint32_t savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
|
|
|
Cy_IPC_Pipe_Init(&userPipeConfig);
|
|
|
|
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
|
}
|
|
|
|
//! Interrupt service routine for the user pipe.
|
|
void IPC_UserPipeISR(void)
|
|
{
|
|
Cy_IPC_Pipe_ExecuteCallback(IPC_EP_USRPIPE_ADDR);
|
|
}
|
|
|