3628 lines
144 KiB
C
3628 lines
144 KiB
C
/**
|
|
* @file module_driver_fciic.c
|
|
* @author Flagchip
|
|
* @brief FCIIC driver type definition and API
|
|
* @version 2.0.0
|
|
* @date 2023-09-18
|
|
*
|
|
* SDK Version: 2.6.0
|
|
*
|
|
|
|
* @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd.
|
|
*
|
|
*/
|
|
|
|
/* ********************************************************************************
|
|
* Revision History:
|
|
*
|
|
* Version Date Initials CR# Descriptions
|
|
* --------- ---------- ------------ ---------- ---------------
|
|
* 0.1.0 2022/12/31 qxw0052 N/A First version for FC7300
|
|
* 0.2.0 2023/02/14 qxw0052 N/A Fix MISRA issues
|
|
* 0.2.1 2023/09/18 qxw0100 N/A modify clock duty to 1:2
|
|
* x.x.x 2024/xx/xx qxw0100 N/A Refactor driver
|
|
* 2.3.5 2025/06/25 qxw0120 N/A Update subaddress mode
|
|
******************************************************************************** */
|
|
|
|
#include "module_driver_fciic.h"
|
|
|
|
#if FCIIC_INSTANCE_COUNT > 0U
|
|
|
|
#include "module_driver_dma.h"
|
|
|
|
#include "stdarg.h"
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
#include "stdlib.h"
|
|
|
|
|
|
#ifndef FCIIC_DEV_ERROR_REPORT
|
|
#define FCIIC_DEV_ERROR_REPORT STD_OFF
|
|
#endif
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
#define FCIIC_ReportDevError(func, error) ReportDevError(FCIIC_MODULE_ID, func, error)
|
|
#endif
|
|
|
|
/********* Local variable ************/
|
|
static FCIIC_Type *const s_aFCIIC_InstanceTable[FCIIC_INSTANCE_COUNT] = FCIIC_BASE_PTRS;
|
|
|
|
/* ################################################################################## */
|
|
/* ################################ Global Functions ################################ */
|
|
|
|
/**
|
|
* @brief Checks if the I2C bus is busy for the master.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC Master handle.
|
|
*
|
|
* @return FCIIC_StatusType Indicates whether the bus is busy or not.
|
|
* @retval FCIIC_SUCCESS Bus is not busy.
|
|
* @retval FCIIC_BUSY Bus is busy.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterCheckForBusyBus(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
FCIIC_StatusType ret = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
|
|
uint32_t status = FCIIC_HWA_MasterGetStatusFlags(pFciic);
|
|
|
|
if (0U != (status & (uint32_t)FCIIC_MSR_BBF))
|
|
{
|
|
ret = FCIIC_BUSY;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Initializes a default configuration for the I2C master.
|
|
*
|
|
* This function sets up the default configuration parameters for the I2C master.
|
|
*
|
|
* @param[out] pMasterConfig Pointer to the structure where the default configuration will be stored.
|
|
*
|
|
* The following configurations are set:
|
|
* - bEnableMaster: Enables the master functionality.
|
|
* - bDebugEnable: Disables debug mode by default.
|
|
* - ePinConfig: Sets the pin configuration to open-drain.
|
|
* - u32BaudRate: Sets the baud rate to 100 kHz.
|
|
* - u32BusIdleTimeout: Disables the bus idle timeout.
|
|
* - u32PinLowTimeout: Disables the pin low timeout.
|
|
* - u8SdaGlitchFilterWidth: Disables the SDA glitch filter.
|
|
* - u8SclGlitchFilterWidth: Disables the SCL glitch filter.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly.
|
|
*/
|
|
void FCIIC_MasterGetDefaultConfig(FCIIC_MasterConfigType *const pMasterConfig)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pMasterConfig == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERGETDEFAULTCONFIG_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pMasterConfig->bEnableMaster = true;
|
|
pMasterConfig->bDebugEnable = false;
|
|
pMasterConfig->ePinConfig = FCIIC_OPENDRAIN;
|
|
pMasterConfig->u32BaudRate = 100000U;
|
|
pMasterConfig->u32BusIdleTimeout = 0U; /* Set to 0 to disable the function */
|
|
pMasterConfig->u32PinLowTimeout = 0U; /* Set to 0 to disable the function */
|
|
pMasterConfig->u8SdaGlitchFilterWidth = 0U; /* Set to 0 to disable the function */
|
|
pMasterConfig->u8SclGlitchFilterWidth = 0U; /* Set to 0 to disable the function */
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the baud rate for the I2C master.
|
|
*
|
|
* This function calculates and sets the baud rate for the I2C master based on the given source clock frequency and desired baud rate.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] sourceClock_Hz The source clock frequency in Hz.
|
|
* @param[in] pMasterConfig Pointer to the master configuration structure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Calculates the optimal values for CLKHI, CLKLO, and PRESCALE to achieve the closest possible baud rate to the desired one.
|
|
* - Configures the MCCR and MCFGR1 registers with the calculated values.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterSetBaudRate(FCIIC_MasterHandleType *const pFciicMasterHandle, uint32_t sourceClock_Hz, const FCIIC_MasterConfigType *const pMasterConfig)
|
|
{
|
|
|
|
/* SCL_LATENCY is defined as ROUNDDOWN ((2 + FILTSCL + SCL_RISETIME) / (2 ^ PRESCALE)) */
|
|
/* CLKLO: Minimum value is 0x3 */
|
|
/* CLKHI: Minimum value is 0x1 */
|
|
/* SCL clock period: (CLKHI + CLKLO + 2 + SCL_LATENCY) / (2 ^ PRESCALE) / function clock period */
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSETBAUDRATE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MODULE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint32_t u32TempMcfgr1, u32TempMccr, u32CLKHI, u32CLKHITemp, u32CLKLO, u32CLKLOTemp;
|
|
uint32_t u32Prescale;
|
|
uint32_t u32BandrateDeltaCur, u32BandrateDeltaBest;
|
|
uint32_t u32FreqDesired, u32FreqCur;
|
|
uint32_t u32ClkSrcHz;
|
|
uint32_t u32FlitScl;
|
|
uint8_t u8PrescaleTemp;
|
|
uint32_t u32Divide;
|
|
|
|
u32ClkSrcHz = sourceClock_Hz;
|
|
u32FreqDesired = pMasterConfig->u32BaudRate;
|
|
u32BandrateDeltaBest = pMasterConfig->u32BaudRate;
|
|
u32BandrateDeltaCur = pMasterConfig->u32BaudRate;
|
|
u32FlitScl = pMasterConfig->u8SclGlitchFilterWidth;
|
|
|
|
for (u8PrescaleTemp = 1U; (u8PrescaleTemp <= 8U) && (u32BandrateDeltaCur != 0); u8PrescaleTemp++)
|
|
{
|
|
u32Divide = Fc_Power(2U, u8PrescaleTemp);
|
|
for (u32CLKHITemp = 1U; (u32CLKHITemp < 32U) && (u32BandrateDeltaCur != 0); u32CLKHITemp++)
|
|
{
|
|
for(u32CLKLOTemp = (2 * u32CLKHITemp - 1); (u32CLKLOTemp < (2 * u32CLKHITemp + 2)) && (u32BandrateDeltaCur != 0); u32CLKLOTemp++)
|
|
{
|
|
u32FreqCur = u32ClkSrcHz / (u32Divide * (u32CLKLOTemp + u32CLKHITemp + 2U) + 4 + u32FlitScl);
|
|
|
|
u32BandrateDeltaCur = u32FreqDesired > u32FreqCur ? (u32FreqDesired - u32FreqCur) : (u32FreqCur - u32FreqDesired);
|
|
|
|
if (u32BandrateDeltaCur < u32BandrateDeltaBest)
|
|
{
|
|
u32Prescale = u8PrescaleTemp;
|
|
u32CLKHI = u32CLKHITemp;
|
|
u32CLKLO = u32CLKLOTemp;
|
|
u32BandrateDeltaBest = u32BandrateDeltaCur;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
u32TempMccr = FCIIC_MCCR_DATAVD(2) |
|
|
FCIIC_MCCR_SETHOLD(2) |
|
|
FCIIC_MCCR_CLKHI(u32CLKHI) |
|
|
FCIIC_MCCR_CLKLO(u32CLKLO);
|
|
|
|
u32TempMcfgr1 = FCIIC_HWA_GetMCFGR1(pFciic);
|
|
u32TempMcfgr1 &= ~FCIIC_MCFGR1_PRESCALE_MASK;
|
|
u32TempMcfgr1 |= FCIIC_MCFGR1_PRESCALE(u32Prescale);
|
|
|
|
FCIIC_HWA_SetMCCR(pFciic, u32TempMccr);
|
|
FCIIC_HWA_SetMCFGR1(pFciic, u32TempMcfgr1);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Initializes the I2C master with the specified configuration.
|
|
*
|
|
* This function initializes the I2C master with the provided configuration and sets up the baud rate.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] pMasterConfig Pointer to the master configuration structure.
|
|
* @param[in] sourceClock_Hz The source clock frequency in Hz.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Resets the I2C hardware.
|
|
* - Sets the baud rate using the `FCIIC_MasterSetBaudRate` function.
|
|
* - Configures the master control register (MCR) for debug enablement.
|
|
* - Configures the master configuration registers (MCFGR1, MCFGR2, MCFGR3) for pin configuration, glitch filters, and timeouts.
|
|
* - Enables the master operation.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointers are null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterInit(FCIIC_MasterHandleType *const pFciicMasterHandle, const FCIIC_MasterConfigType *const pMasterConfig, uint32_t sourceClock_Hz)
|
|
{
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL || pMasterConfig == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint32_t u32TempMcfgr1, u32TempMcfgr2, u32TempMcfgr3;
|
|
|
|
FCIIC_HwA_MasterReset(pFciic);
|
|
|
|
FCIIC_MasterSetBaudRate(pFciicMasterHandle, sourceClock_Hz, pMasterConfig);
|
|
|
|
FCIIC_HWA_SetMcr(pFciic, FCIIC_MCR_DBGEN(pMasterConfig->bDebugEnable));
|
|
|
|
/* pin config and ignore ack */
|
|
u32TempMcfgr1 = FCIIC_HWA_GetMCFGR1(pFciic);
|
|
u32TempMcfgr1 &= ~(FCIIC_MCFGR1_PINCFG_MASK | FCIIC_MCFGR1_IGNACK_MASK);
|
|
u32TempMcfgr1 |= FCIIC_MCFGR1_PINCFG(pMasterConfig->ePinConfig);
|
|
FCIIC_HWA_SetMCFGR1(pFciic, u32TempMcfgr1);
|
|
|
|
/* Configure glitch filters. */
|
|
u32TempMcfgr2 = FCIIC_MCFGR2_FILTSDA(pMasterConfig->u8SdaGlitchFilterWidth) |
|
|
FCIIC_MCFGR2_FILTSCL(pMasterConfig->u8SclGlitchFilterWidth) |
|
|
FCIIC_MCFGR2_BUSIDLE(pMasterConfig->u32BusIdleTimeout);
|
|
FCIIC_HWA_SetMCFGR2(pFciic, u32TempMcfgr2);
|
|
|
|
u32TempMcfgr3 = FCIIC_MCFGR3_PINLOW(pMasterConfig->u32PinLowTimeout);
|
|
FCIIC_HWA_SetMCFGR3(pFciic, u32TempMcfgr3);
|
|
|
|
FCIIC_HwA_MasterEnable(pFciic, pMasterConfig->bEnableMaster);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Deinitializes the I2C master.
|
|
*
|
|
* This function deinitializes the I2C master by resetting it and clearing its configuration.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Resets the master control register (MCR) to disable the master, reset, and clear DMA and buffer flags.
|
|
* - Disables DMA operations by setting the master DMA enable register (MDER).
|
|
* - Clears the pin configuration and glitch filter settings in the master configuration registers (MCFGR1, MCFGR2, MCFGR3).
|
|
* - Resets the I2C hardware.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly.
|
|
*/
|
|
void FCIIC_MasterDeinit(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDEINIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
uint32 u32PccCgcMask = 0x800000U;
|
|
uint32 u32PccSelMask = 0x700000U;
|
|
uint32 u32PccBase = 0x40024000U;
|
|
uint32 u32IICPccRegOffset[2] = {0x198U, 0x41CU};
|
|
FCIIC_Type *const pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint32 u32TempMcr, u32TempMder, u32TempPcc;
|
|
|
|
u32TempMcr = FCIIC_MCR_RRF(0U) |
|
|
FCIIC_MCR_RTF(0U) |
|
|
FCIIC_MCR_DBGEN(0U) |
|
|
FCIIC_MCR_RST(0U) |
|
|
FCIIC_MCR_MEN(0U); /* master disable */
|
|
|
|
u32TempMder = FCIIC_MDER_RDDE(0U) | /* disable receive dma */
|
|
FCIIC_MDER_TDDE(0U); /* disable transmit dma */
|
|
|
|
FCIIC_HWA_MasterDisableInterrupts(pFciic, FCIIC_MIER_MASK);
|
|
FCIIC_HWA_SetMder(pFciic, u32TempMder);
|
|
|
|
/* PRQA S 0306 ++ #Misra-C:2012 Rule-11.4 A conversion should not be performed between a pointer to object and an integer type
|
|
* Reason: Pointer to register addressing map operation could not be avoid */
|
|
u32TempPcc = *((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicMasterHandle->eInstance]));
|
|
/* Disable PCC gate */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicMasterHandle->eInstance])) = (uint32)(u32TempPcc & (~u32PccCgcMask));
|
|
/* Disable function clock */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicMasterHandle->eInstance])) = (uint32)(u32TempPcc & (~u32PccSelMask));
|
|
|
|
FCIIC_HWA_SetMcr(pFciic, FCIIC_MCR_RST(1U));
|
|
FCIIC_HWA_SetMcr(pFciic, u32TempMcr);
|
|
|
|
/* Disable PCC gate */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicMasterHandle->eInstance])) = (uint32)(u32TempPcc & (~u32PccCgcMask));
|
|
/* Recover function clock */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicMasterHandle->eInstance])) = u32TempPcc;
|
|
/* PRQA S 0306 -- */
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Initializes the I2C master handle.
|
|
*
|
|
* This function initializes the I2C master handle with the specified instance and clears its status and settings.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] eInstance The instance of the I2C master to initialize.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Sets the instance of the handle.
|
|
* - Clears the status fields including command data, direction, channel status, and offsets.
|
|
* - Sets callback functions and user data pointers to null.
|
|
* - Initializes DMA-related settings to null or zero.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterInitHandle(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_InstanceType eInstance)
|
|
{
|
|
uint8_t i = 0;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINITHANDLE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINITHANDLE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciicMasterHandle->eInstance = eInstance;
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
pFciicMasterHandle->tStatus.eDirection = FCIIC_DIRNOCONFIG;
|
|
for (i = 0; i < FCIIC_MASTER_CMD_SIZE; i++)
|
|
{
|
|
pFciicMasterHandle->tStatus.u8Cmd[i] = FCIIC_TX_CMD_STOP;
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[i] = 0;
|
|
pFciicMasterHandle->tStatus.u8CmdData[i] = 0;
|
|
}
|
|
pFciicMasterHandle->tStatus.u8CmdSize = 0;
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicMasterHandle->tStatus.u8CmdOffset = 0;
|
|
pFciicMasterHandle->tStatus.u16DataSize = 0;
|
|
pFciicMasterHandle->tStatus.u16DataOffset = 0;
|
|
pFciicMasterHandle->tSettings.pCallback = NULL;
|
|
pFciicMasterHandle->tSettings.pErrorCallback = NULL;
|
|
pFciicMasterHandle->tSettings.pUserData = NULL;
|
|
pFciicMasterHandle->tSettings.pData = NULL;
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize = 0;
|
|
pFciicMasterHandle->tStatus.u8DmaCmdOffset = 0;
|
|
pFciicMasterHandle->tSettings.pFciicTxDmaConfig = NULL;
|
|
pFciicMasterHandle->tSettings.pFciicRxDmaConfig = NULL;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Enables interrupt handling for the I2C master.
|
|
*
|
|
* This function sets the callback functions and user data for interrupt handling in the I2C master.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] pCallback Pointer to the transfer callback function.
|
|
* @param[in] pErrorCallback Pointer to the error callback function.
|
|
* @param[in] pUserData User-defined data to be passed to the callback functions.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Sets the transfer callback, error callback, and user data pointers in the handle's settings.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly.
|
|
*/
|
|
void FCIIC_MasterEnableInterrupt(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterTransfer_CallbackType pCallback, FCIIC_MasterError_CallBackType pErrorCallback,
|
|
void *pUserData)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERENABLEINTERRUPT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciicMasterHandle->tSettings.pCallback = pCallback;
|
|
pFciicMasterHandle->tSettings.pErrorCallback = pErrorCallback;
|
|
pFciicMasterHandle->tSettings.pUserData = pUserData;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Checks and clears errors in the I2C master.
|
|
*
|
|
* This function checks for specific error conditions in the I2C master and clears them if present.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] status The status flags to check and clear.
|
|
*
|
|
* @return FCIIC_StatusType The error status or FCIIC_SUCCESS if no errors were detected.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Checks the status flags against known error conditions.
|
|
* - Selects the appropriate error code based on the severity and type of error.
|
|
* - Clears the error flags in the I2C hardware.
|
|
* - Resets the FIFOs if necessary.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterCheckAndClearError(FCIIC_MasterHandleType *const pFciicMasterHandle, uint32_t status)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERCHECKANDCLEARERROR_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERCHECKANDCLEARERROR_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
status &= (uint32_t)FCIIC_MasterErrorFlags;
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
if (0U != status)
|
|
{
|
|
/* Select the correct error code. Ordered by severity, with bus issues first. */
|
|
if (0U != (status & (uint32_t)FCIIC_MSR_PLTF))
|
|
{
|
|
result = FCIIC_PINLOWTIMEOUT;
|
|
}
|
|
else if (0U != (status & (uint32_t)FCIIC_MSR_ALF))
|
|
{
|
|
result = FCIIC_ARBITRATIONLOST;
|
|
}
|
|
else if (0U != (status & (uint32_t)FCIIC_MSR_NDF))
|
|
{
|
|
result = FCIIC_NAK;
|
|
}
|
|
else if (0U != (status & (uint32_t)FCIIC_MSR_FEF))
|
|
{
|
|
result = FCIIC_FIFOERROR;
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
|
|
/* Clear the flags. */
|
|
FCIIC_HWA_MasterClearStatusFlags(pFciic, status);
|
|
|
|
/* Reset fifos. These flags clear automatically. */
|
|
FCIIC_HWA_MasterResetFIFO(pFciic);
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Waits for a specific flag to be set in the I2C master.
|
|
*
|
|
* This function waits for a given flag to be set in the I2C master status and returns the result.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] u32Flag The flag to wait for.
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or timeout.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Waits for the specified flag to be set within a certain number of attempts.
|
|
* - Returns FCIIC_SUCCESS if the flag is set, or FCIIC_TIMEOUT if the flag is not set within the timeout period.
|
|
* - Checks and clears any errors that may have occurred during the wait.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterWaitFlag(FCIIC_MasterHandleType *const pFciicMasterHandle, uint32_t u32Flag)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_TIMEOUT;
|
|
FCIIC_Type *pFciic;
|
|
uint32_t u32TryCount, u32TryTick;
|
|
uint32_t status;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERWAITFLAG_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERWAITFLAG_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
u32TryCount = 0U;
|
|
while (u32TryCount < 100U)
|
|
{
|
|
u32TryTick = 0U;
|
|
while (u32TryTick++ < 100U)
|
|
{
|
|
__asm("nop");
|
|
}
|
|
|
|
status = FCIIC_HWA_MasterGetStatusFlags(pFciic);
|
|
if (0U != (status & u32Flag))
|
|
{
|
|
result = FCIIC_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
u32TryCount++;
|
|
}
|
|
if (result != FCIIC_TIMEOUT)
|
|
{
|
|
result = FCIIC_MasterCheckAndClearError(pFciicMasterHandle, status);
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Initiates an I2C start condition.
|
|
*
|
|
* This function initiates an I2C start condition and sends the device address along with the read/write direction.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] address The 7-bit I2C address of the target device.
|
|
* @param[in] dir The direction of the communication (read or write).
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or failure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Checks if the bus is busy before starting.
|
|
* - Clears all relevant flags in the I2C hardware.
|
|
* - Sends a start condition followed by the address and direction.
|
|
* - Waits for the transmission done flag to be set.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterStart(FCIIC_MasterHandleType *const pFciicMasterHandle, uint8_t address, FCIIC_DirectionType dir)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_FAIL;
|
|
FCIIC_Type *pFciic;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSTART_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSTART_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
result = FCIIC_MasterCheckForBusyBus(pFciicMasterHandle);
|
|
if (result == FCIIC_SUCCESS)
|
|
{
|
|
/* Clear all flags. */
|
|
FCIIC_HWA_MasterClearStatusFlags(pFciic, FCIIC_MasterClearFlags);
|
|
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_STARTANDTRANSMIT, (uint8_t)((address << 1U) | dir));
|
|
|
|
result = FCIIC_MasterWaitFlag(pFciicMasterHandle, FCIIC_MSR_TDF);
|
|
}
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Initiates an I2C repeated start condition.
|
|
*
|
|
* This function initiates an I2C repeated start condition and sends the device address along with the read/write direction.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] address The 7-bit I2C address of the target device.
|
|
* @param[in] dir The direction of the communication (read or write).
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or failure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Sends a repeated start condition followed by the address and direction.
|
|
* - Waits for the transmission done flag to be set.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterRepeatedStart(FCIIC_MasterHandleType *const pFciicMasterHandle, uint8_t address, FCIIC_DirectionType dir)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERREPEATEDSTART_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERREPEATEDSTART_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_STARTANDTRANSMIT, (uint8_t)((address << 1U) | dir));
|
|
result = FCIIC_MasterWaitFlag(pFciicMasterHandle, FCIIC_MSR_TDF);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a sequence of commands in the I2C master.
|
|
*
|
|
* This function sends a sequence of commands and data to the I2C bus.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or failure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Iterates through each command in the command buffer.
|
|
* - Sends the command and corresponding data.
|
|
* - Waits for the transmission done flag to be set for each command.
|
|
* - Increments the command offset after each successful transmission.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterSendStartCommand(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
uint8 i;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSEND_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSEND_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
for (i = 0; i < pFciicMasterHandle->tStatus.u8CmdSize; ++i)
|
|
{
|
|
FCIIC_Master_HWA_Transmit(pFciic, pFciicMasterHandle->tStatus.u8Cmd[i], pFciicMasterHandle->tStatus.u8CmdData[i]);
|
|
result = FCIIC_MasterWaitFlag(pFciicMasterHandle, FCIIC_MSR_TDF);
|
|
if (result != FCIIC_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
pFciicMasterHandle->tStatus.u8CmdOffset++;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Sends data over the I2C bus.
|
|
*
|
|
* This function sends a block of data over the I2C bus.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] txBuff Pointer to the transmit buffer containing the data to send.
|
|
* @param[in] txSize The size of the data to send in bytes.
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or failure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Iterates through each byte in the transmit buffer.
|
|
* - Sends the byte over the I2C bus.
|
|
* - Waits for the transmission done flag to be set for each byte.
|
|
* - Increments the data offset after each successful transmission.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterSend(FCIIC_MasterHandleType *const pFciicMasterHandle, uint8 *txBuff, uint16 txSize)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
uint16 i;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSEND_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSEND_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
for (i = 0; i < txSize; ++i)
|
|
{
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_TRANSMIT, txBuff[i]);
|
|
result = FCIIC_MasterWaitFlag(pFciicMasterHandle, FCIIC_MSR_TDF);
|
|
if (result != FCIIC_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
pFciicMasterHandle->tStatus.u16DataOffset++;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Receives data over the I2C bus.
|
|
*
|
|
* This function receives a block of data over the I2C bus.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or failure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Iterates through each byte of the receive buffer.
|
|
* - Waits for the receive data flag to be set.
|
|
* - Reads the received byte from the I2C bus.
|
|
* - Stores the received byte in the receive buffer.
|
|
* - Increments the data offset after each successful reception.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterReceive(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
uint8_t i;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERRECEIVE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERRECEIVE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
for (i = 0; i < pFciicMasterHandle->tStatus.u16DataSize; ++i)
|
|
{
|
|
result = FCIIC_MasterWaitFlag(pFciicMasterHandle, FCIIC_MSR_RDF);
|
|
if (result != FCIIC_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
pFciicMasterHandle->tSettings.pData[i] = FCIIC_Master_HWA_Receive(pFciic);
|
|
pFciicMasterHandle->tStatus.u16DataOffset++;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Sends a stop condition over the I2C bus.
|
|
*
|
|
* This function sends a stop condition over the I2C bus.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* @return FCIIC_StatusType The status indicating success or failure.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Sends a stop condition over the I2C bus.
|
|
* - Waits for the transmission done flag to be set.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterStop(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSTOP_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSTOP_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_STOP, 0U);
|
|
result = FCIIC_MasterWaitFlag(pFciicMasterHandle, FCIIC_MSR_TDF);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Aborts an ongoing I2C transfer.
|
|
*
|
|
* This function aborts an ongoing I2C transfer by disabling interrupts, resetting the FIFO, and marking the handle as unused.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Disables interrupts for the I2C master.
|
|
* - Resets the FIFO.
|
|
* - Marks the handle as unused.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterTransferAbort(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
FCIIC_Type *pFciic;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSFERABORT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSFERABORT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
FCIIC_HWA_MasterDisableInterrupts(pFciic, (uint32_t)FCIIC_MasterIrqFlags);
|
|
FCIIC_HWA_MasterResetFIFO(pFciic);
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the receive length for an ongoing I2C transfer.
|
|
*
|
|
* This function sets the number of bytes to receive during an ongoing I2C transfer.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] u8Len The number of bytes to receive.
|
|
*
|
|
* @return uint8_t Returns 1 if the receive length was successfully set, otherwise 0.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Checks if the transmit count is less than 8.
|
|
* - If the condition is met, sends a receive command with the specified length minus one.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly.
|
|
*/
|
|
uint8_t FCIIC_MasterSetReceiveLen(FCIIC_MasterHandleType *const pFciicMasterHandle, uint8 u8Len)
|
|
{
|
|
uint8_t eRetType = 0;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERSETRECEIVELEN_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint8_t count = (uint8_t)FCIIC_Master_HWA_GetTxCount(pFciic);
|
|
if (8u > count)
|
|
{
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_RECEIVE, (uint8_t)(u8Len - (uint8)1u));
|
|
eRetType = 1;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eRetType;
|
|
}
|
|
|
|
/**
|
|
* @brief Transmits data over the I2C bus.
|
|
*
|
|
* This function transmits data over the I2C bus if the transmission data flag is set.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] pTxData Pointer to the transmit data structure containing the command and data to send.
|
|
*
|
|
* @return uint8_t Returns 1 if the transmission was initiated, otherwise 0.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Clears any error flags.
|
|
* - Checks the transmission data flag.
|
|
* - If the flag is set, sends the command and data.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointers are null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
uint8_t FCIIC_MasterTransmit(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_TxDataType *pTxData)
|
|
{
|
|
uint8_t u8RetVal = 0;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle || NULL == pTxData)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSMIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSMIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
|
|
/* clear error flag */
|
|
/* CheckAndClear(pFciic); */
|
|
|
|
/* check tx data flag */
|
|
u8RetVal = FCIIC_Master_HWA_GetStatus(pFciic, FCIIC_MSR_TDF_STATUS);
|
|
|
|
/* pFciic->MSR |= FCIIC_MSR_FEF_MASK; */ /* clear fifo error error */
|
|
if (u8RetVal == 1U)
|
|
{
|
|
FCIIC_Master_HWA_Transmit(pFciic, pTxData->eCmd, pTxData->u8Data);
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return u8RetVal;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the status of the I2C master.
|
|
*
|
|
* This function retrieves the status of the I2C master based on the specified status type.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] eStatus The status type to retrieve.
|
|
*
|
|
* @return uint8_t Returns the status value as a bit mask.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Retrieves the status based on the specified status type.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
uint8_t FCIIC_MasterGetStatus(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterStatusType eStatus)
|
|
{
|
|
uint8_t u8Status = 0;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERGETSTATUS_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERGETSTATUS_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
u8Status = (uint8_t)(1U >> FCIIC_Master_HWA_GetStatus(pFciic, eStatus));
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return u8Status;
|
|
}
|
|
|
|
/**
|
|
* @brief Clears the status flags of the I2C master.
|
|
*
|
|
* This function clears specific status flags of the I2C master.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Clears the data match flag, protocol error flag, FIFO error flag, address lost flag,
|
|
* not data flag, start detection flag, and end packet flag.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterClrStatus(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERCLRSTATUS_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERCLRSTATUS_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
|
|
FCIIC_Master_HWA_ClrStatus(pFciic, FCIIC_MSR_DMF_MASK | FCIIC_MSR_PLTF_MASK |
|
|
FCIIC_MSR_FEF_MASK | FCIIC_MSR_ALF_MASK |
|
|
FCIIC_MSR_NDF_MASK | FCIIC_MSR_SDF_MASK |
|
|
FCIIC_MSR_EPF_MASK);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Performs a blocking I2C transfer.
|
|
*
|
|
* This function performs a blocking I2C transfer, which includes sending commands and data, and handling the transfer completion or errors.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] transfer Pointer to the I2C transfer parameters.
|
|
*
|
|
* @return FCIIC_StatusType Returns the status of the transfer operation.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Checks if the bus is busy or the handle is already in use.
|
|
* - Clears the status flags.
|
|
* - Initializes the handle's status fields.
|
|
* - Generates and sends the start command.
|
|
* - Sends or receives data based on the direction.
|
|
* - Sends a stop signal after the data transfer.
|
|
* - Calls the callback function upon successful transfer completion.
|
|
* - Calls the error callback function if an error occurs during the transfer.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointers are null and report an error accordingly.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterTransferBlocking(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterTransferType *const transfer)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
uint32_t u8CurChSts;
|
|
FCIIC_DirectionType eDirection;
|
|
FCIIC_Type *pFciic;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if ((NULL == pFciicMasterHandle) || (NULL == transfer))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSFERBLOCKING_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if ((NULL != pFciicMasterHandle) && (NULL != transfer) && (pFciicMasterHandle->eInstance < FCIIC_INSTANCE_COUNT))
|
|
{
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
result = FCIIC_MasterCheckForBusyBus(pFciicMasterHandle);
|
|
|
|
if ((result == FCIIC_BUSY) || (pFciicMasterHandle->tStatus.bUsed == true) || (FCIIC_CH_IDLE != pFciicMasterHandle->tStatus.eChannelStatus))
|
|
{
|
|
return FCIIC_BUSY;
|
|
}
|
|
/* Clear FIFO. */
|
|
FCIIC_HWA_MasterResetFIFO(pFciic);
|
|
FCIIC_MasterClrStatus(pFciicMasterHandle);
|
|
|
|
pFciicMasterHandle->tStatus.bUsed = true;
|
|
pFciicMasterHandle->tStatus.eDirection = transfer->eDirection;
|
|
pFciicMasterHandle->tSettings.pData = transfer->pData;
|
|
pFciicMasterHandle->tStatus.u16DataSize = transfer->u16DataSize;
|
|
pFciicMasterHandle->tStatus.u16DataOffset = 0;
|
|
pFciicMasterHandle->tStatus.u8CmdSize = 0;
|
|
pFciicMasterHandle->tStatus.u8CmdOffset = 0;
|
|
eDirection = pFciicMasterHandle->tStatus.eDirection;
|
|
|
|
FCIIC_MasterGenerateStartCommand(pFciicMasterHandle, transfer);
|
|
|
|
/*master send command data stage*/
|
|
result = FCIIC_MasterSendStartCommand(pFciicMasterHandle);
|
|
|
|
if ((FCIIC_SUCCESS == result) && (pFciicMasterHandle->tStatus.u8CmdOffset == pFciicMasterHandle->tStatus.u8CmdSize))
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = eDirection == FCIIC_WRITE ? FCIIC_CH_START_WRITE : FCIIC_CH_START_READ;
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
/*master transmit or receive data stage*/
|
|
if ((FCIIC_WRITE == eDirection) && (FCIIC_CH_START_WRITE == pFciicMasterHandle->tStatus.eChannelStatus))
|
|
{
|
|
result = FCIIC_MasterSend(pFciicMasterHandle, pFciicMasterHandle->tSettings.pData, pFciicMasterHandle->tStatus.u16DataSize);
|
|
}
|
|
else if ((FCIIC_READ == eDirection) && (FCIIC_CH_START_READ == pFciicMasterHandle->tStatus.eChannelStatus))
|
|
{
|
|
result = FCIIC_MasterReceive(pFciicMasterHandle);
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
result = FCIIC_TRAMSMITORRECEIVEERROR;
|
|
}
|
|
|
|
/*master send stop signal stage*/
|
|
if ((FCIIC_SUCCESS == result) && (pFciicMasterHandle->tStatus.u16DataOffset == pFciicMasterHandle->tStatus.u16DataSize))
|
|
{
|
|
result = FCIIC_MasterStop(pFciicMasterHandle);
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
result |= FCIIC_TRAMSMITORRECEIVEERROR;
|
|
}
|
|
/*master callback function*/
|
|
if ((FCIIC_SUCCESS == result) && (pFciicMasterHandle->tStatus.eChannelStatus == FCIIC_CH_TRANSFER_FINISHED))
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
if (NULL != pFciicMasterHandle->tSettings.pCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pCallback(pFciicMasterHandle, FCIIC_SUCCESS);
|
|
}
|
|
}
|
|
/*master callback error function*/
|
|
if (FCIIC_CH_ERROR_PRESENT == pFciicMasterHandle->tStatus.eChannelStatus)
|
|
{
|
|
u8CurChSts = FCIIC_HWA_GetMSR(pFciic);
|
|
result |= FCIIC_MasterCheckAndClearError(pFciicMasterHandle, u8CurChSts);
|
|
FCIIC_MasterTransferAbort(pFciicMasterHandle);
|
|
if (NULL != pFciicMasterHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pErrorCallback(pFciicMasterHandle, result);
|
|
}
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = FCIIC_FAIL;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
/**
|
|
* @brief Prepares the DMA channel for I2C master transfer.
|
|
*
|
|
* This function prepares the DMA channel for data transfer by configuring the DMA attributes and starting the DMA transfer.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Configures the DMA channel attributes based on the transfer direction (read/write).
|
|
* - Sets up the DMA source and destination buffers, block size, and other settings.
|
|
* - Starts the DMA transfer.
|
|
* - Updates the channel status based on the transfer direction.
|
|
* - Calls the error callback function if an error occurs during preparation.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterDmaPrepare(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMAPREPARE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((NULL != pFciicMasterHandle) && (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMAPREPARE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_HandleType *pDmaHandle = NULL;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
DMA_ChannelCfgType FCIIC_DmaChannelAttr = {0};
|
|
|
|
if (FCIIC_DMA_NEXT_STAGE_DATA == pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage ||
|
|
FCIIC_DMA_NEXT_STAGE_DATA == pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage)
|
|
{
|
|
FCIIC_DmaChannelAttr.eSrcDataSize = DMA_TRANSFER_SIZE_1B;
|
|
FCIIC_DmaChannelAttr.eDestDataSize = DMA_TRANSFER_SIZE_1B;
|
|
FCIIC_DmaChannelAttr.u32BlockSize = 1;
|
|
FCIIC_DmaChannelAttr.u16BlockCount = pFciicMasterHandle->tStatus.u16DataSize;
|
|
if (FCIIC_WRITE == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
FCIIC_DmaChannelAttr.pSrcBuffer = &(pFciicMasterHandle->tSettings.pData[0]);
|
|
FCIIC_DmaChannelAttr.pDestBuffer = &(pFciic->MTDR);
|
|
FCIIC_DmaChannelAttr.eSrcIncMode = DMA_INCREMENT_DATA_SIZE ;
|
|
FCIIC_DmaChannelAttr.eDestIncMode = DMA_INCREMENT_DISABLE;
|
|
pDmaHandle = pFciicMasterHandle->tSettings.pFciicTxDmaConfig->pDmaHandle;
|
|
if (FCIIC_INSTANCE_0 == pFciicMasterHandle->eInstance)
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC0_TX;
|
|
}
|
|
else
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC1_TX;
|
|
}
|
|
}
|
|
else if (FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
FCIIC_DmaChannelAttr.pSrcBuffer = &(pFciic->MRDR);
|
|
FCIIC_DmaChannelAttr.pDestBuffer = &(pFciicMasterHandle->tSettings.pData[0]);
|
|
FCIIC_DmaChannelAttr.eSrcIncMode = DMA_INCREMENT_DISABLE ;
|
|
FCIIC_DmaChannelAttr.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
|
|
pDmaHandle = pFciicMasterHandle->tSettings.pFciicRxDmaConfig->pDmaHandle;
|
|
if (FCIIC_INSTANCE_0 == pFciicMasterHandle->eInstance)
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC0_RX;
|
|
}
|
|
else
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC1_RX;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FCIIC_DmaChannelAttr.pSrcBuffer = &(pFciicMasterHandle->tStatus.u16DmaCmdData[0]);
|
|
FCIIC_DmaChannelAttr.pDestBuffer = &(pFciic->MTDR);
|
|
FCIIC_DmaChannelAttr.eSrcDataSize = DMA_TRANSFER_SIZE_2B;
|
|
FCIIC_DmaChannelAttr.eDestDataSize = DMA_TRANSFER_SIZE_2B;
|
|
FCIIC_DmaChannelAttr.u32BlockSize = 2;
|
|
FCIIC_DmaChannelAttr.u16BlockCount = pFciicMasterHandle->tStatus.u8DmaCmdSize;
|
|
FCIIC_DmaChannelAttr.eSrcIncMode = DMA_INCREMENT_DATA_SIZE ;
|
|
FCIIC_DmaChannelAttr.eDestIncMode = DMA_INCREMENT_DISABLE;
|
|
pDmaHandle = pFciicMasterHandle->tSettings.pFciicTxDmaConfig->pDmaHandle;
|
|
if (FCIIC_INSTANCE_0 == pFciicMasterHandle->eInstance)
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC0_TX;
|
|
}
|
|
else
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC1_TX;
|
|
}
|
|
}
|
|
|
|
FCIIC_DmaChannelAttr.u8ChannelPriority = pDmaHandle->tSettings.u8Channel;
|
|
FCIIC_DmaChannelAttr.bSrcBlockOffsetEn = false;
|
|
FCIIC_DmaChannelAttr.bDestBlockOffsetEn = false;
|
|
FCIIC_DmaChannelAttr.s32BlockOffset = 0;
|
|
FCIIC_DmaChannelAttr.bSrcAddrLoopbackEn = false;
|
|
FCIIC_DmaChannelAttr.bDestAddrLoopbackEn = false;
|
|
FCIIC_DmaChannelAttr.bAutoStop = true;
|
|
FCIIC_DmaChannelAttr.bSrcCircularBufferEn = false;
|
|
FCIIC_DmaChannelAttr.u32SrcCircBufferSize = 0;
|
|
FCIIC_DmaChannelAttr.bDestCircularBufferEn = false;
|
|
FCIIC_DmaChannelAttr.u32DestCircBufferSize = 0;
|
|
|
|
|
|
FCIIC_DmaChannelAttr.bTransferCompleteIntEn = true;
|
|
FCIIC_DmaChannelAttr.pTransferCompleteNotify = pDmaHandle->tSettings.callback.pTransferCompleteCallback;
|
|
FCIIC_DmaChannelAttr.bTransferErrorIntEn = false;
|
|
FCIIC_DmaChannelAttr.pTransferErrorNotify = NULL;
|
|
FCIIC_DmaChannelAttr.completedata = NULL;
|
|
FCIIC_DmaChannelAttr.errdata = NULL;
|
|
|
|
|
|
if (FCIIC_CH_IDLE == pFciicMasterHandle->tStatus.eChannelStatus)
|
|
{
|
|
if ((FCIIC_READ == pFciicMasterHandle->tStatus.eDirection) && (FCIIC_DMA_NEXT_STAGE_IDLE == pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_START_READ;
|
|
pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_DATA;
|
|
}
|
|
else if ((FCIIC_WRITE == pFciicMasterHandle->tStatus.eDirection) && (FCIIC_DMA_NEXT_STAGE_IDLE == pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_DATA;
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_START_WRITE;
|
|
}
|
|
else
|
|
{
|
|
if (NULL != pFciicMasterHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pErrorCallback(pFciicMasterHandle, FCIIC_DMAREQUESTFAIL);
|
|
}
|
|
}
|
|
}
|
|
|
|
DMA_InitChannel(pDmaHandle, &FCIIC_DmaChannelAttr);
|
|
DMA_StartChannel(pDmaHandle);
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Stops the DMA transfer for the I2C master.
|
|
*
|
|
* This function stops the DMA transfer by preparing a stop command and updating the DMA configuration.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Sets up the stop command in the DMA command buffer.
|
|
* - Prepares the DMA for the stop command.
|
|
* - Updates the channel status to indicate the transfer has been stopped.
|
|
* - Adjusts the next DMA stage based on the transfer direction.
|
|
* - Calls the error callback function if an error occurs during the preparation.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterDmaStop(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMASTOP_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMASTOP_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[0] = (uint16)FCIIC_MTDR_CMD(FCIIC_TX_CMD_STOP);
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize = 1;
|
|
pFciicMasterHandle->tStatus.u8DmaCmdOffset = 0;
|
|
FCIIC_MasterDmaPrepare(pFciicMasterHandle);
|
|
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_CLOSED;
|
|
|
|
if ((FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
&& (FCIIC_DMA_NEXT_STAGE_STOP == pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_NOTIFICATION;
|
|
}
|
|
else if ((FCIIC_WRITE == pFciicMasterHandle->tStatus.eDirection)
|
|
&& (FCIIC_DMA_NEXT_STAGE_STOP == pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_NOTIFICATION;
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Initiates a DMA transmit operation for the I2C master.
|
|
*
|
|
* This function initiates the DMA transmit operation by preparing the DMA for transmission and setting the next DMA stage to stop.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Prepares the DMA for the transmit operation.
|
|
* - Sets the next DMA stage to stop after the transmission.
|
|
* - Calls the error callback function if an error occurs during preparation.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterDmaTransmit(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMATRANSMIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((NULL != pFciicMasterHandle) && (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMATRANSMIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
FCIIC_MasterDmaPrepare(pFciicMasterHandle);
|
|
pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_STOP;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Initiates a DMA receive operation for the I2C master.
|
|
*
|
|
* This function initiates the DMA receive operation by preparing the DMA for reception and setting the next DMA stage to stop.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*
|
|
* The function performs the following steps:
|
|
* - Prepares the DMA for the receive operation.
|
|
* - Sets the next DMA stage to stop after the reception.
|
|
* - Calls the error callback function if an error occurs during preparation.
|
|
*
|
|
* @note If FCIIC_DEV_ERROR_REPORT is defined as STD_ON, this function will check if the provided pointer is null and report an error accordingly. It also checks if the instance is valid.
|
|
*/
|
|
void FCIIC_MasterDmaReceive(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMARECEIVE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((NULL == pFciicMasterHandle) && (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMARECEIVE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
FCIIC_MasterDmaPrepare(pFciicMasterHandle);
|
|
pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_STOP;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Starts the DMA transfer for the FCIIC master.
|
|
*
|
|
* This function initializes the DMA command sequence based on the given transfer parameters.
|
|
* It checks for valid input parameters and then prepares the DMA commands to be sent.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle structure.
|
|
* @param[in] transfer Pointer to the FCIIC master transfer structure containing transfer details.
|
|
*/
|
|
void FCIIC_MasterDmaStart(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterTransferType *const transfer)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMASTART_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMASTART_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
uint8_t *pSubAddr = (uint8_t *)&transfer->subaddress;
|
|
uint32 i;
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize = 0;
|
|
|
|
if (0U != transfer->subaddressSize)
|
|
{
|
|
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[pFciicMasterHandle->tStatus.u8DmaCmdSize] = (uint16)(FCIIC_MTDR_CMD(FCIIC_TX_CMD_STARTANDTRANSMIT) | FCIIC_MTDR_DATA((uint8)(
|
|
transfer->u8SlaveAddress << 1) | FCIIC_WRITE));
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize++;
|
|
|
|
for (i = transfer->subaddressSize; i > 0 ; --i)
|
|
{
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[pFciicMasterHandle->tStatus.u8DmaCmdSize] = (uint16)(FCIIC_MTDR_CMD(FCIIC_TX_CMD_TRANSMIT) | FCIIC_MTDR_DATA(pSubAddr[i - 1]));
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize++;
|
|
}
|
|
|
|
if (FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[pFciicMasterHandle->tStatus.u8DmaCmdSize] = (uint16)(FCIIC_MTDR_CMD(FCIIC_TX_CMD_STARTANDTRANSMIT) | FCIIC_MTDR_DATA((
|
|
transfer->u8SlaveAddress << 1) | FCIIC_READ));
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize++;
|
|
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[pFciicMasterHandle->tStatus.u8DmaCmdSize] = (uint16)(FCIIC_MTDR_CMD(FCIIC_TX_CMD_RECEIVE) | FCIIC_MTDR_DATA((transfer->u16DataSize - 1)));
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[pFciicMasterHandle->tStatus.u8DmaCmdSize] = (uint16)((uint16)FCIIC_MTDR_CMD(FCIIC_TX_CMD_STARTANDTRANSMIT) | ((
|
|
transfer->u8SlaveAddress << 1) | transfer->eDirection));
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize++;
|
|
if (FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
pFciicMasterHandle->tStatus.u16DmaCmdData[pFciicMasterHandle->tStatus.u8DmaCmdSize] = (uint16)(FCIIC_MTDR_CMD(FCIIC_TX_CMD_RECEIVE) | (uint8_t)(transfer->u16DataSize - 1));
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize++;
|
|
}
|
|
}
|
|
|
|
FCIIC_MasterDmaPrepare(pFciicMasterHandle);
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Handles the notification stage after a DMA transmission.
|
|
*
|
|
* This function updates the channel status and triggers a callback if one is registered.
|
|
* It also manages the next stage of DMA operations based on the direction of the transfer.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_MasterDmaStageNotification(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMASTAGENOTIFICATION_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
#endif
|
|
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
if ((FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
&& (FCIIC_DMA_NEXT_STAGE_NOTIFICATION == pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_IDLE;
|
|
}
|
|
else if ((FCIIC_WRITE == pFciicMasterHandle->tStatus.eDirection)
|
|
&& (FCIIC_DMA_NEXT_STAGE_NOTIFICATION == pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_IDLE;
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
if (NULL != pFciicMasterHandle->tSettings.pCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pCallback(pFciicMasterHandle, FCIIC_SUCCESS);
|
|
}
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
}
|
|
|
|
/**
|
|
* @brief Handles the data stage of a DMA transmission.
|
|
*
|
|
* This function updates the channel status and triggers the data transfer phase
|
|
* based on the current state and direction of the transfer.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_MasterDmaStageData(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMASTAGEDATA_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
#endif
|
|
FCIIC_ChannelStatusType eChannelStatus;
|
|
|
|
eChannelStatus = pFciicMasterHandle->tStatus.eChannelStatus;
|
|
|
|
if ((FCIIC_WRITE == pFciicMasterHandle->tStatus.eDirection) && (FCIIC_CH_START_WRITE == eChannelStatus)
|
|
&& (FCIIC_DMA_NEXT_STAGE_DATA == pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
FCIIC_MasterDmaTransmit(pFciicMasterHandle);
|
|
}
|
|
else if ((FCIIC_READ == pFciicMasterHandle->tStatus.eDirection) && (FCIIC_CH_START_READ == eChannelStatus)
|
|
&& (FCIIC_DMA_NEXT_STAGE_DATA == pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
FCIIC_MasterDmaReceive(pFciicMasterHandle);
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief DMA interrupt handler for the FCIIC master.
|
|
*
|
|
* This function handles DMA interrupts by determining the next stage of the DMA operation,
|
|
* updating the channel status, and managing error conditions.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_LL_MasterDmaIRQnHandler(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_MASTERDMAIRQNHANDLER_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
#endif
|
|
FCIIC_DmaStatusType eDmaNextStage;
|
|
uint32_t u8CurChSts;
|
|
FCIIC_ChannelStatusType eChannelStatus = pFciicMasterHandle->tStatus.eChannelStatus;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
FCIIC_StatusType eResult;
|
|
|
|
eDmaNextStage = FCIIC_WRITE == pFciicMasterHandle->tStatus.eDirection ?
|
|
pFciicMasterHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage : pFciicMasterHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage;
|
|
|
|
eChannelStatus = pFciicMasterHandle->tStatus.eChannelStatus;
|
|
|
|
if ((FCIIC_DMA_NEXT_STAGE_DATA == eDmaNextStage) && ((FCIIC_CH_START_READ == eChannelStatus) || (FCIIC_CH_START_WRITE == eChannelStatus)))
|
|
{
|
|
pFciicMasterHandle->tStatus.u8DmaCmdOffset = pFciicMasterHandle->tStatus.u8DmaCmdSize;
|
|
FCIIC_MasterDmaStageData(pFciicMasterHandle);
|
|
}
|
|
else if ((FCIIC_DMA_NEXT_STAGE_STOP == eDmaNextStage) && (FCIIC_CH_TRANSFER_FINISHED == eChannelStatus))
|
|
{
|
|
pFciicMasterHandle->tStatus.u16DataOffset = pFciicMasterHandle->tStatus.u16DataSize;
|
|
FCIIC_MasterDmaStop(pFciicMasterHandle);
|
|
}
|
|
else if ((FCIIC_DMA_NEXT_STAGE_NOTIFICATION == eDmaNextStage) && (FCIIC_CH_CLOSED == eChannelStatus))
|
|
{
|
|
pFciicMasterHandle->tStatus.u8DmaCmdOffset = pFciicMasterHandle->tStatus.u8DmaCmdSize ;
|
|
FCIIC_MasterDmaStageNotification(pFciicMasterHandle);
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
if (FCIIC_CH_ERROR_PRESENT == pFciicMasterHandle->tStatus.eChannelStatus)
|
|
{
|
|
u8CurChSts = FCIIC_HWA_GetMSR(pFciic);
|
|
eResult = FCIIC_MasterCheckAndClearError(pFciicMasterHandle, u8CurChSts);
|
|
FCIIC_MasterTransferAbort(pFciicMasterHandle);
|
|
if (NULL != pFciicMasterHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pErrorCallback(pFciicMasterHandle, eResult);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Initiates a DMA transfer for the FCIIC master.
|
|
*
|
|
* This function starts a DMA transfer by configuring the DMA settings and initiating the transfer process.
|
|
* It checks for valid parameters, ensures the bus is not busy, and configures the DMA accordingly.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
* @param[in] transfer Pointer to the FCIIC master transfer structure containing transfer details.
|
|
*
|
|
* @return FCIIC_StatusType The status of the DMA transfer initiation.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterDmaTransfer(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterTransferType *const transfer)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle || NULL == transfer)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMATRANSFER_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERDMATRANSFER_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if ((NULL != pFciicMasterHandle) && (NULL != transfer) && (pFciicMasterHandle->eInstance < FCIIC_INSTANCE_COUNT))
|
|
{
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
result = FCIIC_MasterCheckForBusyBus(pFciicMasterHandle);
|
|
if ((result == FCIIC_BUSY) || (pFciicMasterHandle->tStatus.bUsed == true) || (FCIIC_CH_IDLE != pFciicMasterHandle->tStatus.eChannelStatus))
|
|
{
|
|
return FCIIC_BUSY;
|
|
}
|
|
|
|
if ((NULL != pFciicMasterHandle->tSettings.pFciicRxDmaConfig) && (NULL != pFciicMasterHandle->tSettings.pFciicTxDmaConfig))
|
|
{
|
|
/* Clear FIFO. */
|
|
FCIIC_HWA_MasterResetFIFO(pFciic);
|
|
FCIIC_HWA_MasterClearStatusFlags(pFciic, FCIIC_MasterClearFlags);
|
|
FCIIC_HWA_MasterEnableDMA(pFciic, false, false);
|
|
|
|
pFciicMasterHandle->tSettings.pData = transfer->pData;
|
|
pFciicMasterHandle->tStatus.u16DataSize = transfer->u16DataSize;
|
|
pFciicMasterHandle->tStatus.eDirection = transfer->eDirection;
|
|
pFciicMasterHandle->tStatus.u16DataOffset = 0;
|
|
pFciicMasterHandle->tStatus.u8DmaCmdSize = 0;
|
|
pFciicMasterHandle->tStatus.u8DmaCmdOffset = 0;
|
|
pFciicMasterHandle->tStatus.bUsed = true;
|
|
|
|
FCIIC_MasterDmaStart(pFciicMasterHandle, transfer);
|
|
FCIIC_HWA_MasterEnableDMA(pFciic, true, true);
|
|
|
|
}
|
|
else
|
|
{
|
|
result = FCIIC_DMAREQUESTFAIL;
|
|
if (NULL != pFciicMasterHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pErrorCallback(pFciicMasterHandle, FCIIC_DMAREQUESTFAIL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = FCIIC_FAIL;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Stops the interrupt process for the FCIIC master.
|
|
*
|
|
* This function disables all interrupts, updates the channel status, and triggers a callback if the data transfer is complete.
|
|
* It also handles error conditions if the data offset does not match the expected size.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_MasterInterruptProcessStop(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSSTOP_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSSTOP_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
/* Disable All interrupts */
|
|
FCIIC_HWA_MasterDisableInterrupts(pFciic, (uint32_t)FCIIC_MasterIrqFlags);
|
|
|
|
/* Update channel status */
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
|
|
if (pFciicMasterHandle->tStatus.u16DataOffset == pFciicMasterHandle->tStatus.u16DataSize)
|
|
{
|
|
if (NULL != pFciicMasterHandle->tSettings.pCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pCallback(pFciicMasterHandle, FCIIC_SUCCESS);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Processes the transmit phase in interrupt mode for the FCIIC master.
|
|
*
|
|
* This function transmits data and updates the data offset. It stops the transfer and updates the channel status when the data transfer is complete.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_MasterInterruptProcessTransmit(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSTRANSMIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSTRANSMIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint16 u16CurIdx;
|
|
uint8 u8Data;
|
|
|
|
u16CurIdx = pFciicMasterHandle->tStatus.u16DataOffset;
|
|
|
|
if (u16CurIdx != pFciicMasterHandle->tStatus.u16DataSize)
|
|
{
|
|
u8Data = pFciicMasterHandle->tSettings.pData[u16CurIdx];
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_TRANSMIT, u8Data);
|
|
pFciicMasterHandle->tStatus.u16DataOffset++;
|
|
|
|
if (pFciicMasterHandle->tStatus.u16DataOffset == pFciicMasterHandle->tStatus.u16DataSize)
|
|
{
|
|
(void)FCIIC_MasterStop(pFciicMasterHandle);
|
|
/* Update channel status */
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Processes the receive phase in interrupt mode for the FCIIC master.
|
|
*
|
|
* This function receives data and updates the data offset. It stops the transfer and updates the channel status when the data reception is complete.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_MasterInterruptProcessReceive(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSRECEIVE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSRECEIVE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint16 u16CurIdx = pFciicMasterHandle->tStatus.u16DataOffset;
|
|
|
|
if (u16CurIdx != pFciicMasterHandle->tStatus.u16DataSize)
|
|
{
|
|
pFciicMasterHandle->tSettings.pData[u16CurIdx] = FCIIC_Master_HWA_Receive(pFciic);
|
|
pFciicMasterHandle->tStatus.u16DataOffset++;
|
|
|
|
if (pFciicMasterHandle->tStatus.u16DataOffset == pFciicMasterHandle->tStatus.u16DataSize)
|
|
{
|
|
(void)FCIIC_MasterStop(pFciicMasterHandle);
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Processes the start phase in interrupt mode for the FCIIC master.
|
|
*
|
|
* This function manages the command transmission and updates the command offset. It transitions the channel status based on the current phase of the transfer.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_MasterInterruptProcessStart(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicMasterHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSSTART_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERINTERRUPTPROCESSSTART_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
FCIIC_ChannelStatusType eChannelStatus = pFciicMasterHandle->tStatus.eChannelStatus;
|
|
uint8 u16CurIdx = pFciicMasterHandle->tStatus.u8CmdOffset;
|
|
|
|
if (u16CurIdx != pFciicMasterHandle->tStatus.u8CmdSize)
|
|
{
|
|
pFciicMasterHandle->tStatus.u8CmdOffset++;
|
|
|
|
if (pFciicMasterHandle->tStatus.u8CmdOffset == pFciicMasterHandle->tStatus.u8CmdSize)
|
|
{
|
|
if (eChannelStatus == FCIIC_CH_START_WRITE)
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_SENDING;
|
|
}
|
|
else if (eChannelStatus == FCIIC_CH_START_READ)
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_RECEIVING;
|
|
FCIIC_HWA_MasterDisableInterrupts(pFciic, FCIIC_MIER_TDIE);
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
FCIIC_Master_HWA_Transmit(pFciic,
|
|
pFciicMasterHandle->tStatus.u8Cmd[u16CurIdx],
|
|
pFciicMasterHandle->tStatus.u8CmdData[u16CurIdx]);
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
/**
|
|
* @brief Handles the interrupt for the FCIIC master.
|
|
*
|
|
* This function processes various interrupt sources and updates the state of the transfer based on the current channel status.
|
|
* It also handles errors and calls appropriate callbacks.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC master handle.
|
|
*/
|
|
void FCIIC_LL_MasterIRQnHandler(FCIIC_MasterHandleType *const pFciicMasterHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicMasterHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_MASTERIRQNHANDLER_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_MASTERIRQNHANDLER_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
uint32_t u8CurChSts;
|
|
FCIIC_StatusType eResult = FCIIC_SUCCESS;
|
|
|
|
FCIIC_ChannelStatusType eChannelStatus = pFciicMasterHandle->tStatus.eChannelStatus;
|
|
|
|
u8CurChSts = FCIIC_HWA_GetMSR(pFciic);
|
|
u8CurChSts &= FCIIC_HWA_GetMIER(pFciic);
|
|
|
|
if ((0 != (u8CurChSts & FCIIC_MasterErrorFlags)))
|
|
{
|
|
eResult = FCIIC_MasterCheckAndClearError(pFciicMasterHandle, u8CurChSts);
|
|
/* Update channel status */
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_MSR_TDF)) && ((eChannelStatus == FCIIC_CH_START_WRITE) || (eChannelStatus == FCIIC_CH_START_READ)))
|
|
{
|
|
FCIIC_MasterInterruptProcessStart(pFciicMasterHandle);
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_MSR_TDF)) && (eChannelStatus == FCIIC_CH_SENDING))
|
|
{
|
|
FCIIC_MasterInterruptProcessTransmit(pFciicMasterHandle);
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_MSR_RDF)) && (eChannelStatus == FCIIC_CH_RECEIVING))
|
|
{
|
|
FCIIC_MasterInterruptProcessReceive(pFciicMasterHandle);
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_MSR_SDF)) && (eChannelStatus == FCIIC_CH_TRANSFER_FINISHED))
|
|
{
|
|
FCIIC_MasterInterruptProcessStop(pFciicMasterHandle);
|
|
}
|
|
else
|
|
{
|
|
FCIIC_Master_HWA_Transmit(pFciic, FCIIC_TX_CMD_STOP, 0U);
|
|
eResult = FCIIC_TRAMSMITORRECEIVEERROR;
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
if (FCIIC_CH_ERROR_PRESENT == pFciicMasterHandle->tStatus.eChannelStatus)
|
|
{
|
|
FCIIC_MasterTransferAbort(pFciicMasterHandle);
|
|
if (NULL != pFciicMasterHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicMasterHandle->tSettings.pErrorCallback(pFciicMasterHandle, eResult);
|
|
}
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicMasterHandle->tStatus.bUsed = false;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Generates a start command for the FCIIC Master.
|
|
*
|
|
* This function initializes the master for transmission by generating the necessary commands for the start of a transfer.
|
|
*
|
|
* @param[in] pFciicMasterHandle The FCIIC Master Handle.
|
|
* @param[in] transfer Pointer to the `FCIIC_MasterTransferType` structure containing the transfer details.
|
|
* @return void
|
|
*/
|
|
void FCIIC_MasterGenerateStartCommand(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterTransferType *const transfer)
|
|
{
|
|
uint8_t *pSubAddr = (uint8_t *)&transfer->subaddress;
|
|
uint32_t i;
|
|
|
|
if (0U != transfer->subaddressSize)
|
|
{
|
|
pFciicMasterHandle->tStatus.u8Cmd[pFciicMasterHandle->tStatus.u8CmdSize] = FCIIC_TX_CMD_STARTANDTRANSMIT;
|
|
pFciicMasterHandle->tStatus.u8CmdData[pFciicMasterHandle->tStatus.u8CmdSize] = (uint8_t)((transfer->u8SlaveAddress << 1) | FCIIC_WRITE);
|
|
pFciicMasterHandle->tStatus.u8CmdSize++;
|
|
|
|
for (i = transfer->subaddressSize; i > 0 ; --i)
|
|
{
|
|
pFciicMasterHandle->tStatus.u8Cmd[pFciicMasterHandle->tStatus.u8CmdSize] = FCIIC_TX_CMD_TRANSMIT;
|
|
pFciicMasterHandle->tStatus.u8CmdData[pFciicMasterHandle->tStatus.u8CmdSize] = pSubAddr[i - 1];
|
|
pFciicMasterHandle->tStatus.u8CmdSize++;
|
|
}
|
|
|
|
if (FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
pFciicMasterHandle->tStatus.u8Cmd[pFciicMasterHandle->tStatus.u8CmdSize] = FCIIC_TX_CMD_STARTANDTRANSMIT;
|
|
pFciicMasterHandle->tStatus.u8CmdData[pFciicMasterHandle->tStatus.u8CmdSize] = (uint8_t)((transfer->u8SlaveAddress << 1) | FCIIC_READ);
|
|
pFciicMasterHandle->tStatus.u8CmdSize++;
|
|
|
|
pFciicMasterHandle->tStatus.u8Cmd[pFciicMasterHandle->tStatus.u8CmdSize] = FCIIC_TX_CMD_RECEIVE;
|
|
pFciicMasterHandle->tStatus.u8CmdData[pFciicMasterHandle->tStatus.u8CmdSize] = (uint8_t)(transfer->u16DataSize - 1);
|
|
pFciicMasterHandle->tStatus.u8CmdSize++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.u8Cmd[pFciicMasterHandle->tStatus.u8CmdSize] = FCIIC_TX_CMD_STARTANDTRANSMIT;
|
|
pFciicMasterHandle->tStatus.u8CmdData[pFciicMasterHandle->tStatus.u8CmdSize] = (uint8_t)((transfer->u8SlaveAddress << 1) | pFciicMasterHandle->tStatus.eDirection);
|
|
pFciicMasterHandle->tStatus.u8CmdSize++;
|
|
|
|
if (FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
pFciicMasterHandle->tStatus.u8Cmd[pFciicMasterHandle->tStatus.u8CmdSize] = FCIIC_TX_CMD_RECEIVE;
|
|
pFciicMasterHandle->tStatus.u8CmdData[pFciicMasterHandle->tStatus.u8CmdSize] = (uint8_t)(transfer->u16DataSize - 1);
|
|
pFciicMasterHandle->tStatus.u8CmdSize++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Initiates a non-blocking I2C Master transfer.
|
|
*
|
|
* Sets up and initiates a non-blocking I2C Master transfer, including handling of START, addressing, subaddress (if provided),
|
|
* data transfer, and STOP conditions. Returns immediately after starting the transfer, and the transfer is managed asynchronously
|
|
* using interrupts.
|
|
*
|
|
* @param[in] pFciicMasterHandle Pointer to the FCIIC Master Handle.
|
|
* @param[in] transfer Pointer to the `FCIIC_MasterTransferType` structure containing the transfer details.
|
|
* @return A status code indicating the outcome of the initiation process:
|
|
* - FCIIC_SUCCESS: The transfer was initiated successfully.
|
|
* - FCIIC_BSY: Another non-blocking transfer is already in progress.
|
|
* - Other error codes: Errors encountered during the transfer setup, such as a busy bus.
|
|
*/
|
|
FCIIC_StatusType FCIIC_MasterTransferNonBlocking(FCIIC_MasterHandleType *const pFciicMasterHandle, FCIIC_MasterTransferType *const transfer)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic ;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if ((NULL == pFciicMasterHandle) || (NULL == transfer))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSFERNONBLOCKING_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if ((pFciicMasterHandle->eInstance >= FCIIC_INSTANCE_COUNT))
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_MASTERTRANSFERNONBLOCKING_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if ((NULL != pFciicMasterHandle) && (NULL != transfer) && (pFciicMasterHandle->eInstance < FCIIC_INSTANCE_COUNT))
|
|
{
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicMasterHandle->eInstance];
|
|
if (pFciicMasterHandle->tStatus.bUsed == true)
|
|
{
|
|
result = FCIIC_BUSY;
|
|
}
|
|
else
|
|
{
|
|
result = FCIIC_MasterCheckForBusyBus(pFciicMasterHandle);
|
|
if ((result == FCIIC_SUCCESS) && (FCIIC_CH_IDLE == pFciicMasterHandle->tStatus.eChannelStatus))
|
|
{
|
|
/* Clear FIFO. */
|
|
FCIIC_HWA_MasterResetFIFO(pFciic);
|
|
/* Clear all flags. */
|
|
FCIIC_HWA_MasterClearStatusFlags(pFciic, FCIIC_MasterClearFlags);
|
|
|
|
pFciicMasterHandle->tStatus.bUsed = true;
|
|
pFciicMasterHandle->tStatus.eDirection = transfer->eDirection;
|
|
pFciicMasterHandle->tSettings.pData = transfer->pData;
|
|
pFciicMasterHandle->tStatus.u16DataSize = transfer->u16DataSize;
|
|
pFciicMasterHandle->tStatus.u16DataOffset = 0;
|
|
pFciicMasterHandle->tStatus.u8CmdSize = 0;
|
|
pFciicMasterHandle->tStatus.u8CmdOffset = 0;
|
|
|
|
FCIIC_MasterGenerateStartCommand(pFciicMasterHandle, transfer);
|
|
if (FCIIC_READ == pFciicMasterHandle->tStatus.eDirection)
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_START_READ;
|
|
}
|
|
else
|
|
{
|
|
pFciicMasterHandle->tStatus.eChannelStatus = FCIIC_CH_START_WRITE;
|
|
}
|
|
FCIIC_HWA_MasterEnableInterrupts(pFciic, FCIIC_MasterIrqFlags);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = FCIIC_FAIL;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
/**
|
|
* @brief Initializes the I2C Slave mode.
|
|
*
|
|
* Configures the I2C interface for slave mode operation according to the parameters provided.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave Handle.
|
|
* @param[in] pInitReg Pointer to the `FCIIC_SlaveConfigType` structure containing the initialization settings.
|
|
* @return void
|
|
*/
|
|
void FCIIC_SlaveInit(FCIIC_SlaveHandleType *const pFciicSlaveHandle, const FCIIC_SlaveConfigType *pInitReg)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle || NULL == pInitReg)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
uint32 u32TempScr, u32TempScfgr1, u32TempScfgr2, u32TempSamr, u32TempSder;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
|
|
u32TempScr = FCIIC_SCR_SEN(pInitReg->bEnableSlave) |
|
|
FCIIC_SCR_RST(0U) |
|
|
FCIIC_SCR_FILTEN(pInitReg->bI2cSlaveFilterEnable);
|
|
|
|
u32TempSder = FCIIC_SDER_TDDE(pInitReg->bUsedDMA) |
|
|
FCIIC_SDER_RDDE(pInitReg->bUsedDMA) |
|
|
FCIIC_SDER_AVDE(0U);
|
|
|
|
u32TempSamr = FCIIC_SAMR_ADDR1(0U) |
|
|
FCIIC_SAMR_ADDR0(pInitReg->slaveAddress);
|
|
|
|
u32TempScfgr1 = FCIIC_SCFGR1_ADDRCFG(pInitReg->u8AddrCfg) |
|
|
FCIIC_SCFGR1_HSMEN(0U) |
|
|
FCIIC_SCFGR1_IGNACK(0U) |
|
|
FCIIC_SCFGR1_RXCFG(0U) |
|
|
FCIIC_SCFGR1_TXCFG(0U) |
|
|
FCIIC_SCFGR1_SAEN(0U) |
|
|
FCIIC_SCFGR1_GCEN(0U) |
|
|
FCIIC_SCFGR1_ACKSTALL(pInitReg->bI2cSlaveAckStall) |
|
|
FCIIC_SCFGR1_TXDSTALL(pInitReg->bI2cSlaveTxStall) |
|
|
FCIIC_SCFGR1_RXSTALL(pInitReg->bI2cSlaveRxStall) |
|
|
FCIIC_SCFGR1_ADRSTALL(pInitReg->bI2cSlaveAdrStall);
|
|
|
|
|
|
u32TempScfgr2 = FCIIC_SCFGR2_FILTSDA(pInitReg->u8SdaGlitchFilterWidth) |
|
|
FCIIC_SCFGR2_FILTSCL(pInitReg->u8SclGlitchFilterWidth) |
|
|
FCIIC_SCFGR2_DATAVD(pInitReg->u32PinLowTimeout) |
|
|
FCIIC_SCFGR2_CLKHOLD(pInitReg->u32BusIdleTimeout);
|
|
|
|
FCIIC_HWA_SetSCR(pFciic, u32TempScr);
|
|
FCIIC_HWA_SetSDER(pFciic, u32TempSder);
|
|
FCIIC_HWA_SetSCFGR1(pFciic, u32TempScfgr1);
|
|
FCIIC_HWA_SetSCFGR2(pFciic, u32TempScfgr2);
|
|
FCIIC_HWA_SetSAMR(pFciic, u32TempSamr);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Start listen in IIC Slave mode.
|
|
*
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the slave handle structure.
|
|
* @param[in] transfer Pointer to the I2C transfer parameters.
|
|
*
|
|
* @return FCIIC_StatusType indicating the status of the operation.
|
|
*/
|
|
FCIIC_StatusType FCIIC_Slavelistening(FCIIC_SlaveHandleType *const pFciicSlaveHandle, FCIIC_SlaveTransferType *const transfer)
|
|
{
|
|
FCIIC_StatusType eRetType = FCIIC_FAIL;
|
|
uint32 u32I2cSlaveDmaStatus, u8CurChSts;
|
|
FCIIC_Type *pFciic;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle || NULL == transfer)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if ((NULL != pFciicSlaveHandle) && (NULL != transfer))
|
|
{
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
u8CurChSts = FCIIC_HWA_GetSSR(pFciic);
|
|
eRetType = FCIIC_SlaveCheckForBusyBus(pFciicSlaveHandle);
|
|
eRetType |= FCIIC_SlaveCheckAndClearError(pFciicSlaveHandle, u8CurChSts);
|
|
|
|
if ((FCIIC_SUCCESS == eRetType) && (FCIIC_CH_IDLE == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_LISTENING;
|
|
pFciicSlaveHandle->tStatus.u16DataSize = transfer->u16DataSize;
|
|
pFciicSlaveHandle->tSettings.pData = transfer->pData;
|
|
pFciicSlaveHandle->tStatus.u16DataOffset = 0;
|
|
pFciicSlaveHandle->tStatus.curSubaddressSize = 0;
|
|
pFciicSlaveHandle->tStatus.subaddressSize = transfer->subaddressSize;
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_TREIE | FCIIC_SIER_BEIE);
|
|
|
|
u32I2cSlaveDmaStatus = FCIIC_HWA_GetSDER(pFciic);
|
|
/* DMA Priority*/
|
|
if ((u32I2cSlaveDmaStatus == (uint32)0x0u) && ((NULL == pFciicSlaveHandle->tSettings.pFciicTxDmaConfig) && (NULL == pFciicSlaveHandle->tSettings.pFciicRxDmaConfig)))
|
|
{
|
|
eRetType = FCIIC_SlaveTransferNonBlocking(pFciicSlaveHandle);
|
|
}
|
|
else if ((u32I2cSlaveDmaStatus == (uint32)0x3u) && ((NULL != pFciicSlaveHandle->tSettings.pFciicTxDmaConfig) && (NULL != pFciicSlaveHandle->tSettings.pFciicRxDmaConfig)))
|
|
{
|
|
eRetType = FCIIC_SlaveTransferDMA(pFciicSlaveHandle);
|
|
}
|
|
else
|
|
{
|
|
eRetType = FCIIC_FAIL;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL != pFciicSlaveHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pErrorCallback(pFciicSlaveHandle);
|
|
}
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eRetType = FCIIC_FAIL;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return eRetType;
|
|
}
|
|
|
|
/**
|
|
* @brief Deinitializes the FCIIC slave configuration.
|
|
*
|
|
* This function resets the FCIIC slave peripheral to its default state.
|
|
* It disables the FCIIC slave, clears all registers, and disables interrupts.
|
|
*
|
|
* @param pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*/
|
|
void FCIIC_SlaveDeInit(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDEINIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDEINIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
uint32 u32PccCgcMask = 0x800000U;
|
|
uint32 u32PccSelMask = 0x700000U;
|
|
uint32 u32PccBase = 0x40024000U;
|
|
uint32 u32IICPccRegOffset[2] = {0x198U, 0x41CU};
|
|
FCIIC_Type *const pFciic = s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
uint32 u32TempScr, u32TempSder, u32TempPcc;
|
|
|
|
u32TempScr = FCIIC_SCR_FILTEN(0U) |
|
|
FCIIC_SCR_RST(0U) |
|
|
FCIIC_SCR_SEN(0U); /* slave enable */
|
|
|
|
u32TempSder = FCIIC_SDER_AVDE(0U) |
|
|
FCIIC_SDER_RDDE(0U) |
|
|
FCIIC_SDER_TDDE(0U);
|
|
|
|
FCIIC_Slave_HWA_DisableInterrupt(pFciic, FCIIC_SIER_MASK);
|
|
FCIIC_HWA_SetSDER(pFciic, u32TempSder);
|
|
|
|
/* PRQA S 0306 ++ #Misra-C:2012 Rule-11.4 A conversion should not be performed between a pointer to object and an integer type
|
|
* Reason: Pointer to register addressing map operation could not be avoid */
|
|
u32TempPcc = *((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicSlaveHandle->eInstance]));
|
|
/* Disable PCC gate */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicSlaveHandle->eInstance])) = (uint32)(u32TempPcc & (~u32PccCgcMask));
|
|
/* Disable function clock */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicSlaveHandle->eInstance])) = (uint32)(u32TempPcc & (~u32PccSelMask));
|
|
|
|
FCIIC_HWA_SetSCR(pFciic, FCIIC_SCR_RST(1U));
|
|
FCIIC_HWA_SetSCR(pFciic, u32TempScr);
|
|
|
|
/* Disable PCC gate */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicSlaveHandle->eInstance])) = (uint32)(u32TempPcc & (~u32PccCgcMask));
|
|
/* Recover function clock */
|
|
*((volatile uint32 *)(u32PccBase + u32IICPccRegOffset[pFciicSlaveHandle->eInstance])) = u32TempPcc;
|
|
/* PRQA S 0306 -- */
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Deinitializes the FCIIC slave handle.
|
|
*
|
|
* This function resets the FCIIC slave handle to its default state.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*/
|
|
void FCIIC_SlaveDeinitHandle(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDEINITHANDLE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciicSlaveHandle->tStatus.u16DataSize = 0;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicSlaveHandle->tSettings.pData = NULL;
|
|
pFciicSlaveHandle->tStatus.u16DataOffset = 0;
|
|
pFciicSlaveHandle->tStatus.bUsed = false;
|
|
pFciicSlaveHandle->tStatus.eRunStatus = FCIIC_SUCCESS;
|
|
pFciicSlaveHandle->tStatus.subaddressSize = 0;
|
|
pFciicSlaveHandle->tStatus.u32CurSubaddress = 0;
|
|
pFciicSlaveHandle->tStatus.u32Subaddress = 0;
|
|
pFciicSlaveHandle->tSettings.pCallback = NULL;
|
|
pFciicSlaveHandle->tSettings.pUserData = NULL;
|
|
pFciicSlaveHandle->tSettings.pErrorCallback = NULL;
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig = NULL;
|
|
pFciicSlaveHandle->tSettings.pFciicRxDmaConfig = NULL;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Sends an ACK/NACK signal in IIC Slave mode.
|
|
*
|
|
* This function sends an ACK or NACK signal based on the input parameter.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
* @param[in] bAck Boolean flag to indicate whether to send ACK (true) or NACK (false).
|
|
*/
|
|
void FCIIC_SlaveAck(FCIIC_SlaveHandleType *const pFciicSlaveHandle, boolean bAck)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEACK_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
if ((boolean)TRUE == bAck)
|
|
{
|
|
FCIIC_Slave_HWA_NACK(pFciic, FCIIC_STAR_TXNACK(0U));
|
|
}
|
|
else
|
|
{
|
|
FCIIC_Slave_HWA_NACK(pFciic, FCIIC_STAR_TXNACK(1U));
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Clears the I2C slave status flag state.
|
|
*
|
|
* This function clears the status flags of the I2C slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*/
|
|
void FCIIC_SlaveClrStatus(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVECLRSTATUS_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_MASK);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the slave SSR status.
|
|
*
|
|
* This function retrieves the current status of the slave SSR register.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*
|
|
* @return The current SSR status as a 32-bit unsigned integer.
|
|
*/
|
|
uint32_t FCIIC_SlaveGetStatus(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
uint32_t u32Status = 0;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETSTATUS_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
u32Status = FCIIC_HWA_GetSSR(pFciic);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return u32Status;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Enables the interrupt for the specified FCIIC Slave instance.
|
|
*
|
|
* This function configures the interrupt system to handle non-blocking transfers for the given FCIIC Slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
* @param[in] pCallback Pointer to a callback function that will be invoked when a non-blocking transfer completes.
|
|
* @param[in] pErrorCallBack Pointer to a callback function that will be invoked when an error occurs.
|
|
* @param[in] pUserData Pointer to user-defined data that will be passed back to the callback function when it is called.
|
|
*/
|
|
void FCIIC_SlaveEnableInterrupt(FCIIC_SlaveHandleType *const pFciicSlaveHandle,
|
|
FCIIC_SlaveTransfer_CallbackType pCallback, FCIIC_SlaveError_CallBackType pErrorCallBack, void *pUserData)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEENABLEINTERRUPT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
pFciicSlaveHandle->tSettings.pCallback = pCallback;
|
|
pFciicSlaveHandle->tSettings.pUserData = pUserData;
|
|
pFciicSlaveHandle->tSettings.pErrorCallback = pErrorCallBack;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the FCIIC bus is busy.
|
|
*
|
|
* This function determines if the FCIIC bus is currently busy.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*
|
|
* @return FCIIC_StatusType indicating the bus status.
|
|
*/
|
|
FCIIC_StatusType FCIIC_SlaveCheckForBusyBus(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
FCIIC_StatusType ret = FCIIC_SUCCESS;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETSTATUS_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
uint32_t status = FCIIC_HWA_GetSSR(pFciic);
|
|
|
|
if (0U != (status & (uint32_t)FCIIC_SSR_BBF))
|
|
{
|
|
ret = FCIIC_BUSY;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Checks for and clears I2C Slave errors.
|
|
*
|
|
* This function checks the provided status register for any I2C Slave errors and clears them.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
* @param[in] status The current status register value.
|
|
*
|
|
* @return FCIIC_StatusType indicating the encountered error or FCIIC_SUCCESS if no error is found.
|
|
*/
|
|
FCIIC_StatusType FCIIC_SlaveCheckAndClearError(FCIIC_SlaveHandleType *const pFciicSlaveHandle, uint32_t status)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVECHECKANDCLEARERROR_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
status &= (uint32_t)FCIIC_SlaveErrorFlags;
|
|
if (0U != status)
|
|
{
|
|
/* Select the correct error code. Ordered by severity, with bus issues first. */
|
|
if (0U != (status & (uint32_t)FCIIC_SSR_TREF))
|
|
{
|
|
result = FCIIC_TRAMSMITORRECEIVEERROR;
|
|
}
|
|
else if (0U != (status & (uint32_t)FCIIC_SSR_BEF))
|
|
{
|
|
result = FCIIC_BITERROR;
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
}
|
|
/* Clear the flags. */
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, status);
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the default configuration for the I2C Slave.
|
|
*
|
|
* This function sets the default configuration parameters for the I2C Slave.
|
|
*
|
|
* @param[in] slaveConfig Pointer to the configuration structure.
|
|
* @param[in] bUsedDMA Boolean flag indicating whether DMA is used.
|
|
*/
|
|
void FCIIC_SlaveGetDefaultConfig(FCIIC_SlaveConfigType *const slaveConfig, boolean bUsedDMA)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == slaveConfig)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETDEFAULTCONFIG_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
slaveConfig->bEnableSlave = true; /*!< Enables Slave mode if set to true. */
|
|
slaveConfig->bI2cSlaveFilterEnable = false; /*!< Enables Slave mode if set to true. */
|
|
slaveConfig->bUsedDMA = bUsedDMA;
|
|
slaveConfig->u8AddrCfg = 0;
|
|
slaveConfig->bI2cSlaveAdrStall = false;
|
|
slaveConfig->bI2cSlaveAckStall = false;
|
|
slaveConfig->bI2cSlaveTxStall = false;
|
|
slaveConfig->bI2cSlaveRxStall = false;
|
|
slaveConfig->u32BusIdleTimeout = 0U; /*!< Bus idle timeout in nanoseconds. Set to 0 to disable timeout. */
|
|
slaveConfig->u32PinLowTimeout = 0; /*!< Pin low timeout in nanoseconds. Set to 0 to disable timeout. */
|
|
slaveConfig->u8SdaGlitchFilterWidth = 0; /*!< Width of the SDA glitch filter in nanoseconds. Set to 0 to disable. */
|
|
slaveConfig->u8SclGlitchFilterWidth = 0;
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Receives data in IIC Slave mode.
|
|
*
|
|
* This function receives data when polling (not used when RX interrupt is enabled) in Slave mode.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
* @param[out] pData Pointer to the data buffer where the received data will be stored.
|
|
*
|
|
* @return 0 if fail, non-zero otherwise.
|
|
*/
|
|
uint8_t FCIIC_SlaveReceive(FCIIC_SlaveHandleType *const pFciicSlaveHandle, uint8_t *pData)
|
|
{
|
|
uint8_t u8RetVal = 0;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVERECEIVE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVERECEIVE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
/* check slave receive flag */
|
|
u8RetVal = FCIIC_Slave_HWA_GetStatus(pFciic, FCIIC_SSR_RDF_STATUS);
|
|
|
|
/* u8RetVal = (pFciic->MRDR & FCIIC_MRDR_RXEMPTY_MASK)>>FCIIC_MRDR_RXEMPTY_SHIFT; */
|
|
|
|
if (u8RetVal != 0U)
|
|
{
|
|
/* get received data */
|
|
(*pData) = FCIIC_Slave_HWA_Receive(pFciic);
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return u8RetVal;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the slave error value.
|
|
*
|
|
* This function retrieves the current error value of the slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*
|
|
* @return The current error value as a 32-bit unsigned integer.
|
|
*/
|
|
uint32_t FCIIC_SlaveGetError(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
uint32_t u32RetVal = 0;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETERROR_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETERROR_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic;
|
|
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
/* check receive flag */
|
|
u32RetVal = FCIIC_Slave_HWA_GetErrorFlag(pFciic);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return u32RetVal;
|
|
}
|
|
|
|
/**
|
|
* @brief Clears the slave error value.
|
|
*
|
|
* This function clears the error value of the slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*/
|
|
void FCIIC_SlaveClrError(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVECLRERROR_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVECLRERROR_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic;
|
|
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
/* clear receive flag */
|
|
FCIIC_Slave_HWA_ClrErrorFlag(pFciic);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the current direction of the slave.
|
|
*
|
|
* This function retrieves the current direction (read/write) of the slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
*
|
|
* @return The current direction as an FCIIC_DirectionType enum value.
|
|
*/
|
|
FCIIC_DirectionType FCIIC_SlaveGetDir(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
FCIIC_DirectionType direction = FCIIC_DIRNOCONFIG;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETDIR_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEGETDIR_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
direction = (FCIIC_DirectionType)(FCIIC_HWA_GetSASR(pFciic) & 0x1);
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return direction;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief Processes the IIC Slave AM0F interrupt.
|
|
*
|
|
* This function processes the Address Match 0 Flag interrupt for the IIC Slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
* @param[in] u32IsrStatus The status of the SSR flags.
|
|
*/
|
|
void FCIIC_SlaveInterruptProcessAddressMatch(FCIIC_SlaveHandleType *const pFciicSlaveHandle, uint32 u32IsrStatus)
|
|
{
|
|
(void)u32IsrStatus;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSADDRESSMATCH_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSADDRESSMATCH_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
FCIIC_ChannelStatusType u8CurChSts;
|
|
uint32 u32I2cSlaveDmaStatus = FCIIC_HWA_GetSDER(pFciic);
|
|
uint32 u32Raddr = FCIIC_HWA_GetSASR(pFciic);
|
|
uint32 u32SlaveStatus = FCIIC_HWA_GetSSR(pFciic);
|
|
u8CurChSts = pFciicSlaveHandle->tStatus.eChannelStatus;
|
|
|
|
/*subAddressSize !=0x00u,only support Interrupt*/
|
|
if (((uint8)0X0U != pFciicSlaveHandle->tStatus.subaddressSize) && ((uint32)0x0U == u32I2cSlaveDmaStatus))
|
|
{
|
|
/*firstly match device address when the master want to read and */
|
|
if ((FCIIC_CH_LISTENING == u8CurChSts) && (pFciicSlaveHandle->tStatus.curSubaddressSize != pFciicSlaveHandle->tStatus.subaddressSize) && (0 == (u32SlaveStatus & FCIIC_SSR_RSF_MASK)))
|
|
{
|
|
if ((FCIIC_WRITE == (u32Raddr & FCIIC_DIR_MASK)))
|
|
{
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_RDIE_MASK);
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_LISTENING_READ;
|
|
}
|
|
else
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_SENDING;
|
|
if ((NULL != pFciicSlaveHandle->tSettings.pSubAddressSendingCallback))
|
|
{
|
|
pFciicSlaveHandle->tSettings.pSubAddressSendingCallback(pFciicSlaveHandle);
|
|
}
|
|
uint16 u16CurIdx = pFciicSlaveHandle->tStatus.u16DataOffset;
|
|
FCIIC_Slave_HWA_Transmit(pFciic, pFciicSlaveHandle->tSettings.pData[u16CurIdx]);
|
|
pFciicSlaveHandle->tStatus.u16DataOffset++;
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_TDIE_MASK);
|
|
}
|
|
}
|
|
/*secondly match adddress when the master read and subAddressSize more than 0*/
|
|
else if ((FCIIC_CH_LISTENING_READ == u8CurChSts) && (pFciicSlaveHandle->tStatus.curSubaddressSize == pFciicSlaveHandle->tStatus.subaddressSize) && (0 != (u32SlaveStatus & FCIIC_SSR_RSF_MASK)))
|
|
{
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_RSF_STATUS);
|
|
if (FCIIC_READ == (u32Raddr & FCIIC_DIR_MASK))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_SENDING;
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
if ((NULL != pFciicSlaveHandle->tSettings.pSubAddressSendingCallback))
|
|
{
|
|
pFciicSlaveHandle->tSettings.pSubAddressSendingCallback(pFciicSlaveHandle);
|
|
}
|
|
uint16 u16CurIdx = pFciicSlaveHandle->tStatus.u16DataOffset;
|
|
FCIIC_Slave_HWA_Transmit(pFciic, pFciicSlaveHandle->tSettings.pData[u16CurIdx]);
|
|
pFciicSlaveHandle->tStatus.u16DataOffset++;
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_TDIE_MASK);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_FIFOERROR;
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)FALSE);
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)FALSE);
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_STATEMACHINEERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
/*subAddressSize ==0x00u,for support Interrupt*/
|
|
else if (((uint32)0x0U == u32I2cSlaveDmaStatus) && ((uint8)0X0U == pFciicSlaveHandle->tStatus.subaddressSize))
|
|
{
|
|
/*slave interrupt and subAddressSize=0 */
|
|
if ((FCIIC_CH_LISTENING == u8CurChSts || FCIIC_CH_IDLE == u8CurChSts))
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
if ((FCIIC_READ == (u32Raddr & FCIIC_DIR_MASK)))
|
|
{
|
|
FCIIC_Slave_HWA_Transmit(pFciic, pFciicSlaveHandle->tSettings.pData[pFciicSlaveHandle->tStatus.u16DataOffset]);
|
|
pFciicSlaveHandle->tStatus.u16DataOffset++;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_SENDING;
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_TDIE_MASK);
|
|
}
|
|
else if ((FCIIC_WRITE == (u32Raddr & FCIIC_DIR_MASK)))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_RECEIVING;
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_RDIE_MASK);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_STATEMACHINEERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)FALSE);
|
|
}
|
|
}
|
|
/*unknown error */
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Processes the IIC Slave RDF interrupt.
|
|
*
|
|
* This function processes the Receive Data Flag interrupt for the IIC Slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC slave handle structure.
|
|
* @param[in] u8CurChSts The status of the SSR flags.
|
|
*/
|
|
void FCIIC_SlaveInterruptProcessReceive(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSRECEIVE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSRECEIVE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
uint16 u16CurIdx;
|
|
uint8 u8SubAddrTotalLen;
|
|
uint8 u8SubAddrCurIdx;
|
|
uint8 u8ShiftWidth;
|
|
uint8 u8Data;
|
|
|
|
u8SubAddrTotalLen = pFciicSlaveHandle->tStatus.subaddressSize;
|
|
u8SubAddrCurIdx = pFciicSlaveHandle->tStatus.curSubaddressSize;
|
|
u16CurIdx = pFciicSlaveHandle->tStatus.u16DataOffset;
|
|
|
|
if (0x0U != pFciicSlaveHandle->tStatus.subaddressSize)
|
|
{
|
|
/*If the subaddress is fully received, change the state machine to FCIIC_CH_RECEIVING to prepare to send data */
|
|
if ((FCIIC_CH_LISTENING_READ == pFciicSlaveHandle->tStatus.eChannelStatus) && (pFciicSlaveHandle->tStatus.curSubaddressSize == pFciicSlaveHandle->tStatus.subaddressSize))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_RECEIVING;
|
|
if ((NULL != pFciicSlaveHandle->tSettings.pSubAddressReceivingCallback))
|
|
{
|
|
pFciicSlaveHandle->tSettings.pSubAddressReceivingCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
/*receive subAddress data*/
|
|
if ((FCIIC_CH_LISTENING_READ == pFciicSlaveHandle->tStatus.eChannelStatus) && (u8SubAddrCurIdx < u8SubAddrTotalLen))
|
|
{
|
|
if(pFciicSlaveHandle->tStatus.curSubaddressSize == 0x0U)
|
|
{
|
|
pFciicSlaveHandle->tStatus.u32CurSubaddress = 0x0U;
|
|
}
|
|
u8ShiftWidth = (uint8)((u8SubAddrTotalLen - u8SubAddrCurIdx - (uint8) 0X1U) << 0x3U);
|
|
u8Data = FCIIC_Slave_HWA_Receive(pFciic);
|
|
pFciicSlaveHandle->tStatus.u32CurSubaddress |= (uint32)(u8Data << u8ShiftWidth);
|
|
pFciicSlaveHandle->tStatus.curSubaddressSize = (uint8)(pFciicSlaveHandle->tStatus.curSubaddressSize + 1u);
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
}
|
|
/*receive data */
|
|
else if ((FCIIC_CH_RECEIVING == pFciicSlaveHandle->tStatus.eChannelStatus) && (u8SubAddrCurIdx == u8SubAddrTotalLen))
|
|
{
|
|
u16CurIdx = pFciicSlaveHandle->tStatus.u16DataOffset;
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
if (u16CurIdx < pFciicSlaveHandle->tStatus.u16DataSize)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pData[u16CurIdx] = FCIIC_Slave_HWA_Receive(pFciic);
|
|
pFciicSlaveHandle->tStatus.u16DataOffset = (uint16)(u16CurIdx + 1u);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_OVERFLOWERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
(void)FCIIC_Slave_HWA_Receive(pFciic);
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((FCIIC_CH_RECEIVING == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
if (u16CurIdx < pFciicSlaveHandle->tStatus.u16DataSize)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pData[u16CurIdx] = FCIIC_Slave_HWA_Receive(pFciic);
|
|
pFciicSlaveHandle->tStatus.u16DataOffset = (uint16)(u16CurIdx + 1u);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_OVERFLOWERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
(void)FCIIC_Slave_HWA_Receive(pFciic);
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)FALSE);
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Processes IIC Slave TDF interrupt.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
void FCIIC_SlaveInterruptProcessTransmit(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSTRANSMIT_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSTRANSMIT_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
uint16 u16CurIdx = pFciicSlaveHandle->tStatus.u16DataOffset;
|
|
|
|
if ((FCIIC_CH_SENDING == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
if (u16CurIdx <= pFciicSlaveHandle->tStatus.u16DataSize)
|
|
{
|
|
FCIIC_Slave_HWA_Transmit(pFciic, pFciicSlaveHandle->tSettings.pData[u16CurIdx]);
|
|
pFciicSlaveHandle->tStatus.u16DataOffset = (uint16)(u16CurIdx + 1u);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_OVERFLOWERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FCIIC_Slave_HWA_Transmit(pFciic, 0x00);
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_STATEMACHINEERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Processes IIC Slave SDF interrupt.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
void FCIIC_SlaveInterruptProcessStop(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSSTOP_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEINTERRUPTPROCESSSTOP_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
FCIIC_ChannelStatusType eChannelStatus = pFciicSlaveHandle->tStatus.eChannelStatus;
|
|
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_SDF_STATUS);
|
|
if (eChannelStatus == FCIIC_CH_SENDING || eChannelStatus == FCIIC_CH_RECEIVING)
|
|
{
|
|
/*Interrupt receive Successfully*/
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_STATEMACHINEERROR;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
if ((FCIIC_CH_TRANSFER_FINISHED == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicSlaveHandle->tStatus.eRunStatus = FCIIC_SUCCESS;
|
|
FCIIC_Slave_HWA_DisableInterrupt(pFciic, FCIIC_SIER_RDIE | FCIIC_SIER_TDIE);
|
|
if (0 != pFciicSlaveHandle->tStatus.subaddressSize)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pData = NULL;
|
|
pFciicSlaveHandle->tStatus.curSubaddressSize = 0;
|
|
}
|
|
if (NULL != pFciicSlaveHandle->tSettings.pCallback)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL != pFciicSlaveHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pErrorCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief I2C Slave Interrupt Service Routine (ISR).
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
void FCIIC_LL_SlaveIRQnHandler(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (pFciicSlaveHandle == NULL)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_SLAVEIRQNHANDLER_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_SLAVEIRQNHANDLER_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
uint32_t u8CurChSts, u32I2cSlaveDmaStatus;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
uint32_t u32ErrorValue;
|
|
u8CurChSts = FCIIC_HWA_GetSSR(pFciic);
|
|
u8CurChSts &= FCIIC_HWA_GetSIER(pFciic);
|
|
u32I2cSlaveDmaStatus = FCIIC_HWA_GetSDER(pFciic);
|
|
if (0 != (u8CurChSts & FCIIC_SlaveErrorFlags))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
else if (((uint32_t)0x03 != u32I2cSlaveDmaStatus))
|
|
{
|
|
if (0 != (u8CurChSts & FCIIC_SSR_AM0F))
|
|
{
|
|
FCIIC_SlaveInterruptProcessAddressMatch(pFciicSlaveHandle, u8CurChSts);
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_SSR_RDF)))
|
|
{
|
|
FCIIC_SlaveInterruptProcessReceive(pFciicSlaveHandle);
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_SSR_TDF)))
|
|
{
|
|
FCIIC_SlaveInterruptProcessTransmit(pFciicSlaveHandle);
|
|
}
|
|
else if ((0 != (u8CurChSts & FCIIC_SSR_SDF)))
|
|
{
|
|
FCIIC_SlaveInterruptProcessStop(pFciicSlaveHandle);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else if ((u32I2cSlaveDmaStatus==0x03)&&((NULL != pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->pDmaHandle)) && (NULL != pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->pDmaHandle))
|
|
{
|
|
if (0 != (u8CurChSts & FCIIC_SSR_AM0F))
|
|
{
|
|
FCIIC_SlaveStartDMA(pFciicSlaveHandle);
|
|
}
|
|
else if (0 != (u8CurChSts & FCIIC_SSR_SDF))
|
|
{
|
|
FCIIC_SlaveDMAStageNotification(pFciicSlaveHandle);
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
if (FCIIC_CH_ERROR_PRESENT == pFciicSlaveHandle->tStatus.eChannelStatus)
|
|
{
|
|
u32ErrorValue = FCIIC_SlaveGetError(pFciicSlaveHandle);
|
|
if ((u32ErrorValue != 0U))
|
|
{
|
|
FCIIC_SlaveClrError(pFciicSlaveHandle);
|
|
}
|
|
if ((NULL != pFciicSlaveHandle->tSettings.pErrorCallback))
|
|
{
|
|
pFciicSlaveHandle->tSettings.pErrorCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Starts accepting slave transfers in non-blocking mode.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*
|
|
* @return FCIIC_StatusType Status indicating whether the start was successful.
|
|
*/
|
|
FCIIC_StatusType FCIIC_SlaveTransferNonBlocking(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
FCIIC_StatusType result = FCIIC_SUCCESS;
|
|
FCIIC_Type *pFciic;
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVETRANSFERNONBLOCKING_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVETRANSFERNONBLOCKING_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if ((NULL != pFciicSlaveHandle) && (pFciicSlaveHandle->eInstance < FCIIC_INSTANCE_COUNT))
|
|
{
|
|
pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
if (true == pFciicSlaveHandle->tStatus.bUsed) /* Check if the I2C bus is idle - if not return busy status. */
|
|
{
|
|
result = FCIIC_BUSY;
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.bUsed = true;
|
|
FCIIC_Slave_HWA_DisableInterrupt(pFciic, FCIIC_SlaveIrqFlags);
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SlaveClearFlags);
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_AM0IE | FCIIC_SIER_SDIE); /* Enable I2C internal IRQ sources */
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_LISTENING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = FCIIC_FAIL;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Prepares DMA configuration for IIC Slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
|
|
void FCIIC_SlaveDmaPrepare(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDMAPREPARE_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDMAPREPARE_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_HandleType *pDmaHandle = NULL;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
DMA_ChannelCfgType FCIIC_DmaChannelAttr = {0};
|
|
|
|
FCIIC_DmaChannelAttr.eSrcDataSize = DMA_TRANSFER_SIZE_1B;
|
|
FCIIC_DmaChannelAttr.eDestDataSize = DMA_TRANSFER_SIZE_1B;
|
|
FCIIC_DmaChannelAttr.u32BlockSize = (uint32_t)0x1u;
|
|
FCIIC_DmaChannelAttr.u16BlockCount = (uint16_t)pFciicSlaveHandle->tStatus.u16DataSize;
|
|
|
|
FCIIC_DmaChannelAttr.bSrcBlockOffsetEn = false;
|
|
FCIIC_DmaChannelAttr.bDestBlockOffsetEn = false;
|
|
FCIIC_DmaChannelAttr.s32BlockOffset = 0;
|
|
FCIIC_DmaChannelAttr.bSrcAddrLoopbackEn = true;
|
|
FCIIC_DmaChannelAttr.bDestAddrLoopbackEn = false;
|
|
FCIIC_DmaChannelAttr.bAutoStop = true;
|
|
FCIIC_DmaChannelAttr.bSrcCircularBufferEn = false;
|
|
FCIIC_DmaChannelAttr.u32SrcCircBufferSize = 0;
|
|
FCIIC_DmaChannelAttr.bDestCircularBufferEn = false;
|
|
FCIIC_DmaChannelAttr.u32DestCircBufferSize = 0;
|
|
|
|
FCIIC_DmaChannelAttr.bTransferCompleteIntEn = true;
|
|
FCIIC_DmaChannelAttr.bTransferErrorIntEn = false;
|
|
FCIIC_DmaChannelAttr.pTransferErrorNotify = NULL;
|
|
FCIIC_DmaChannelAttr.completedata = NULL;
|
|
FCIIC_DmaChannelAttr.errdata = NULL;
|
|
|
|
if (NULL != pFciicSlaveHandle->tSettings.pFciicTxDmaConfig)
|
|
{
|
|
FCIIC_DmaChannelAttr.pSrcBuffer = &(pFciicSlaveHandle->tSettings.pData[0]);
|
|
FCIIC_DmaChannelAttr.pDestBuffer = &(pFciic->STDR);
|
|
FCIIC_DmaChannelAttr.eSrcIncMode = DMA_INCREMENT_DATA_SIZE ;
|
|
FCIIC_DmaChannelAttr.eDestIncMode = DMA_INCREMENT_DISABLE;
|
|
pDmaHandle = pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->pDmaHandle;
|
|
FCIIC_DmaChannelAttr.u8ChannelPriority = pDmaHandle->tSettings.u8Channel;
|
|
FCIIC_DmaChannelAttr.pTransferCompleteNotify = pDmaHandle->tSettings.callback.pTransferCompleteCallback;
|
|
|
|
if (FCIIC_INSTANCE_0 == pFciicSlaveHandle->eInstance)
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC0_TX;
|
|
}
|
|
else
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC1_TX;
|
|
}
|
|
DMA_InitChannel(pDmaHandle, &FCIIC_DmaChannelAttr);
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_IDLE;
|
|
}
|
|
|
|
if (NULL != pFciicSlaveHandle->tSettings.pFciicRxDmaConfig)
|
|
{
|
|
FCIIC_DmaChannelAttr.pSrcBuffer = &(pFciic->SRDR);
|
|
FCIIC_DmaChannelAttr.pDestBuffer = &(pFciicSlaveHandle->tSettings.pData[0]);
|
|
FCIIC_DmaChannelAttr.eSrcIncMode = DMA_INCREMENT_DISABLE ;
|
|
FCIIC_DmaChannelAttr.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
|
|
pDmaHandle = pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->pDmaHandle;
|
|
FCIIC_DmaChannelAttr.u8ChannelPriority = pDmaHandle->tSettings.u8Channel;
|
|
FCIIC_DmaChannelAttr.pTransferCompleteNotify = pDmaHandle->tSettings.callback.pTransferCompleteCallback;
|
|
if (FCIIC_INSTANCE_0 == pFciicSlaveHandle->eInstance)
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC0_RX;
|
|
}
|
|
else
|
|
{
|
|
FCIIC_DmaChannelAttr.eTriggerSrc = DMA_REQ_FCIIC1_RX;
|
|
}
|
|
DMA_InitChannel(pDmaHandle, &FCIIC_DmaChannelAttr);
|
|
pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_IDLE;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Initiates an IIC Slave Asynchronous DMA transfer.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*
|
|
* @return FCIIC_StatusType Status indicating whether the DMA transfer was successful.
|
|
*/
|
|
FCIIC_StatusType FCIIC_SlaveTransferDMA(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVETRANSFERDMA_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVETRANSFERDMA_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
|
|
if (true == pFciicSlaveHandle->tStatus.bUsed) /* Check if the I2C bus is idle - if not return busy status. */
|
|
{
|
|
return FCIIC_BUSY;
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.bUsed = true;
|
|
FCIIC_Slave_HWA_DisableInterrupt(pFciic, FCIIC_SlaveIrqFlags);
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SlaveClearFlags);
|
|
FCIIC_SlaveDmaPrepare(pFciicSlaveHandle);
|
|
/*When using DMA, the AM0IE interrupt is used to match the address and open the corresponding DMA request,
|
|
* and then the SDIE interrupt is used to process the logic after the DMA handling is completed.*/
|
|
FCIIC_Slave_HWA_EnableInterrupt(pFciic, FCIIC_SIER_AM0IE | FCIIC_SIER_SDIE);
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_LISTENING;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
return FCIIC_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Starts DMA for IIC Slave in asynchronous mode.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
void FCIIC_SlaveDMAStageNotification(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDMASTAGENOTIFICATION_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVEDMASTAGENOTIFICATION_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
DMA_StatusType ret;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
FCIIC_ChannelStatusType eChannelStatus = pFciicSlaveHandle->tStatus.eChannelStatus;
|
|
FCIIC_DmaConfigType *pFciicRxDmaConfig = pFciicSlaveHandle->tSettings.pFciicRxDmaConfig;
|
|
FCIIC_DmaConfigType *pFciicTxDmaConfig = pFciicSlaveHandle->tSettings.pFciicTxDmaConfig;
|
|
DMA_Type *aDma[] = DMA_BASE_PTRS;
|
|
DMA_Type *const pDma = aDma[pFciicTxDmaConfig->pDmaHandle->tSettings.pInstance->tSettings.u8Instance];
|
|
|
|
uint32_t u32FciicTxSrcAddr = DMA_HWA_GetSrcAddr(pDma, pFciicTxDmaConfig->pDmaHandle->tSettings.u8Channel);
|
|
uint32_t u32FciicRxDstAddr = DMA_HWA_GetDestAddr(pDma, pFciicRxDmaConfig->pDmaHandle->tSettings.u8Channel) - pFciicSlaveHandle->tStatus.u16DataSize;
|
|
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_SDF_STATUS);
|
|
if ((eChannelStatus == FCIIC_CH_SENDING) && (FCIIC_DMA_NEXT_STAGE_DATA == pFciicTxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
/*DMA less send,But more bytes are required to transfer,*/
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_TREF_STATUS);
|
|
ret = DMA_ModifyAddress(pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->pDmaHandle, (const volatile void *)pFciicSlaveHandle->tSettings.pData,
|
|
(const volatile void *)(pFciic->STDR));
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_SLAVEDMANUMBERERROR;
|
|
}
|
|
/*DMA less receive,But not all bytes are transferred completely*/
|
|
else if ((eChannelStatus == FCIIC_CH_RECEIVING) && (FCIIC_DMA_NEXT_STAGE_DATA == pFciicRxDmaConfig->u8I2cDmaNextStage))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_TREF_STATUS);
|
|
ret = DMA_ModifyAddress(pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->pDmaHandle, (const volatile void *)(pFciic->SRDR),
|
|
(const volatile void *)pFciicSlaveHandle->tSettings.pData);
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_SLAVEDMANUMBERERROR;
|
|
}
|
|
/*DMA more send error*/
|
|
else if ((eChannelStatus == FCIIC_CH_TRANSFER_FINISHED) && (pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage == FCIIC_DMA_NEXT_STAGE_STOP))
|
|
{
|
|
if ((u32FciicTxSrcAddr == ((uint32)pFciicSlaveHandle->tSettings.pData)))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_NOTIFICATION;
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_TREF_STATUS);
|
|
ret = DMA_ModifyAddress(pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->pDmaHandle, pFciicSlaveHandle->tSettings.pData, (const volatile void *)(pFciic->STDR));
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_SLAVEDMANUMBERERROR;
|
|
}
|
|
}
|
|
/*DMA more receive error*/
|
|
else if ((eChannelStatus == FCIIC_CH_TRANSFER_FINISHED) && (pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage == FCIIC_DMA_NEXT_STAGE_STOP))
|
|
{
|
|
if ((u32FciicRxDstAddr == ((uint32)pFciicSlaveHandle->tSettings.pData)))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_IDLE;
|
|
pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_NOTIFICATION;
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
FCIIC_Slave_HWA_ClrStatus(pFciic, FCIIC_SSR_TREF_STATUS);
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_SLAVEDMANUMBERERROR;
|
|
ret = DMA_ModifyAddress(pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->pDmaHandle, (const volatile void *)(pFciic->SRDR), pFciicSlaveHandle->tSettings.pData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
|
|
if ((ret == DMA_STATUS_BUSY))
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_DMAREQUESTFAIL;
|
|
}
|
|
|
|
if ((FCIIC_CH_IDLE == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
if(pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage == FCIIC_DMA_NEXT_STAGE_NOTIFICATION)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_IDLE;
|
|
}
|
|
if(pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage == FCIIC_DMA_NEXT_STAGE_NOTIFICATION)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_IDLE;
|
|
}
|
|
pFciicSlaveHandle->tStatus.bUsed = false;
|
|
pFciicSlaveHandle->tStatus.eRunStatus = FCIIC_SUCCESS;
|
|
if (NULL != pFciicSlaveHandle->tSettings.pCallback)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (NULL != pFciicSlaveHandle->tSettings.pErrorCallback)
|
|
{
|
|
pFciicSlaveHandle->tSettings.pErrorCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Starts DMA for IIC Slave in asynchronous mode.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
void FCIIC_SlaveStartDMA(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVESTARTDMA_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_SLAVESTARTDMA_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
FCIIC_DmaStatusType eDmaNextStage;
|
|
FCIIC_Type *pFciic = (FCIIC_Type *)s_aFCIIC_InstanceTable[pFciicSlaveHandle->eInstance];
|
|
FCIIC_ChannelStatusType eChannelStatus;
|
|
FCIIC_DirectionType eDirection = (FCIIC_DirectionType)(FCIIC_HWA_GetSASR(pFciic)& FCIIC_DIR_MASK);
|
|
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = eDirection == FCIIC_READ ? FCIIC_CH_LISTENING : FCIIC_CH_LISTENING_READ;
|
|
|
|
eDmaNextStage = FCIIC_READ == eDirection ?
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage : pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage;
|
|
|
|
eChannelStatus = pFciicSlaveHandle->tStatus.eChannelStatus;
|
|
|
|
if ((FCIIC_WRITE == eDirection) && (FCIIC_CH_LISTENING_READ == eChannelStatus) && (eDmaNextStage == FCIIC_DMA_NEXT_STAGE_IDLE))
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_RECEIVING;
|
|
pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_DATA;
|
|
DMA_StartChannel(pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->pDmaHandle);
|
|
}
|
|
else if ((FCIIC_READ == eDirection) && (FCIIC_CH_LISTENING == eChannelStatus) && (eDmaNextStage == FCIIC_DMA_NEXT_STAGE_IDLE))
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)TRUE);
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_SENDING;
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_DATA;
|
|
DMA_StartChannel(pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->pDmaHandle);
|
|
}
|
|
else
|
|
{
|
|
FCIIC_SlaveAck(pFciicSlaveHandle, (boolean)FALSE);
|
|
if(eDmaNextStage != FCIIC_DMA_NEXT_STAGE_IDLE)
|
|
{
|
|
pFciicSlaveHandle->tStatus.eRunStatus |= FCIIC_STATEMACHINEERROR;
|
|
}
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief DMA handler for IIC Slave.
|
|
*
|
|
* @param[in] pFciicSlaveHandle Pointer to the FCIIC Slave handle.
|
|
*/
|
|
void FCIIC_LL_SlaveDmaIRQnHandler(FCIIC_SlaveHandleType *const pFciicSlaveHandle)
|
|
{
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
if (NULL == pFciicSlaveHandle)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_SLAVEDMAIRQNHANDLER_ID, FCIIC_E_PARAM_NULLPTR);
|
|
}
|
|
else if (pFciicSlaveHandle->eInstance >= FCIIC_INSTANCE_COUNT)
|
|
{
|
|
FCIIC_ReportDevError(FCIIC_LL_SLAVEDMAIRQNHANDLER_ID, FCIIC_E_PARAM_INSTANCE);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
|
|
if ((FCIIC_DMA_NEXT_STAGE_DATA == pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage) && (FCIIC_CH_RECEIVING == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
pFciicSlaveHandle->tSettings.pFciicRxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_STOP;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
}
|
|
else if ((FCIIC_DMA_NEXT_STAGE_DATA == pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage) && (FCIIC_CH_SENDING == pFciicSlaveHandle->tStatus.eChannelStatus))
|
|
{
|
|
pFciicSlaveHandle->tSettings.pFciicTxDmaConfig->u8I2cDmaNextStage = FCIIC_DMA_NEXT_STAGE_STOP;
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_TRANSFER_FINISHED;
|
|
}
|
|
else
|
|
{
|
|
pFciicSlaveHandle->tStatus.eChannelStatus = FCIIC_CH_ERROR_PRESENT;
|
|
}
|
|
if (pFciicSlaveHandle->tStatus.eChannelStatus == FCIIC_CH_ERROR_PRESENT)
|
|
{
|
|
FCIIC_SlaveGetError(pFciicSlaveHandle);
|
|
if ((NULL != pFciicSlaveHandle->tSettings.pErrorCallback))
|
|
{
|
|
FCIIC_SlaveClrError(pFciicSlaveHandle);
|
|
pFciicSlaveHandle->tSettings.pErrorCallback(pFciicSlaveHandle);
|
|
}
|
|
}
|
|
#if FCIIC_DEV_ERROR_REPORT == STD_ON
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif
|