443 lines
12 KiB
C
443 lines
12 KiB
C
/**
|
|
* @file module_driver_mb.c
|
|
* @author flagchip
|
|
* @brief Mailbox driver type definition and API
|
|
* @version 2.0.0
|
|
* @date 2024-08-20
|
|
*
|
|
* SDK Version: 2.6.0
|
|
*
|
|
|
|
* @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd.
|
|
*
|
|
* @details
|
|
*/
|
|
/* ********************************************************************************
|
|
* Revision History:
|
|
*
|
|
* Version Date Initials CR# Descriptions
|
|
* --------- ---------- ------------ ---------- ---------------
|
|
* 0.1.0 2022-11-15 Flagchip070 N/A First version for FC7300
|
|
******************************************************************************** */
|
|
|
|
#include "module_driver_mb.h"
|
|
|
|
#if MB_INSTANCE_COUNT > 0U
|
|
|
|
#ifndef MB_DEV_ERROR_REPORT
|
|
#define MB_DEV_ERROR_REPORT STD_ON
|
|
#endif
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
#define MB_ReportDevError(func, error) ReportDevError(MB_MODULE_ID, func, error)
|
|
#endif
|
|
/********* Local variable ************/
|
|
|
|
static const uint8_t s_aMasterIdTab[MB_INTR_CHANNEL_COUNT] = MB_MASTER_ID_TABLE;
|
|
|
|
/******* Local Function Prototype *********/
|
|
static void MB_GetMasterCoreStatus(MB_ReceiveType *pReceive);
|
|
static uint32_t MB_GetMasterCoreIndex(uint32_t u32MasterId);
|
|
/******* Local Function *********/
|
|
static void MB_GetMasterCoreStatus(MB_ReceiveType *pReceive)
|
|
{
|
|
if (MB_HWA_GetSemaphore(pReceive->u8Channel, MB_CCn_SEMA_LOCK_MASTER_SEC_MASK))
|
|
{
|
|
pReceive->bSecure = true;
|
|
}
|
|
else
|
|
{
|
|
pReceive->bSecure = false;
|
|
}
|
|
if (MB_HWA_GetSemaphore(pReceive->u8Channel, MB_CCn_SEMA_LOCK_MASTER_SUPERVISOR_MASK))
|
|
{
|
|
pReceive->bSupervisor = true;
|
|
}
|
|
else
|
|
{
|
|
pReceive->bSupervisor = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Convert core master id to index
|
|
*
|
|
* @param u32MasterId Core master ID
|
|
*
|
|
*/
|
|
static uint32_t MB_GetMasterCoreIndex(uint32_t u32MasterId)
|
|
{
|
|
uint32_t u32Index = 0;
|
|
uint32_t u32Loop;
|
|
for(u32Loop = 0; u32Loop < MB_INTR_CHANNEL_COUNT; u32Loop++)
|
|
{
|
|
if(s_aMasterIdTab[u32Loop] == u32MasterId)
|
|
{
|
|
u32Index = u32Loop;
|
|
break;
|
|
}
|
|
}
|
|
return u32Index;
|
|
}
|
|
|
|
/********* Global Functions ************/
|
|
|
|
/**
|
|
* @brief Initialize the Mailbox
|
|
* @param pMbHandle Mailbox processing handle
|
|
* @param pInitConfig the configurations of the Mailbox
|
|
*
|
|
*/
|
|
void MB_Init(MB_HandleType *pMbHandle, const MB_InitType *pInitConfig)
|
|
{
|
|
/* Get Core Index*/
|
|
pMbHandle->tStatus.u8CoreIndex = Cpm_HWA_GetCoreId();
|
|
pMbHandle->tStatus.u8CoreIndex = pMbHandle->tStatus.u8CoreIndex >= MB_CORE_INDEX_HSM ? (pMbHandle->tStatus.u8CoreIndex + 1U) : pMbHandle->tStatus.u8CoreIndex;
|
|
pMbHandle->tStatus.u8MasterId = s_aMasterIdTab[pMbHandle->tStatus.u8CoreIndex];
|
|
/*Registering callback functions*/
|
|
pMbHandle->tStatus.pRequestCallback = pInitConfig->pRequestCallback;
|
|
pMbHandle->tStatus.pDoneCallback = pInitConfig->pDoneCallback;
|
|
|
|
MB_HWA_UnlockIntrReg(pMbHandle->tStatus.u8CoreIndex, \
|
|
MB_INTn_CTRL_FLG_LOCK_MASK | MB_INTn_CTRL_FLG_MASK_LOCK_MASK | MB_INTn_CTRL_INTEN_LOCK_MASK);
|
|
|
|
/*Configure the event mask*/
|
|
MB_HWA_ConfigFlagMask(pMbHandle->tStatus.u8CoreIndex, pInitConfig->u32EventMask);
|
|
/*Clear interrupt flag*/
|
|
MB_HWA_ClearFlag(pMbHandle->tStatus.u8CoreIndex, MB_INTn_FLG_MASK_MASK);
|
|
/*Enable event interrupts */
|
|
MB_HWA_ConfigIntrEnable(pMbHandle->tStatus.u8CoreIndex, pInitConfig->u32IntrMask);
|
|
MB_HWA_LockIntrReg( pMbHandle->tStatus.u8CoreIndex, \
|
|
MB_INTn_CTRL_FLG_LOCK_MASK | MB_INTn_CTRL_FLG_MASK_LOCK_MASK | MB_INTn_CTRL_INTEN_LOCK_MASK);
|
|
|
|
}
|
|
|
|
/**
|
|
* @brief De-initialize the Mailbox
|
|
*
|
|
* @param pMbHandle Mailbox processing handle
|
|
*/
|
|
void MB_DeInit(MB_HandleType *pMbHandle)
|
|
{
|
|
MB_HWA_UnlockIntrReg(pMbHandle->tStatus.u8CoreIndex, \
|
|
MB_INTn_CTRL_FLG_LOCK_MASK | MB_INTn_CTRL_FLG_MASK_LOCK_MASK | MB_INTn_CTRL_INTEN_LOCK_MASK);
|
|
/*Disable all event interrupts and flag*/
|
|
MB_HWA_ConfigFlagMask(pMbHandle->tStatus.u8CoreIndex, 0);
|
|
MB_HWA_ConfigIntrEnable(pMbHandle->tStatus.u8CoreIndex, 0);
|
|
/*Clear interrupt flag*/
|
|
MB_HWA_ClearFlag(pMbHandle->tStatus.u8CoreIndex, MB_INTn_FLG_MASK_MASK);
|
|
MB_HWA_LockIntrReg(pMbHandle->tStatus.u8CoreIndex, \
|
|
MB_INTn_CTRL_FLG_LOCK_MASK | MB_INTn_CTRL_FLG_MASK_LOCK_MASK | MB_INTn_CTRL_INTEN_LOCK_MASK);
|
|
}
|
|
|
|
/**
|
|
* @brief Attempt to acquire a Mailbox channel
|
|
*
|
|
* @param u32Channel the selected Mailbox channel
|
|
* @return MB_StatusType whether the operation is successfully
|
|
*/
|
|
MB_StatusType MB_AcquireChannel(uint32_t u32Channel)
|
|
{
|
|
MB_StatusType eStatus = MB_STATUS_SUCCESS;
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
if(u32Channel >= MB_COM_CHANNEL_COUNT)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_LOCK_CHANNEL_ID, MB_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
/*Read SEMA to lock the selected channel*/
|
|
if(0u == MB_HWA_GetSemaphore(u32Channel, MB_CCn_SEMA_LOCK_MASK))
|
|
{
|
|
eStatus = MB_STATUS_LOCKED;
|
|
}
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Release a Mailbox channel
|
|
*
|
|
* @param pMbHandle Mailbox processing handle
|
|
* @param u32Channel the selected Mailbox channel
|
|
* @return MB_StatusType whether the operation is successfully
|
|
*/
|
|
MB_StatusType MB_ReleaseChannel(MB_HandleType *pMbHandle, uint32_t u32Channel)
|
|
{
|
|
MB_StatusType eStatus = MB_STATUS_SUCCESS;
|
|
uint32_t u32MasterId;
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
if(u32Channel >= MB_COM_CHANNEL_COUNT)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_RECEIVE_CHANNEL_ID, MB_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
/*Check the master core of the channel*/
|
|
u32MasterId = MB_HWA_GetMasterID(u32Channel);
|
|
if(u32MasterId == pMbHandle->tStatus.u8MasterId)
|
|
{
|
|
/*Release the selected channel*/
|
|
MB_HWA_ReleaseChannel(u32Channel);
|
|
}
|
|
else
|
|
{
|
|
eStatus = MB_STATUS_FAILED;
|
|
}
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Software clears channel lock
|
|
*
|
|
* @param u32Channel the selected Mailbox channel
|
|
* @return MB_StatusType whether the operation is successfully
|
|
*/
|
|
MB_StatusType MB_UnlockChannel(uint32_t u32Channel)
|
|
{
|
|
MB_StatusType eStatus = MB_STATUS_SUCCESS;
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
if(u32Channel >= MB_COM_CHANNEL_COUNT)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_UNLOCK_CHANNEL_ID, MB_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
MB_HWA_UnlockChannel(u32Channel);
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Launching a Mailbox request
|
|
*
|
|
* @param pMbHandle Mailbox processing handle
|
|
* @param pRequest Configuration of the request
|
|
* @return MB_StatusType whether the operation is successfully
|
|
*/
|
|
MB_StatusType MB_SendRequest(MB_HandleType *pMbHandle, MB_RequestType *pRequest)
|
|
{
|
|
MB_StatusType eStatus;
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
if (pRequest == NULL)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_SEND_REQUEST_ID, MB_E_PARAM_POINTER);
|
|
}
|
|
else if (pRequest->u8Channel >= MB_COM_CHANNEL_COUNT)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_SEND_REQUEST_ID, MB_E_PARAM_CHANNEL);
|
|
}
|
|
else if (!MB_CORE_INDEX_VALID(pRequest->u8TargetCoreIndex))
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_SEND_REQUEST_ID, MB_E_PARAM_INVALID);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
/*Read SEMA to lock the selected channel*/
|
|
if(0u == MB_HWA_GetSemaphore((uint32_t)pRequest->u8Channel, MB_CCn_SEMA_LOCK_MASK))
|
|
{
|
|
eStatus = MB_STATUS_LOCKED;
|
|
}
|
|
else
|
|
{
|
|
uint32_t u32DoneMask = (uint32_t)(1U << pMbHandle->tStatus.u8CoreIndex);
|
|
MB_HWA_ConfigDoneMasterId(pRequest->u8Channel, s_aMasterIdTab[pRequest->u8TargetCoreIndex]);
|
|
MB_HWA_ConfigDoneMask(pRequest->u8Channel, u32DoneMask);
|
|
if (pRequest->bAutoRelease)
|
|
{
|
|
MB_HWA_ConfigAutoUnlock(pRequest->u8Channel, u32DoneMask);
|
|
}
|
|
else
|
|
{
|
|
MB_HWA_ConfigAutoUnlock(pRequest->u8Channel, 0U);
|
|
}
|
|
MB_HWA_WriteData(pRequest->u8Channel, pRequest->aData);
|
|
MB_HWA_ConfigRequest(pRequest->u8Channel, (uint32_t)(1U << pRequest->u8TargetCoreIndex));
|
|
eStatus = MB_STATUS_SUCCESS;
|
|
}
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Attempt to receive a request from the selected channel
|
|
*
|
|
* @param pMbHandle Mailbox processing handle
|
|
* @param pReceive Configuration of the receiving request
|
|
* @return MB_StatusType whether the operation is successfully
|
|
*/
|
|
MB_StatusType MB_ReceiveChannel(MB_HandleType *pMbHandle, MB_ReceiveType *pReceive)
|
|
{
|
|
MB_StatusType eStatus = MB_STATUS_SUCCESS;
|
|
uint32_t u32Flag;
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
if (pReceive->u8Channel >= MB_COM_CHANNEL_COUNT)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_RECEIVE_CHANNEL_ID, MB_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
uint8_t u8CoreIndex = pMbHandle->tStatus.u8CoreIndex;
|
|
u32Flag = MB_HWA_GetFlag(u8CoreIndex, MB_EVENT_REQ(pReceive->u8Channel));
|
|
if(0u != u32Flag)
|
|
{
|
|
MB_HWA_UnlockFlag(u8CoreIndex);
|
|
/* Clear events flag */
|
|
MB_HWA_ClearFlag(u8CoreIndex, u32Flag);
|
|
MB_HWA_LockFlag(u8CoreIndex);
|
|
/* receiving data */
|
|
MB_HWA_GetData(pReceive->u8Channel, pReceive->aData);
|
|
/* get the security information and processing mode */
|
|
MB_GetMasterCoreStatus(pReceive);
|
|
/*get the master core index of the request*/
|
|
volatile uint32 u32Rvalue = MB_HWA_GetMasterID(pReceive->u8Channel);
|
|
|
|
uint32_t u32CoreIndex;
|
|
__asm volatile("rbit %1,%0" : "=r"(u32Rvalue) : "r"(u32Rvalue));
|
|
__asm volatile("clz %0,%1" : "=r"(u32CoreIndex) : "r"(u32Rvalue));
|
|
pReceive->u8MasterCoreIndex = (uint8_t)(u32CoreIndex & 0x3);
|
|
}
|
|
else
|
|
{
|
|
eStatus = MB_STATUS_NO_REQUEST;
|
|
}
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Issue a done event to the selected channel
|
|
*
|
|
* @param pMbHandle Mailbox processing handle
|
|
* @param u32Channel the selected Mailbox channel
|
|
* @param u8TargetCoreIndex the target core index
|
|
* @return MB_StatusType whether the operation is successfully
|
|
*/
|
|
MB_StatusType MB_DoneChannel(MB_HandleType *pMbHandle, uint32_t u32Channel, uint8_t u8TargetCoreIndex)
|
|
{
|
|
MB_StatusType eStatus = MB_STATUS_SUCCESS;
|
|
uint32_t u32DoneMasterId, u32DoneMaskAllow;
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
if (u32Channel >= MB_COM_CHANNEL_COUNT)
|
|
{
|
|
eStatus = MB_STATUS_PARAM_ERROR;
|
|
MB_ReportDevError(MB_DONE_CHANNEL_ID, MB_E_PARAM_CHANNEL);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
/* Check the done master of the channel*/
|
|
u32DoneMasterId = MB_HWA_GetDoneMasterId(u32Channel);
|
|
if(u32DoneMasterId == pMbHandle->tStatus.u8MasterId)
|
|
{
|
|
/* Check if the done mask is allowed */
|
|
uint32_t u32DoneMask = (uint32_t)(1U << u8TargetCoreIndex);
|
|
u32DoneMaskAllow = MB_HWA_GetDoneMask(u32Channel);
|
|
if((u32DoneMaskAllow & u32DoneMask) == u32DoneMask)
|
|
{
|
|
/* issue a done event */
|
|
MB_HWA_SetDone(u32Channel, u32DoneMask);
|
|
}
|
|
else
|
|
{
|
|
eStatus = MB_STATUS_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eStatus = MB_STATUS_FAILED;
|
|
}
|
|
#if MB_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eStatus;
|
|
}
|
|
|
|
/**
|
|
* @brief Polling the done event of all channels
|
|
*
|
|
* @param pMbHandle Mailbox processing handle
|
|
* @return uint32_t Done event from the communication channel
|
|
*/
|
|
uint32_t MB_PollDone(MB_HandleType *pMbHandle)
|
|
{
|
|
uint32_t u32DoneFlag = 0;
|
|
uint8_t u8CoreIndex = pMbHandle->tStatus.u8CoreIndex;
|
|
u32DoneFlag = MB_HWA_GetFlag(u8CoreIndex, MB_EVENT_ALL_DONE);
|
|
if(0u != u32DoneFlag)
|
|
{
|
|
MB_HWA_UnlockFlag(u8CoreIndex);
|
|
/* Clear done flag */
|
|
MB_HWA_ClearFlag(pMbHandle->tStatus.u8CoreIndex, u32DoneFlag);
|
|
MB_HWA_LockFlag(u8CoreIndex);
|
|
u32DoneFlag = u32DoneFlag >> MB_INTn_FLG_DONE_FLAG_SHIFT;
|
|
}
|
|
|
|
return u32DoneFlag;
|
|
}
|
|
|
|
/**
|
|
* @brief Interrupt IRQ handle of Mailbox
|
|
* @param pMbHandle Mailbox processing handle
|
|
*/
|
|
void MB_IRQProcess(MB_HandleType *pMbHandle)
|
|
{
|
|
uint8_t u8CoreIndex = pMbHandle->tStatus.u8CoreIndex;
|
|
uint32_t u32FlagStat = MB_HWA_GetFlagStat(u8CoreIndex, MB_INTn_FLG_STAT_MASK);
|
|
uint32_t u32Index, u32MasterCore;
|
|
|
|
MB_HWA_UnlockFlag(u8CoreIndex);
|
|
MB_HWA_ClearFlag(u8CoreIndex, u32FlagStat);
|
|
MB_HWA_LockFlag(u8CoreIndex);
|
|
for(u32Index = 0; u32Index < MB_COM_CHANNEL_COUNT; u32Index++)
|
|
{
|
|
/* get the master core index of the channel*/
|
|
u32MasterCore = MB_HWA_GetMasterID(u32Index);
|
|
u32MasterCore = MB_GetMasterCoreIndex(u32MasterCore);
|
|
if(0u != (u32FlagStat & ((uint32_t)1u << u32Index)))
|
|
{
|
|
/* request event */
|
|
if(NULL != pMbHandle->tStatus.pRequestCallback)
|
|
{
|
|
MB_ReceiveType tReceive;
|
|
tReceive.u8Channel = (uint8_t)u32Index;
|
|
MB_GetMasterCoreStatus(&tReceive);
|
|
tReceive.u8MasterCoreIndex = (uint8_t)u32MasterCore;
|
|
MB_HWA_GetData(u32Index, tReceive.aData);
|
|
/* call the request callback*/
|
|
pMbHandle->tStatus.pRequestCallback(pMbHandle, &tReceive);
|
|
}
|
|
}
|
|
if ((NULL != pMbHandle->tStatus.pDoneCallback) &&
|
|
(0u != (u32FlagStat & ((uint32_t)1u << (u32Index + MB_INTn_FLG_DONE_FLAG_SHIFT)))))
|
|
{
|
|
pMbHandle->tStatus.pDoneCallback(pMbHandle, u32Index);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* #if MB_INSTANCE_COUNT > 0U */
|
|
|