/*================================================================================================== * Project : RTD AUTOSAR 4.4 * Platform : CORTEXM * Peripheral : * Dependencies : none * * Autosar Version : 4.4.0 * Autosar Revision : ASR_REL_4_4_REV_0000 * Autosar Conf.Variant : * SW Version : 0.9.0 * Build Version : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326 * * (c) Copyright 2020 - 2021 NXP Semiconductors * All Rights Reserved. * * NXP Confidential. This software is owned or controlled by NXP and may only be * used strictly in accordance with the applicable license terms. By expressly * accepting such terms or by downloading, installing, activating and/or otherwise * using the software, you are agreeing that you have read, and that you agree to * comply with and are bound by, such license terms. If you do not agree to be * bound by the applicable license terms, then you may not retain, install, * activate or otherwise use the software. ==================================================================================================*/ /** * @file Clock_Ip_IntOsc.c * @version 0.9.0 * * @brief CLOCK driver implementations. * @details CLOCK driver implementations. * * @addtogroup CLOCK_DRIVER Clock Ip Driver * @{ */ /** * @page misra_violations MISRA-C:2012 violations * * @section Clock_Ip_IntOsc_c_REF_1 * Violates MISRA 2012 Advisory Rule 20.1, #include directives should only be preceded by preprocessor * directives or comments. AUTOSAR imposes the specification of the sections in which certain parts * of the driver must be placed. * * @section Clock_Ip_IntOsc_c_REF_2 * Violates MISRA 2012 Advisory Rule 4.8, This file includes the definition * of types but does not use it. Header is common for all files * */ #include "Clock_Ip_Private.h" /*================================================================================================== SOURCE FILE VERSION INFORMATION ==================================================================================================*/ #define CLOCK_IP_INTOSC_VENDOR_ID_C 43 #define CLOCK_IP_INTOSC_AR_RELEASE_MAJOR_VERSION_C 4 #define CLOCK_IP_INTOSC_AR_RELEASE_MINOR_VERSION_C 4 #define CLOCK_IP_INTOSC_AR_RELEASE_REVISION_VERSION_C 0 #define CLOCK_IP_INTOSC_SW_MAJOR_VERSION_C 0 #define CLOCK_IP_INTOSC_SW_MINOR_VERSION_C 9 #define CLOCK_IP_INTOSC_SW_PATCH_VERSION_C 0 /*================================================================================================== * FILE VERSION CHECKS ==================================================================================================*/ /* Check if Clock_Ip_IntOsc.c file and Clock_Ip_Private.h file are of the same vendor */ #if (CLOCK_IP_INTOSC_VENDOR_ID_C != CLOCK_IP_PRIVATE_VENDOR_ID) #error "Clock_Ip_IntOsc.c and Clock_Ip_Private.h have different vendor ids" #endif /* Check if Clock_Ip_IntOsc.c file and Clock_Ip_Private.h file are of the same Autosar version */ #if ((CLOCK_IP_INTOSC_AR_RELEASE_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MAJOR_VERSION) || \ (CLOCK_IP_INTOSC_AR_RELEASE_MINOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MINOR_VERSION) || \ (CLOCK_IP_INTOSC_AR_RELEASE_REVISION_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_REVISION_VERSION) \ ) #error "AutoSar Version Numbers of Clock_Ip_IntOsc.c and Clock_Ip_Private.h are different" #endif /* Check if Clock_Ip_IntOsc.c file and Clock_Ip_Private.h file are of the same Software version */ #if ((CLOCK_IP_INTOSC_SW_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MAJOR_VERSION) || \ (CLOCK_IP_INTOSC_SW_MINOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MINOR_VERSION) || \ (CLOCK_IP_INTOSC_SW_PATCH_VERSION_C != CLOCK_IP_PRIVATE_SW_PATCH_VERSION) \ ) #error "Software Version Numbers of Clock_Ip_IntOsc.c and Clock_Ip_Private.h are different" #endif /* Clock start section code */ #define MCU_START_SEC_CODE /** * @violates @ref Clock_Ip_IntOsc_c_REF_1 #include directives should only be preceded by preprocessor * directives or comments. */ #include "Mcu_MemMap.h" static void InternalOscillatorEmpty(Clock_Ip_IrcoscConfigType const* config); #ifdef FIRC_STDBY_ENABLE static void FircStdbyEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef SIRC_STDBY_ENABLE static void SircStdbyEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef SIRC_ENABLE static status_t SircEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef SIRC_VLP_ENABLE static SircVlpEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef SIRC_STOP_ENABLE static SircStopEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef FIRC_ENABLE static status_t FIRCEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef FIRC_VLP_ENABLE static FIRCVlpEnable(Clock_Ip_IrcoscConfigType const* config); #endif #ifdef FIRC_STOP_ENABLE static FIRCStopEnable(Clock_Ip_IrcoscConfigType const* config); #endif /* Clock stop section code */ #define MCU_STOP_SEC_CODE /** * @violates @ref Clock_Ip_IntOsc_c_REF_1 #include directives should only be preceded by preprocessor * directives or comments. */ #include "Mcu_MemMap.h" /* Clock start constant section data */ #define MCU_START_SEC_CONST_UNSPECIFIED /** * @violates @ref Clock_Ip_IntOsc_c_REF_1 #include directives should only be preceded by preprocessor * directives or comments. */ #include "Mcu_MemMap.h" const intOscCallback intOscCallbacks[IRCOSC_CALLBACKS_COUNT] = { { InternalOscillatorEmpty, /* Set */ }, #ifdef FIRC_STDBY_ENABLE { FircStdbyEnable, /* Set */ }, #endif #ifdef SIRC_STDBY_ENABLE { SircStdbyEnable, /* Set */ }, #endif #ifdef SIRC_ENABLE { SircEnable, /* Set */ }, #endif #ifdef SIRC_VLP_ENABLE { SircVlpEnable, /* Set */ }, #endif #ifdef SIRC_STOP_ENABLE { SircStopEnable, /* Set */ }, #endif #ifdef FIRC_ENABLE { FIRCEnable, /* Set */ }, #endif #ifdef FIRC_VLP_ENABLE { FIRCVlpEnable, /* Set */ }, #endif #ifdef FIRC_STOP_ENABLE { FIRCStopEnable, /* Set */ }, #endif }; /* Clock stop constant section data */ #define MCU_STOP_SEC_CONST_UNSPECIFIED /** * @violates @ref Clock_Ip_IntOsc_c_REF_1 #include directives should only be preceded by preprocessor * directives or comments. */ #include "Mcu_MemMap.h" /* Clock start section code */ #define MCU_START_SEC_CODE /** * @violates @ref Clock_Ip_IntOsc_c_REF_1 #include directives should only be preceded by preprocessor * directives or comments. */ #include "Mcu_MemMap.h" static void InternalOscillatorEmpty(Clock_Ip_IrcoscConfigType const* config) { (void)config; /* No implementation */ } #ifdef FIRC_STDBY_ENABLE static void FircStdbyEnable(Clock_Ip_IrcoscConfigType const* config) { if (config->enable != 0U) { FIRC->STDBY_ENABLE |= FIRC_STDBY_ENABLE_STDBY_EN_MASK; /* Update Clock state for FIRC_STANDBY_CLK to enable */ UpdateClockState(config->name, ENABLED_CLOCK); } else { FIRC->STDBY_ENABLE &= ~FIRC_STDBY_ENABLE_STDBY_EN_MASK; /* Update Clock state for FIRC_STANDBY_CLK to disable */ UpdateClockState(config->name, DISABLED_CLOCK); } } #endif #ifdef SIRC_STDBY_ENABLE static void SircStdbyEnable(Clock_Ip_IrcoscConfigType const* config) { if (config->enable != 0U) { SIRC->MISCELLANEOUS_IN |= SIRC_MISCELLANEOUS_IN_STANDBY_ENABLE_MASK; /* Update Clock state for SIRC_STANDBY_CLK to enable */ UpdateClockState(config->name, ENABLED_CLOCK); } else { SIRC->MISCELLANEOUS_IN &= ~SIRC_MISCELLANEOUS_IN_STANDBY_ENABLE_MASK; /* Update Clock state for SIRC_STANDBY_CLK to disable */ UpdateClockState(config->name, DISABLED_CLOCK); } } #endif #ifdef SIRC_ENABLE static status_t SircEnable(Clock_Ip_IrcoscConfigType const* config) { uint32 instance = clockFeatures[config->name][CLOCK_MODULE_INSTANCE]; boolean TimeoutOccurred = FALSE; uint32 StartTime; uint32 ElapsedTime; uint32 TimeoutTicks; uint32 IrcoscStatus; Clock_Ip_IrcoscConfigType sircConfig; (void)instance; /* TODO config = NULL ??*/ if (config == NULL) { config.name = FIRC_CLK; config.range = 1U; /* 8MHz */ config.enable = 1U; /* enabled */ } /* Clear LK bit field */ SCG->SIRCCSR &= (uint32)(~(SCG_SIRCCSR_LK_MASK)); /* Disable clock */ SCG->SIRCCSR &= (uint32)(~(SCG_SIRCCSR_SIRCEN_MASK)); /* Configure SIRC. */ if (config->enable) { /* Step frequency range. */ SCG->SIRCCFG = SCG_SIRCCFG_RANGE(config->range); /* Enable clock. */ SCG->SIRCCSR |= SCG_SIRCCSR_SIRCEN(1U); ClockStartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_TIMEOUT_VALUE_US); /* Wait until ircosc is locked */ do { Clock_Ip_TimeDelay(); IrcoscStatus = (((SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) >> SCG_SIRCCSR_SIRCVLD_SHIFT)); TimeoutOccurred = ClockTimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks); } while ((IrcoscStatus == 0U) && (FALSE == TimeoutOccurred)); if (FALSE == TimeoutOccurred) { UpdateClockState(config->name, ENABLED_CLOCK); } else { /* Report timeout error */ ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, config->name); } } return status; } #endif #ifdef SIRC_VLP_ENABLE static SircVlpEnable(Clock_Ip_IrcoscConfigType const* config) { /* Clear LK bit field */ SCG->SIRCCSR &= (uint32)(~(SCG_SIRCCSR_LK_MASK)); /* Disable clock */ SCG->SIRCCSR &= (uint32)(~(SCG_SIRCCSR_SIRCLPEN_MASK)); /* Configure SIRC. */ if (config->enable) { /* Enable clock in VLP mode */ SCG->SIRCCSR |= SCG_SIRCCSR_SIRCLPEN(1U); } } #endif #ifdef SIRC_STOP_ENABLE static SircStopEnable(Clock_Ip_IrcoscConfigType const* config) { /* Clear LK bit field */ SCG->SIRCCSR &= (uint32)(~(SCG_SIRCCSR_LK_MASK)); /* Disable clock */ SCG->SIRCCSR &= (uint32)(~(SCG_SIRCCSR_SIRCSTEN_MASK)); /* Configure SIRC. */ if (config->enable) { /* Enable clock in STOP mode */ SCG->SIRCCSR |= SCG_SIRCCSR_SIRCSTEN(1U); } } #endif #ifdef FIRC_ENABLE static status_t FIRCEnable(Clock_Ip_IrcoscConfigType const* config) { uint32 instance = clockFeatures[config->name][CLOCK_MODULE_INSTANCE]; boolean TimeoutOccurred = FALSE; uint32 StartTime; uint32 ElapsedTime; uint32 TimeoutTicks; uint32 IrcoscStatus; (void)instance; /* Clear LK bit field */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_LK_MASK)); /* Check that FIRC is used by system clock) */ if ((SCG->FIRCSCR & SCG_FIRCCSR_FIRCSEL_MASK) != 0U) { /* Check whether FIRC is already configured as required */ if (((config->range != (SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT) || (config->regulator != SCG_FIRCCSR_FIRCREGOFF((regulator) ? 0UL : 1UL))) { /* Enable SIRC if it is disabled. */ if ((SCG->SIRCCSR & SCG_SIRCCSR_SIRCEN_MASK) == 0U) { SircEnable(NULL_PTR); } /* Switch to SIRC */ uint32 regValue = scg->RCCR; regValue &= ~SCG_RCCR_SCS_MASK; regValue |= (SIRC_CLK_SOURCE << SCG_RCCR_SCS_SHIFT); scg->RCCR = regValue; timeut = 10U; while ((((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) != ((uint32_t)SIRC_clock_source)) && (timeout > 0U)); if (timeout == 0U) { retValue = STATUS_TIMEOUT; } /* Disable clock */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_FIRCEN_MASK)); /* Configure FIRC. */ if (config->enable) { /* Step frequency range. */ SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->range) | SCG_FIRCCSR_FIRCREGOFF((config->regulator) ? 0UL : 1UL); /* Enable clock. */ SCG->FIRCCSR |= SCG_FIRCCSR_FIRCEN(1U); ClockStartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_TIMEOUT_VALUE_US); /* Wait until ircosc is locked */ do { Clock_Ip_TimeDelay(); IrcoscStatus = (((SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) >> SCG_FIRCCSR_FIRCVLD_SHIFT)); TimeoutOccurred = ClockTimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks); } while ((IrcoscStatus == 0U) && (FALSE == TimeoutOccurred)); if (FALSE == TimeoutOccurred) { UpdateClockState(config->name, ENABLED_CLOCK); } else { /* Report timeout error */ ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, config->name); } /* Switch back to FIRC */ uint32 regValue = scg->RCCR; regValue &= ~SCG_RCCR_SCS_MASK; regValue |= (FIRC_CLK_SOURCE << SCG_RCCR_SCS_SHIFT); scg->RCCR = regValue; timeut = 10U; while ((((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) != ((uint32_t)SIRC_clock_source)) && (timeout > 0U)); if (timeout == 0U) { retValue = STATUS_TIMEOUT; } } else { UpdateClockState(config->name, DISABLED_CLOCK); } } else { /* Firc is used as system clock source and is configured as required */ UpdateClockState(config->name, ENABLED_CLOCK); } } else { /* Configure FIRC. */ /* Disable clock */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_FIRCEN_MASK)); if (config->enable) { /* Step frequency range. */ SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->range) | SCG_FIRCCSR_FIRCREGOFF((config->regulator) ? 0UL : 1UL); /* Enable clock. */ SCG->FIRCCSR |= SCG_FIRCCSR_FIRCEN(1U); ClockStartTimeout(&StartTime, &ElapsedTime, &TimeoutTicks, CLOCK_TIMEOUT_VALUE_US); /* Wait until ircosc is locked */ do { Clock_Ip_TimeDelay(); IrcoscStatus = (((SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) >> SCG_FIRCCSR_FIRCVLD_SHIFT)); TimeoutOccurred = ClockTimeoutExpired(&StartTime, &ElapsedTime, TimeoutTicks); } while ((IrcoscStatus == 0U) && (FALSE == TimeoutOccurred)); if (FALSE == TimeoutOccurred) { UpdateClockState(config->name, ENABLED_CLOCK); } else { /* Report timeout error */ ReportClockErrors(CLOCK_IP_REPORT_TIMEOUT_ERROR, config->name); } } else { UpdateClockState(config->name, DISABLED_CLOCK); } } return status; } #endif #ifdef FIRC_VLP_ENABLE static FIRCVlpEnable(Clock_Ip_IrcoscConfigType const* config) { /* Clear LK bit field */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_LK_MASK)); /* Disable clock */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_FIRCLPEN_MASK)); /* Configure FIRC. */ if (config->enable) { /* Enable clock in VLP mode */ SCG->FIRCCSR |= SCG_FIRCCSR_FIRCLPEN(1U); } } #endif #ifdef FIRC_STOP_ENABLE static FIRCStopEnable(Clock_Ip_IrcoscConfigType const* config) { /* Clear LK bit field */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_LK_MASK)); /* Disable clock */ SCG->FIRCCSR &= (uint32)(~(SCG_FIRCCSR_FIRCSTEN_MASK)); /* Configure FIRC. */ if (config->enable) { /* Enable clock in STOP mode */ SCG->FIRCCSR |= SCG_FIRCCSR_FIRCSTEN(1U); } } #endif /* Clock stop section code */ #define MCU_STOP_SEC_CODE /** * @violates @ref Clock_Ip_IntOsc_c_REF_1 #include directives should only be preceded by preprocessor * directives or comments. */ #include "Mcu_MemMap.h" /*! @}*/ /******************************************************************************* * EOF ******************************************************************************/