2020TPC-SW/2020TPCApp1.cydsn/COMM/COMM_IPC_Messages.c
2025-02-01 19:52:04 -06:00

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);
}