PeripheralDriver_Flagchip_F.../Src/fc7xxx_driver_mb.c

457 lines
11 KiB
C

/**
* @file fc7xxx_driver_mb.c
* @author Flagchip070
* @brief FC7xxx Mailbox driver type definition and API
* @version 0.1.0
* @date 2022-11-15
*
* @copyright Copyright (c) 2022 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 "fc7xxx_driver_mb.h"
/********* Local variable ************/
static uint32_t s_u32CoreIndex = MB_NOT_INIT;
static const uint8_t s_aMasterIdTab[MB_INT_CONFIG_COUNT] = {
0u, 8u
};
static void (*s_pRequestCallback)(MB_ReceiveType *pReceive) = NULL;
static void (*s_pDoneCallback)(uint32_t u32ChannelMask) = NULL;
/******* Local Function Prototype *********/
static uint32_t core_id_2_index(uint32_t u32MasterId);
static uint8_t get_channel_status(uint32_t u32Channel);
/**
* @brief Convert core master id to index
*
* @param u32MasterId Core master ID
*
*/
static uint32_t core_id_2_index(uint32_t u32MasterId)
{
uint32_t u32Index = 0;
uint32_t u32Loop;
for(u32Loop = 0; u32Loop < MB_INT_CONFIG_COUNT; u32Loop++)
{
if(s_aMasterIdTab[u32Loop] == u32MasterId)
{
u32Index = u32Loop;
break;
}
}
return u32Index;
}
/**
* @brief Get the master security information and processing mode of the channel
*
* @param u32Channel the selected MB channel
*
*/
static uint8_t get_channel_status(uint32_t u32Channel)
{
uint8_t u8Status = 0;
if(0u == MB_HWA_GetSecure(u32Channel))
{
u8Status |= MB_CHANNEL_STATUS_SECURE;
}
if(0u != MB_HWA_GetSupervisor(u32Channel))
{
u8Status |= MB_CHANNEL_STATUS_PRIVILEGED;
}
return u8Status;
}
/********* Global Functions ************/
/**
* @brief Get the index of the core
*
* @return uint32_t index of the core
*/
uint32_t MB_GetCoreIndex(void)
{
return s_u32CoreIndex;
}
/**
* @brief Initialize the Mailbox
*
* @param pInitConfig the configurations of the Mailbox
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_Init(const MB_InitType *pInitConfig)
{
MB_StatusType eStatus = MB_STATUS_SUCCESS;
if(MB_NOT_INIT != s_u32CoreIndex)
{
eStatus = MB_STATUS_ALREADY_INITED;
}
else
{
/* Get Core Index */
#if defined(DEVICE_TYPE) && (DEVICE_TYPE == FC7XXXHSM)
s_u32CoreIndex = HSM_MAILBOX_CORE_INDEX;
#else
uint32_t u32CoreId;
uint32_t u32Index;
u32CoreId = (MCM->MICR & MCM_MICR_COREID_Msk) >> MCM_MICR_COREID_Pos;
for(u32Index = 0; u32Index < MB_INT_CONFIG_COUNT; u32Index++)
{
if(u32CoreId == s_aMasterIdTab[u32Index])
{
s_u32CoreIndex = u32Index;
break;
}
}
#endif
if(MB_NOT_INIT != s_u32CoreIndex)
{
/*Registering callback functions*/
s_pRequestCallback = pInitConfig->pRequestCallback;
s_pDoneCallback = pInitConfig->pDoneCallback;
/*Configure the event mask*/
MB_HWA_ConfigFlagMask(s_u32CoreIndex, pInitConfig->u32EventMask);
/*Enable event interrupts */
MB_HWA_ConfigIntrEnable(s_u32CoreIndex, pInitConfig->u32IntrMask);
}
else
{
eStatus = MB_STATUS_FAILED;
}
}
return eStatus;
}
/**
* @brief De-initialize the Mailbox
*
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_DeInit(void)
{
MB_StatusType eStatus = MB_STATUS_UNINIT;
if(MB_NOT_INIT != s_u32CoreIndex)
{
/*Disable all event interrupts and flag*/
MB_HWA_ConfigFlagMask(s_u32CoreIndex, 0);
MB_HWA_ConfigIntrEnable(s_u32CoreIndex, 0);
s_u32CoreIndex = MB_NOT_INIT;
}
return eStatus;
}
/**
* @brief Attempt to acquire a Mailbox channel
*
* @param u32Channel the selected Mailbox channel
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_LockChannel(uint32_t u32Channel)
{
MB_StatusType eStatus = MB_STATUS_SUCCESS;
uint32_t u32Lock;
if(MB_NOT_INIT == s_u32CoreIndex)
{
eStatus = MB_STATUS_UNINIT;
}
else
{
if(u32Channel < MB_CHANNEL_CONFIG_COUNT)
{
/*Read SEMA to lock the selected channel*/
u32Lock = MB_HWA_LockChannel(u32Channel);
if(0u == u32Lock)
{
eStatus = MB_STATUS_LOCKED;
}
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
}
return eStatus;
}
/**
* @brief Release a Mailbox channel
*
* @param u32Channel the selected Mailbox channel
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_ReleaseChannel(uint32_t u32Channel)
{
MB_StatusType eStatus = MB_STATUS_SUCCESS;
uint32_t u32MasterId;
if(MB_NOT_INIT == s_u32CoreIndex)
{
eStatus = MB_STATUS_UNINIT;
}
else
{
if(u32Channel < MB_CHANNEL_CONFIG_COUNT)
{
/*Check the master core of the channel*/
u32MasterId = MB_HWA_GetMasterID(u32Channel);
if(u32MasterId == s_aMasterIdTab[s_u32CoreIndex])
{
/*Release the selected channel*/
MB_HWA_ReleaseChannel(u32Channel);
}
else
{
eStatus = MB_STATUS_FAILED;
}
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
}
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_NOT_INIT == s_u32CoreIndex)
{
eStatus = MB_STATUS_UNINIT;
}
else
{
if(u32Channel < MB_CHANNEL_CONFIG_COUNT)
{
MB_HWA_UnlockChanne(u32Channel);
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
}
return eStatus;
}
/**
* @brief Launching a Mailbox request
*
* @param pRequest Configuration of the request
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_SendRequest(MB_RequestType *pRequest)
{
MB_StatusType eStatus = MB_LockChannel(pRequest->u8Channel);
if(MB_STATUS_SUCCESS == eStatus)
{
if(pRequest->u8DoneMasterIndex < MB_INT_CONFIG_COUNT)
{
MB_HWA_ConfigDoneMasterId(pRequest->u8Channel, s_aMasterIdTab[pRequest->u8DoneMasterIndex]);
MB_HWA_ConfigDoneMask(pRequest->u8Channel, pRequest->u8DoneMask);
MB_HWA_ConfigAutoUnlock(pRequest->u8Channel, pRequest->u8AutoReleaseFlag);
MB_HWA_WriteData(pRequest->u8Channel, pRequest->aData);
MB_HWA_ConfigRequest(pRequest->u8Channel, pRequest->u8RequestMask);
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
}
return eStatus;
}
/**
* @brief Attempt to receive a request from the selected channel
*
* @param pReceive Configuration of the receiving request
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_ReceiveChannel(MB_ReceiveType *pReceive)
{
MB_StatusType eStatus = MB_STATUS_SUCCESS;
uint32_t u32Flag;
if(MB_NOT_INIT == s_u32CoreIndex)
{
eStatus = MB_STATUS_UNINIT;
}
else if(pReceive->u8Channel < MB_CHANNEL_CONFIG_COUNT)
{
u32Flag = MB_HWA_GetFlag(s_u32CoreIndex, MB_EVENT_REQ(pReceive->u8Channel));
if(0u != u32Flag)
{
/* Clear events flag */
MB_HWA_ClearFlag(s_u32CoreIndex, u32Flag);
/* receiving data */
MB_HWA_GetData(pReceive->u8Channel, pReceive->aData);
/* get the security information and processing mode */
pReceive->u8ChannelStatus = get_channel_status(pReceive->u8Channel);
/*get the master core index of the request*/
pReceive->u8MasterCoreIndex = (uint8_t)MB_HWA_GetMasterID(pReceive->u8Channel);
pReceive->u8MasterCoreIndex = (uint8_t)core_id_2_index((uint32_t)pReceive->u8MasterCoreIndex);
}
else
{
eStatus = MB_STATUS_NO_REQUEST;
}
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
return eStatus;
}
/**
* @brief Issue a done event to the selected channel
*
* @param u32Channel the selected Mailbox channel
* @param u32DoneMask The mask for issuing done
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_DoneChannel(uint32_t u32Channel, uint32_t u32DoneMask)
{
MB_StatusType eStatus = MB_STATUS_SUCCESS;
uint32_t u32DoneMasterId, u32DoneMaskAllow;
if(MB_NOT_INIT == s_u32CoreIndex)
{
eStatus = MB_STATUS_UNINIT;
}
else if(u32Channel < MB_CHANNEL_CONFIG_COUNT)
{
/* Check the done master of the channel*/
u32DoneMasterId = MB_HWA_GetDoneMasterId(u32Channel);
if(u32DoneMasterId == s_aMasterIdTab[s_u32CoreIndex])
{
/* Check if the done mask is allowed */
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;
}
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
return eStatus;
}
/**
* @brief Polling the done event of all channels
*
* @param u32PollMask mask of the done event
* @param pDoneMask buffer to store the done events
* @return MB_StatusType whether the operation is successfully
*/
MB_StatusType MB_PollDone(uint32_t u32PollMask, uint32_t *pDoneMask)
{
MB_StatusType eStatus = MB_STATUS_SUCCESS;
uint32_t u32Flag, u32Index;
*pDoneMask = 0;
if(MB_NOT_INIT == s_u32CoreIndex)
{
eStatus = MB_STATUS_UNINIT;
}
else if(0u != u32PollMask)
{
for(u32Index = 0; u32Index < MB_CHANNEL_CONFIG_COUNT; u32Index++)
{
if(0u != (u32PollMask & ((uint32_t)1u << u32Index)))
{
u32Flag = MB_HWA_GetFlag(s_u32CoreIndex, MB_EVENT_DONE(u32Index));
if(0u != u32Flag)
{
/* Clear done flag */
MB_HWA_ClearFlag(s_u32CoreIndex, u32Flag);
/* store the done event */
*pDoneMask |= (uint32_t)1u << u32Index;
}
}
}
}
else
{
eStatus = MB_STATUS_PARAM_ERROR;
}
return eStatus;
}
/**
* @brief Interrupt IRQ handle of Mailbox
*
*/
void MB_IRQProcess(void)
{
uint32_t u32FlagStat = MB_HWA_GetFlagStat(s_u32CoreIndex, MB_INTn_FLG_STAT_MASK);
uint32_t u32Index, u32MasterCore, u32ChannelMask = 0;
MB_ReceiveType tReceive;
MB_HWA_ClearFlag(s_u32CoreIndex, u32FlagStat);
for(u32Index = 0; u32Index < MB_CHANNEL_CONFIG_COUNT; u32Index++)
{
/* get the master core index of the channel*/
u32MasterCore = MB_HWA_GetMasterID(u32Index);
u32MasterCore = core_id_2_index(u32MasterCore);
if(0u != (u32FlagStat & ((uint32_t)1u << u32Index)))
{
/* request event */
if(NULL != s_pRequestCallback)
{
tReceive.u8Channel = (uint8_t)u32Index;
tReceive.u8ChannelStatus = get_channel_status(u32Index);
tReceive.u8MasterCoreIndex = (uint8_t)u32MasterCore;
MB_HWA_GetData(u32Index, tReceive.aData);
/* call the request callback*/
s_pRequestCallback(&tReceive);
}
}
if(0u != (u32FlagStat & ((uint32_t)1u << (u32Index + MB_INTn_FLG_STAT_FLG_DONE_INT_STAT_SHIFT))))
{
u32ChannelMask |= (uint32_t)1u << u32Index;
/*done event*/
if((0u == MB_HWA_GetAutoClear(u32Index, s_u32CoreIndex)) && (u32MasterCore == s_u32CoreIndex))
{
/* if channel is not automatically clear,
* and master core is self, release the channel */
MB_HWA_ReleaseChannel(u32Index);
}
}
}
if((NULL != s_pDoneCallback) && (0u != u32ChannelMask))
{
s_pDoneCallback(u32ChannelMask);
}
}