/** * @file module_driver_port.c * @author Flagchip * @brief PORT driver type definition and API * @version 2.0.0 * @date 2023-2-4 * * SDK Version: 2.6.0 * * @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd. * * @details */ /******************************************************************************** * Revision History: * * Version Date Initials CR# Descriptions * --------- ---------- ------------ ---------- --------------- * 0.1.0 31/12/2022 Flagchip071 N/A First version for FC7300 * 0.2.0 4/2/2022 Flagchip071 N/A 0.2.0 release ********************************************************************************/ #include "module_driver_port.h" #if PORT_INSTANCE_COUNT > 0U #ifndef PORT_DEV_ERROR_REPORT #define PORT_DEV_ERROR_REPORT STD_OFF #endif #if PORT_DEV_ERROR_REPORT == STD_ON #define PORT_ReportDevError(func, error) ReportDevError(PORT_MODULE_ID, func, error) #endif /********* Local Variables ************/ /** @brief PORT instance list */ static PORT_Type *const s_pPortInstanceTable[PORT_INSTANCE_COUNT] = PORT_BASE_PTRS; /** @brief Gpio instance list */ static GPIO_Type *const s_pGpioInstanceTable[PORT_INSTANCE_COUNT] = GPIO_BASE_PTRS; #if PORT_DEV_ERROR_REPORT == STD_ON /** @brief Pin mask list */ static uint32_t const s_pPinMaskTable[GPIO_INSTANCE_COUNT] = GPIO_PIN_MASK; #endif /** @brief port common interrupt handle function */ static void Port_CommonProcessInterrupt(PORT_HandleType *pPortHandle, const uint8_t u32Pin); /***************PORT Global Functions*****************/ /** * @brief Initialize port * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param pInitStruct Initialization structure of port */ void PORT_InitPins(PORT_HandleType *pPortHandle, const PORT_InitType *const pInitStruct) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = pInitStruct->u32PortPins; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INSTANCE); } else if (NULL == pInitStruct) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_PIN); } else { #endif uint32_t u32PcrRegValue = 0U; uint32_t u32TempPins = 0U; uint8_t u8PinIndex = 0U; PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *const pPort = s_pPortInstanceTable[ePort]; GPIO_Type *const pGpio = s_pGpioInstanceTable[ePort]; u32TempPins = pInitStruct->u32PortPins; while (u32TempPins) { if (u32TempPins & ((uint32_t)1 << u8PinIndex)) { u32PcrRegValue |= PORT_PCR_MUX(pInitStruct->uPortPinMux.u32PortPinMode); if (pInitStruct->bPullEn) { if (PORT_ALT0_FUNC_MODE != pInitStruct->uPortPinMux.u32PortPinMode) { u32PcrRegValue |= PORT_PCR_PE(1U); if (PORT_PULL_UP == pInitStruct->ePullSel) { u32PcrRegValue |= PORT_PCR_PS(1U); } else { u32PcrRegValue &= ~(uint32_t)PORT_PCR_PS_MASK; } } } else { u32PcrRegValue &= ~(uint32_t)PORT_PCR_PE_MASK; } if (pInitStruct->bDrvStrengthEn) { u32PcrRegValue |= (uint32_t)PORT_PCR_DSE0_MASK; u32PcrRegValue |= (uint32_t)PORT_PCR_DSE1_MASK; } if (pInitStruct->bPassiveFilterEn) { u32PcrRegValue |= PORT_PCR_PFE(1); } else { u32PcrRegValue &= ~(uint32_t)PORT_PCR_PFE_MASK; } u32PcrRegValue |= PORT_PCR_ISF_MASK; if (PORT_GPIO_MODE == pInitStruct->uPortPinMux.u32PortPinMode) { if (PORT_GPIO_OUT == pInitStruct->ePortGpioDir) { if (PORT_GPIO_LOW == pInitStruct->ePortGpioLevel) { GPIO_HWA_ClearPinOutput(pGpio, u8PinIndex); } else { GPIO_HWA_SetPinOutput(pGpio, u8PinIndex); } GPIO_HWA_SetPinDirection(pGpio, u8PinIndex); } else if (PORT_GPIO_IN == pInitStruct->ePortGpioDir) { GPIO_HWA_ClearPinDirection(pGpio, u8PinIndex); } else { u32PcrRegValue &= ~(PORT_PCR_MUX_MASK); } } PORT_HWA_ConfigPin(pPort, u8PinIndex, u32PcrRegValue); PORT_HWA_ClearPinInterruptFlag(pPort, u8PinIndex); PORT_HWA_SetPinInterruptMode(pPort, u8PinIndex, (PORT_IrqcConfigurationType)pInitStruct->tInterruptCfg.ePortIsrMode); } u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); u8PinIndex++; } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief De-initialize the Port instance * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. */ void PORT_Deinit(PORT_HandleType *pPortHandle, const uint32_t u32Pins) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = u32Pins; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_Deinit_ID, PORT_E_PARAM_INSTANCE); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_Deinit_ID, PORT_E_PARAM_PIN); } else { #endif PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *const pPort = s_pPortInstanceTable[ePort]; uint8_t u8PinIndex = 0U; uint32_t u32TempPins = u32Pins; while (u32TempPins) { if (u32TempPins & ((uint32_t)1 << u8PinIndex)) { PORT_HWA_ConfigPin(pPort, u8PinIndex, (uint32_t)0U); pPortHandle->tSettings.PORT_PinInterruptCallBackType = NULL; } u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); u8PinIndex++; } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief set Emergency Stop of pin * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. * @param bEnable Enable or Disable. */ void PORT_EnableEmergencyStop(PORT_HandleType *pPortHandle, const uint32_t u32Pins, bool bEnable) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = u32Pins; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_SetPinEmergencyStop_ID, PORT_E_PARAM_INSTANCE); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_SetPinEmergencyStop_ID, PORT_E_PARAM_PIN); } else { #endif PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *pPort = s_pPortInstanceTable[ePort]; uint8_t u8PinIndex = 0U; uint32_t u32TempPins = u32Pins; while (u32TempPins != 0u) { if ((u32TempPins & ((uint32_t)1 << u8PinIndex)) != 0u) { PORT_HWA_SetPinEmgcyStop(pPort, u8PinIndex, bEnable); } u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); u8PinIndex++; } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief set interrupt config of port * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. * @param ePortPinIrq The config of interrupt. */ void PORT_SetInterruptCfg(PORT_HandleType *pPortHandle, const uint32_t u32Pins, PORT_IrqcConfigurationType ePortPinIrq) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = u32Pins; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_SetInterruptCfg_ID, PORT_E_PARAM_INSTANCE); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_SetInterruptCfg_ID, PORT_E_PARAM_PIN); } else { #endif uint8_t u8PinIndex = 0U; uint32_t u32TempPins = u32Pins; PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *const pPort = s_pPortInstanceTable[ePort]; while (u32TempPins) { if (u32TempPins & ((uint32_t)1 << u8PinIndex)) { PORT_HWA_ClearPinInterruptFlag(pPort, u8PinIndex); PORT_HWA_SetPinInterruptMode(pPort, u8PinIndex, ePortPinIrq); } u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); u8PinIndex++; } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief Initialize digital filter for Port instance * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param pDFStruct Digital filter initialization structure of port */ void PORT_InitDigitalFilterPort(PORT_HandleType *pPortHandle, const PORT_DigitalFilterType *const pDFStruct) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = pDFStruct->u32PortPinsEn; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_InitDigitalFilterPort_ID, PORT_E_PARAM_INSTANCE); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_InitDigitalFilterPort_ID, PORT_E_PARAM_PIN); } else { #endif PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *const pPort = s_pPortInstanceTable[ePort]; if (0u != pDFStruct->u32PortPinsEn) { if (PORT_FILTER_AON32K_CLK == pDFStruct->eClkSrc) { PORT_HWA_SetDigitalFilterClkSrc(pPort); } else { PORT_HWA_ClearDigitalFilterClkSrc(pPort); } PORT_HWA_ConfigDigitalFilterWidth(pPort, (uint32_t)pDFStruct->u8FilterLength); PORT_HWA_ConfigDigitalFilter(pPort, pDFStruct->u32PortPinsEn); } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief De-initialize digital filter for Port instance * * @param pPortHandle pPortHandle PORT handle for PORT functionality */ void PORT_DeinitDigitalFilterPort(PORT_HandleType *pPortHandle) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_DeinitDigitalFilterPort_ID, PORT_E_PARAM_INSTANCE); } else { #endif PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *const pPort = s_pPortInstanceTable[ePort]; PORT_HWA_ClearDigitalFilterClkSrc(pPort); PORT_HWA_ClearDigitalFilterWidth(pPort); PORT_HWA_ClearDigitalFilterEnable(pPort); #if PORT_DEV_ERROR_REPORT == STD_ON } #endif } /** * @brief Enable the digital filter function for the specific pin. * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. */ void PORT_EnableDigitalFilterPin(PORT_HandleType *pPortHandle, const uint32_t u32Pins) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = u32Pins; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_EnableDigitalFilterPin_ID, PORT_E_PARAM_INSTANCE); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_EnableDigitalFilterPin_ID, PORT_E_PARAM_PIN); } else { #endif PORT_InstanceType ePort = pPortHandle->eInstance; uint8_t u8PinIndex = 0U; uint32_t u32TempPins = u32Pins; PORT_Type *const pPort = s_pPortInstanceTable[ePort]; while (u32TempPins) { if (u32TempPins & ((uint32_t)1 << u8PinIndex)) { PORT_HWA_SetDigitalFilterEnable(pPort, u8PinIndex); } u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); u8PinIndex++; } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief Disable the digital filter function for the specific pin. * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param u32Pins The bit of u32Pins indicate the Pin number of this Port. */ void PORT_DisableDigitalFilterPin(PORT_HandleType *pPortHandle, const uint32_t u32Pins) { #if PORT_DEV_ERROR_REPORT == STD_ON if (NULL == pPortHandle) { PORT_ReportDevError(PORT_InitPins_ID, PORT_E_PARAM_INPUT); } else { uint32_t u32DetPins = u32Pins; uint32_t u32ValidPins = s_pPinMaskTable[pPortHandle->eInstance]; if (pPortHandle->eInstance >= PORT_INSTANCE_COUNT) { PORT_ReportDevError(PORT_DisableDigitalFilterPin_ID, PORT_E_PARAM_INSTANCE); } else if (u32DetPins != (u32DetPins & u32ValidPins)) { PORT_ReportDevError(PORT_DisableDigitalFilterPin_ID, PORT_E_PARAM_PIN); } else { #endif PORT_InstanceType ePort = pPortHandle->eInstance; uint8_t u8PinIndex = 0U; uint32_t u32TempPins = u32Pins; PORT_Type *pPort; pPort = s_pPortInstanceTable[ePort]; while (u32TempPins) { if (u32TempPins & ((uint32_t)1 << u8PinIndex)) { PORT_HWA_ClearDigitalFilterPin(pPort, u8PinIndex); } u32TempPins &= (uint32_t)~((uint32_t)1 << u8PinIndex); u8PinIndex++; } #if PORT_DEV_ERROR_REPORT == STD_ON } } #endif } /** * @brief port common interrupt handle function * * @param pPortHandle pPortHandle PORT handle for PORT functionality * @param u8Pin bit of u8Pin indicate pin number */ static void Port_CommonProcessInterrupt(PORT_HandleType *pPortHandle, const uint8_t u8Pin) { if (NULL != pPortHandle->tSettings.PORT_PinInterruptCallBackType) { pPortHandle->tSettings.PORT_PinInterruptCallBackType(pPortHandle, (uint32_t)1 << u8Pin); } } /***************PORT IRQ Functions*****************/ /** * @brief PORT interrupt process function * @param pPortHandle pPortHandle PORT handle for PORT functionality */ void PORT_IRQHandler(PORT_HandleType *pPortHandle) { uint8_t u8PinIndex; PORT_InstanceType ePort = pPortHandle->eInstance; PORT_Type *pPort = s_pPortInstanceTable[ePort]; for (u8PinIndex = 0U; u8PinIndex < (uint32_t)32; u8PinIndex++) { if (PORT_HWA_ReadPinInterruptFlag(pPort, u8PinIndex)) { PORT_HWA_ClearPinInterruptFlag(pPort, u8PinIndex); Port_CommonProcessInterrupt(pPortHandle, u8PinIndex); } } } #endif