mirror of
https://github.com/Dev-KATECH/ADM.git
synced 2026-05-17 01:43:59 +09:00
817 lines
31 KiB
C
817 lines
31 KiB
C
/*==================================================================================================
|
|
* 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.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_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_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
|
|
*
|
|
* @section Clock_Ip_c_REF_3
|
|
* Violates MISRA 2012 Advisory Directive 4.9, A function should be used in preference to a function-like macro where they are interchangeable.
|
|
* Function like macro are used to reduce code complexity
|
|
*
|
|
* @section Clock_Ip_c_REF_4
|
|
* Violates MISRA 2012 Advisory Rule 12.3, The comma operator should not be used.
|
|
* The comma is used to abstract the trusted call function and to determine when the return into user mode is needed.
|
|
*
|
|
* @section Clock_Ip_c_REF_5
|
|
* Violates MISRA 2012 Advisory Rule 8.7, Functions and objects should not be defined with external linkage if
|
|
* they are referenced in only one translation unit.
|
|
* These functions represent the API of the driver. External linkage is needed to "export" the API.
|
|
*/
|
|
|
|
#include "Clock_Ip_Private.h"
|
|
#include "OsIf.h"
|
|
|
|
/*==================================================================================================
|
|
SOURCE FILE VERSION INFORMATION
|
|
==================================================================================================*/
|
|
#define CLOCK_IP_VENDOR_ID_C 43
|
|
#define CLOCK_IP_AR_RELEASE_MAJOR_VERSION_C 4
|
|
#define CLOCK_IP_AR_RELEASE_MINOR_VERSION_C 4
|
|
#define CLOCK_IP_AR_RELEASE_REVISION_VERSION_C 0
|
|
#define CLOCK_IP_SW_MAJOR_VERSION_C 0
|
|
#define CLOCK_IP_SW_MINOR_VERSION_C 9
|
|
#define CLOCK_IP_SW_PATCH_VERSION_C 0
|
|
|
|
/*==================================================================================================
|
|
* FILE VERSION CHECKS
|
|
==================================================================================================*/
|
|
/* Check if Clock_Ip.c file and Clock_Ip_Private.h file are of the same vendor */
|
|
#if (CLOCK_IP_VENDOR_ID_C != CLOCK_IP_PRIVATE_VENDOR_ID)
|
|
#error "Clock_Ip.c and Clock_Ip_Private.h have different vendor ids"
|
|
#endif
|
|
|
|
/* Check if Clock_Ip.c file and Clock_Ip_Private.h file are of the same Autosar version */
|
|
#if ((CLOCK_IP_AR_RELEASE_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MAJOR_VERSION) || \
|
|
(CLOCK_IP_AR_RELEASE_MINOR_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_MINOR_VERSION) || \
|
|
(CLOCK_IP_AR_RELEASE_REVISION_VERSION_C != CLOCK_IP_PRIVATE_AR_RELEASE_REVISION_VERSION) \
|
|
)
|
|
#error "AutoSar Version Numbers of Clock_Ip.c and Clock_Ip_Private.h are different"
|
|
#endif
|
|
|
|
/* Check if Clock_Ip.c file and Clock_Ip_Private.h file are of the same Software version */
|
|
#if ((CLOCK_IP_SW_MAJOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MAJOR_VERSION) || \
|
|
(CLOCK_IP_SW_MINOR_VERSION_C != CLOCK_IP_PRIVATE_SW_MINOR_VERSION) || \
|
|
(CLOCK_IP_SW_PATCH_VERSION_C != CLOCK_IP_PRIVATE_SW_PATCH_VERSION) \
|
|
)
|
|
#error "Software Version Numbers of Clock_Ip.c and Clock_Ip_Private.h are different"
|
|
#endif
|
|
|
|
#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
|
|
/* Check if Clock_Ip.c file and OsIf.h file are of the same Autosar version */
|
|
#if ((CLOCK_IP_AR_RELEASE_MAJOR_VERSION_C != OSIF_AR_RELEASE_MAJOR_VERSION) || \
|
|
(CLOCK_IP_AR_RELEASE_MINOR_VERSION_C != OSIF_AR_RELEASE_MINOR_VERSION))
|
|
#error "AutoSar Version Numbers of Clock_Ip.c and OsIf.h are different"
|
|
#endif
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
#define MCU_START_SEC_CODE
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
static void ClockNotificatonsEmptyCallback(Clock_Ip_ClockNotificationType notification, Clock_Ip_NameType clockName);
|
|
static void Clock_Ip_Sleep(void);
|
|
|
|
#define MCU_STOP_SEC_CODE
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
/* Clock start initialized section data */
|
|
#define MCU_START_SEC_VAR_INIT_BOOLEAN
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
static boolean clockTreeIsConsumingPll = FALSE; /* Clock tree is using a PLL output */
|
|
/* Clock stop initialized section data */
|
|
#define MCU_STOP_SEC_VAR_INIT_BOOLEAN
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
#define MCU_START_SEC_VAR_INIT_UNSPECIFIED
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
static Clock_Ip_NotificationsCallbackType clockNotificationsCallback = ClockNotificatonsEmptyCallback; /* Clock Report Error Callback */
|
|
const Clock_Ip_ClockConfigType *clockConfig = NULL_PTR; /* Reference to the current clock configuration */
|
|
/* Clock stop initialized section data */
|
|
#define MCU_STOP_SEC_VAR_INIT_UNSPECIFIED
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
/* Clock start uninitialized section data */
|
|
#define MCU_START_SEC_VAR_NO_INIT_8
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
static uint8 ClockCalcFreqCallIdx;
|
|
|
|
/* Clock stop uninitialized section data */
|
|
#define MCU_STOP_SEC_VAR_NO_INIT_8
|
|
/**
|
|
* @violates @ref Clock_Ip_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_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_Init
|
|
* Description : This function configures all clocks according to a clock configuration.
|
|
*
|
|
* @implements Clock_Ip_Init_Activity
|
|
* END**********************************************************************************/
|
|
Clock_Ip_StatusType Clock_Ip_Init(Clock_Ip_ClockConfigType const * config)
|
|
{
|
|
Clock_Ip_StatusType clockStatus = CLOCK_IP_ERROR;
|
|
Clock_Ip_PllStatusType pllStatus;
|
|
|
|
(void)consumerClockCallbacks;
|
|
(void)xoscCallbackIndex;
|
|
(void)extOscCallbacks;
|
|
(void)ircoscCallbackIndex;
|
|
(void)intOscCallbacks;
|
|
(void)pcfsCallbackIndex;
|
|
(void)pcfsCallbacks;
|
|
(void)dividerCallbackIndex;
|
|
(void)dividerCallbacks;
|
|
(void)calcFreqCallbacks;
|
|
|
|
(void)CLOCK_MODULE_INSTANCE;
|
|
(void)CLOCK_CALLBACK;
|
|
(void)INTERFACE_CLOCK;
|
|
(void)SELECTOR_INDEX;
|
|
(void)PCFS_INSTANCE;
|
|
(void)DIVIDER_INDEX;
|
|
(void)PCTL_INDEX;
|
|
(void)PCC_INDEX;
|
|
(void)PARTITION_INDEX;
|
|
(void)COLLECTION_INDEX;
|
|
(void)PCFS_HW_INDEX;
|
|
(void)ENABLE_REQUEST;
|
|
(void)PCFS_SW_INDEX;
|
|
(void)TRIGGER_FEATURE;
|
|
|
|
|
|
#if (defined(CLOCK_IP_ENABLE_USER_MODE_SUPPORT))
|
|
#if (STD_ON == CLOCK_IP_ENABLE_USER_MODE_SUPPORT)
|
|
/* Set user access allowed for Clock */
|
|
Clock_Ip_SetUserAccessAllowed();
|
|
#endif
|
|
#endif
|
|
CLOCK_DEV_ASSERT(NULL_PTR != config);
|
|
|
|
Clock_Ip_InitClock(config);
|
|
|
|
if (clockTreeIsConsumingPll)
|
|
{
|
|
pllStatus = Clock_Ip_GetPllStatus();
|
|
if (CLOCK_IP_PLL_LOCKED == pllStatus)
|
|
{
|
|
Clock_Ip_DistributePll();
|
|
clockStatus = CLOCK_IP_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
clockStatus = CLOCK_IP_SUCCESS;
|
|
}
|
|
|
|
return clockStatus;
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_InitClock
|
|
* Description : This function configures all clocks according to a clock configuration.
|
|
*
|
|
* @implements Clock_Ip_InitClock_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_InitClock(Clock_Ip_ClockConfigType const * config)
|
|
{
|
|
uint32 callbackIndex;
|
|
uint32 i;
|
|
|
|
ClockCalcFreqCallIdx = 0U;
|
|
|
|
CLOCK_DEV_ASSERT(NULL_PTR != config);
|
|
/* Clear all the settings for CMU0/1/2... */
|
|
/* In case one clock configuration has the CMU disabled, then need to make the transition to
|
|
reset state of CMU modules. */
|
|
if (NULL_PTR != clockConfig)
|
|
{
|
|
for (i = 0U; i < config->cmusCount; i++) /* Reset all clock monitor units from previous configuration. */
|
|
{
|
|
callbackIndex = cmuCallbackIndex[clockFeatures[config->cmus[i].name][CLOCK_CALLBACK]];
|
|
cmuCallbacks[callbackIndex].Reset(&config->cmus[i]);
|
|
}
|
|
}
|
|
|
|
/* Save the current clock configuration to be used by "Clock_Ip_DistributePllClock". */
|
|
clockConfig = config;
|
|
|
|
/* Platform specific initialization:
|
|
* DFS reset, FIRC_CLK configuration etc. */
|
|
SpecificPlatformInitClock(config);
|
|
|
|
/*********************************************************************
|
|
*** Ramp down to safe configuration. Reset elements from clock tree:
|
|
*** selectors, fractional dividers, plls and xoscs
|
|
***********************************************************************/
|
|
|
|
for (i = 0U; i < config->selectorsCount; i++) /* Ramp down all selectors from configuration to SAFE_CLOCK */
|
|
{
|
|
callbackIndex = selectorCallbackIndex[clockFeatures[config->selectors[i].name][CLOCK_CALLBACK]];
|
|
selectorCallbacks[callbackIndex].Reset(&config->selectors[i]);
|
|
}
|
|
|
|
for (i = 0U; i < config->fracDivsCount; i++) /* Put in reset state all fractional dividers from configuration */
|
|
{
|
|
callbackIndex = fractional_dividerCallbackIndex[clockFeatures[config->fracDivs[i].name][CLOCK_CALLBACK]];
|
|
fracDivCallbacks[callbackIndex].Reset(&config->fracDivs[i]);
|
|
}
|
|
|
|
for (i = 0U; i < config->pllsCount; i++) /* Power down all plls from configuration */
|
|
{
|
|
callbackIndex = pllCallbackIndex[clockFeatures[config->plls[i].name][CLOCK_CALLBACK]];
|
|
pllCallbacks[callbackIndex].Reset(&config->plls[i]);
|
|
}
|
|
|
|
for (i = 0U; i < config->xoscsCount; i++) /* Power down all xoscs from configuration */
|
|
{
|
|
callbackIndex = xoscCallbackIndex[clockFeatures[config->xoscs[i].name][CLOCK_CALLBACK]];
|
|
extOscCallbacks[callbackIndex].Reset(&config->xoscs[i]);
|
|
}
|
|
|
|
/*******************************************************
|
|
*** Load the new configuration. Selectors that might
|
|
*** be clocked from PLLs/XOCs shouldn't be configured.
|
|
*******************************************************/
|
|
|
|
for (i = 0U; i < config->ircoscsCount; i++) /* Set internal oscillators from configuration */
|
|
{
|
|
callbackIndex = ircoscCallbackIndex[clockFeatures[config->ircoscs[i].name][CLOCK_CALLBACK]];
|
|
intOscCallbacks[callbackIndex].Set(&config->ircoscs[i]);
|
|
}
|
|
|
|
for (i = 0U; i < config->xoscsCount; i++) /* Configure all xoscs from configuration */
|
|
{
|
|
callbackIndex = xoscCallbackIndex[clockFeatures[config->xoscs[i].name][CLOCK_CALLBACK]];
|
|
extOscCallbacks[callbackIndex].Set(&config->xoscs[i]);
|
|
}
|
|
|
|
/* Complete the process frequency calculations */
|
|
Clock_Ip_Sleep();
|
|
|
|
/* Configure the PCFS */
|
|
for (i = 0U; i < config->pcfsCount; i++) /* Configure all progressive frequency switching clocks from configuration */
|
|
{
|
|
callbackIndex = pcfsCallbackIndex[clockFeatures[config->pcfs[i].name][CLOCK_CALLBACK]];
|
|
pcfsCallbacks[callbackIndex].Set(&config->pcfs[i]);
|
|
}
|
|
|
|
/* Configure the clock divider triggers that are under MCU control */
|
|
for (i = 0U; i < config->dividerTriggersCount; i++) /* Set divider triggers from configuration. */
|
|
{
|
|
callbackIndex = dividertriggerCallbackIndex[clockFeatures[config->dividerTriggers[i].name][CLOCK_CALLBACK]];
|
|
dividerTriggerCallbacks[callbackIndex].Configure(&config->dividerTriggers[i]);
|
|
}
|
|
|
|
/* Configure the clock dividers that are under MCU control */
|
|
for (i = 0U; i < config->dividersCount; i++) /* Set dividers from configuration. */
|
|
{
|
|
callbackIndex = dividerCallbackIndex[clockFeatures[config->dividers[i].name][CLOCK_CALLBACK]];
|
|
dividerCallbacks[callbackIndex].Set(&config->dividers[i]);
|
|
}
|
|
|
|
/* Trigger update for all divider trigger that are under MCU control */
|
|
for (i = 0U; i < config->dividerTriggersCount; i++) /* Set divider triggers from configuration. */
|
|
{
|
|
callbackIndex = dividertriggerCallbackIndex[clockFeatures[config->dividerTriggers[i].name][CLOCK_CALLBACK]];
|
|
dividerTriggerCallbacks[callbackIndex].TriggerUpdate(&config->dividerTriggers[i]);
|
|
}
|
|
|
|
/* Configure PLL clock generators */
|
|
for (i = 0U; i < config->pllsCount; i++) /* Configure all plls from configuration asynchronously. Do not wait. */
|
|
{
|
|
callbackIndex = pllCallbackIndex[clockFeatures[config->plls[i].name][CLOCK_CALLBACK]];
|
|
pllCallbacks[callbackIndex].Set(&config->plls[i]);
|
|
}
|
|
|
|
/* Configure fractional dividers */
|
|
/* Note: The DFS configuration might actually need to be done after we
|
|
* know that the PLLs are all locked in "Clock_Ip_GetPllStatus". */
|
|
for (i = 0U; i < config->fracDivsCount; i++) /* Configure all fractional dividers from configuration asynchronously. Do not wait. */
|
|
{
|
|
callbackIndex = fractional_dividerCallbackIndex[clockFeatures[config->fracDivs[i].name][CLOCK_CALLBACK]];
|
|
fracDivCallbacks[callbackIndex].Set(&config->fracDivs[i]);
|
|
}
|
|
|
|
#ifdef FEATURE_CLOCK_IP_HAS_RAM_WAIT_STATES
|
|
/* The entry point of the flash and RAM controllers configuration. */
|
|
clockNotificationsCallback(CLOCK_IP_RAM_MEMORY_CONFIG_ENTRY_POINT, RESERVED_CLK);
|
|
|
|
SetRamWaitStates();
|
|
|
|
/* The exit point of the flash and RAM controllers configuration. */
|
|
clockNotificationsCallback(CLOCK_IP_RAM_MEMORY_CONFIG_EXIT_POINT, RESERVED_CLK);
|
|
#endif
|
|
|
|
#ifdef FEATURE_CLOCK_IP_HAS_FLASH_WAIT_STATES
|
|
/* The entry point of the flash and RAM controllers configuration. */
|
|
clockNotificationsCallback(CLOCK_IP_FLASH_MEMORY_CONFIG_ENTRY_POINT, RESERVED_CLK);
|
|
|
|
SetFlashWaitStates();
|
|
|
|
/* The exit point of the flash and RAM controllers configuration. */
|
|
clockNotificationsCallback(CLOCK_IP_FLASH_MEMORY_CONFIG_EXIT_POINT, RESERVED_CLK);
|
|
#endif
|
|
|
|
clockTreeIsConsumingPll = FALSE; /* Check if the clock tree is using a PLL output */
|
|
|
|
/* Switch the clock multiplexers under MCU control to the configured source clocks */
|
|
/* Note: if the configured source clock of a ClockMux is the output clock of a PLL/DFS,
|
|
* the configuration will be skipped and the respective ClockMux will be switched in
|
|
* the "Clock_Ip_DistributePllClock" function instead, when the source clock will have
|
|
* stabilized already. */
|
|
for (i = 0U; i < config->selectorsCount; i++) /* Set only if selected inputs are not clocked from XOSCs or PLLs */
|
|
{
|
|
if ((IRCOSC_TYPE == clockName_sourceType[config->selectors[i].value])) {
|
|
|
|
callbackIndex = selectorCallbackIndex[clockFeatures[config->selectors[i].name][CLOCK_CALLBACK]];
|
|
selectorCallbacks[callbackIndex].Set(&config->selectors[i]);
|
|
}
|
|
else
|
|
{
|
|
/* At least one mux is consuming pll */
|
|
clockTreeIsConsumingPll = TRUE;
|
|
}
|
|
}
|
|
|
|
for (i = 0U; i < config->gatesCount; i++) /* Set clock gates that are under clock control. */
|
|
{
|
|
callbackIndex = gateCallbackIndex[clockFeatures[config->gates[i].name][CLOCK_CALLBACK]];
|
|
gateCallbacks[callbackIndex].Set(&config->gates[i]);
|
|
}
|
|
|
|
/* Check if the clock tree is using a PLL output */
|
|
if ( FALSE == clockTreeIsConsumingPll )
|
|
{
|
|
#if CLOCK_SPECIFIC_PERIPH_NO > 0U
|
|
/* Configure the specific modules like eMios */
|
|
SpecificPeripheralClockInitialization(&config->specificPeriphalConfiguration);
|
|
#endif
|
|
/* Set the Clock Monitoring Units ( CMU0 .. n ). */
|
|
for (i = 0U; i < config->cmusCount; i++)
|
|
{
|
|
callbackIndex = cmuCallbackIndex[clockFeatures[config->cmus[i].name][CLOCK_CALLBACK]];
|
|
cmuCallbacks[callbackIndex].Set(&config->cmus[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* The clock tree is using at least one PLL/DFS output clock as source. */
|
|
/* The user must wait until the PLLs and DFSs are locked by polling Clock_Ip_GetPllStatus */
|
|
/* and then call "Clock_Ip_DistributePllClock" */
|
|
}
|
|
/* When mcu clock distribution is updated or power mode is changed, frequencies must be updated. */
|
|
UpdateFrequencies(RUN_MODE);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_GetPllStatus
|
|
* Description : This function configures all clocks according to a clock configuration.
|
|
* If no configuration is received, no change will be processed in HW and clock driver
|
|
* will calculate frequencies only.
|
|
*
|
|
* @implements Clock_Ip_GetPllStatus_Activity
|
|
* END**********************************************************************************/
|
|
Clock_Ip_PllStatusType Clock_Ip_GetPllStatus(void)
|
|
{
|
|
|
|
Clock_Ip_PllStatusType retValue = CLOCK_IP_PLL_STATUS_UNDEFINED;
|
|
clock_pll_status_t pllStatus;
|
|
#ifdef CLOCK_IP_DFS_SUPPORT
|
|
#if (STD_ON == CLOCK_IP_DFS_SUPPORT)
|
|
clock_dfs_status_t dfsStatus;
|
|
#endif
|
|
#endif
|
|
uint32 i, callbackIndex;
|
|
|
|
for (i = 0U; i < NUMBER_OF_HARDWARE_PLL; i++)
|
|
{
|
|
callbackIndex = pllCallbackIndex[clockFeatures[HwPllName[i]][CLOCK_CALLBACK]];
|
|
pllStatus = pllCallbacks[callbackIndex].Complete(HwPllName[i]);
|
|
if (STATUS_PLL_UNLOCKED == pllStatus)
|
|
{
|
|
retValue = CLOCK_IP_PLL_UNLOCKED;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (STATUS_PLL_LOCKED == pllStatus)
|
|
{
|
|
retValue = CLOCK_IP_PLL_LOCKED;
|
|
}
|
|
}
|
|
}
|
|
#ifdef CLOCK_IP_DFS_SUPPORT
|
|
#if (STD_ON == CLOCK_IP_DFS_SUPPORT)
|
|
if (CLOCK_IP_PLL_LOCKED == retValue)
|
|
{
|
|
for (i = 0U; i < NUMBER_OF_HARDWARE_DFS; i++)
|
|
{
|
|
callbackIndex = fractional_dividerCallbackIndex[clockFeatures[HwDfsName[i]][CLOCK_CALLBACK]];
|
|
dfsStatus = fracDivCallbacks[callbackIndex].Complete(HwDfsName[i]);
|
|
if (STATUS_DFS_UNLOCKED == dfsStatus)
|
|
{
|
|
retValue = CLOCK_IP_PLL_UNLOCKED;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
return retValue;
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_DistributePll
|
|
* Description : Function completes the PLL configuration and then activates the PLL clock to Mcu
|
|
* The function will not distribute the PLL clock if the driver state does not allow it, or the PLL is not stable.
|
|
*
|
|
* @implements Clock_Ip_DistributePll_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_DistributePll(void)
|
|
{
|
|
|
|
uint32 i, callbackIndex;
|
|
|
|
CLOCK_DEV_ASSERT(NULL_PTR != clockConfig);
|
|
/* 'clockConfig' is set by Clock_Ip_InitClock().
|
|
* It doesn't make sense to call PLL distribution without clock initialization. */
|
|
if (NULL_PTR != clockConfig)
|
|
{
|
|
for (i = 0U; i < clockConfig->selectorsCount; i++) /* Set only if selected inputs are clocked from XOSCs or PLLs */
|
|
{
|
|
if (IRCOSC_TYPE != clockName_sourceType[clockConfig->selectors[i].value]) {
|
|
|
|
callbackIndex = selectorCallbackIndex[clockFeatures[clockConfig->selectors[i].name][CLOCK_CALLBACK]];
|
|
selectorCallbacks[callbackIndex].Set(&clockConfig->selectors[i]);
|
|
}
|
|
}
|
|
|
|
/* In the case of PLL is enabled but PLL clock source is not used by any clock Mux.
|
|
So, no need to re-configure for CMUs, because they are configured by Clock_Ip_InitClock */
|
|
/* Check if the clock tree is using a PLL output */
|
|
if ( clockTreeIsConsumingPll )
|
|
{
|
|
#if CLOCK_SPECIFIC_PERIPH_NO > 0U
|
|
SpecificPeripheralClockInitialization(&clockConfig->specificPeriphalConfiguration);
|
|
#endif
|
|
/* Enable CMU if used */
|
|
for (i = 0U; i < clockConfig->cmusCount; i++)
|
|
{
|
|
callbackIndex = cmuCallbackIndex[clockFeatures[clockConfig->cmus[i].name][CLOCK_CALLBACK]];
|
|
cmuCallbacks[callbackIndex].Set(&clockConfig->cmus[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* When mcu clock distribution is updated or
|
|
* power mode is changed, frequencies must be updated.
|
|
*/
|
|
UpdateFrequencies(RUN_MODE);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_DisableClockMonitor
|
|
* Description : Disables a clock monitor.
|
|
*
|
|
* @implements Clock_Ip_DisableClockMonitor_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_DisableClockMonitor(Clock_Ip_NameType clockName)
|
|
{
|
|
|
|
uint32 callbackIndex;
|
|
|
|
callbackIndex = cmuCallbackIndex[clockFeatures[clockName][CLOCK_CALLBACK]];
|
|
cmuCallbacks[callbackIndex].Disable(clockName);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_GetClockMonitorStatus
|
|
* Description : Returns the clock monitor status.
|
|
*
|
|
* @implements Clock_Ip_GetClockMonitorStatus_Activity
|
|
* END**********************************************************************************/
|
|
Clock_Ip_CmuStatusType Clock_Ip_GetClockMonitorStatus(Clock_Ip_NameType clockName)
|
|
{
|
|
uint32 callbackIndex;
|
|
|
|
callbackIndex = cmuCallbackIndex[clockFeatures[clockName][CLOCK_CALLBACK]];
|
|
return cmuCallbacks[callbackIndex].GetStatus(clockName);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_ClearClockMonitorStatus
|
|
* Description : Clears status flags for a monitor clock.
|
|
*
|
|
* @implements Clock_Ip_ClearClockMonitorStatus_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_ClearClockMonitorStatus(Clock_Ip_NameType clockName)
|
|
{
|
|
|
|
uint32 callbackIndex;
|
|
|
|
callbackIndex = cmuCallbackIndex[clockFeatures[clockName][CLOCK_CALLBACK]];
|
|
cmuCallbacks[callbackIndex].Clear(clockName);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_PowerModeChangeNotification
|
|
* Description : Notifies clock driver when a power mode is changed.
|
|
*
|
|
* @implements Clock_Ip_PowerModeChangeNotification_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_PowerModeChangeNotification(power_modes_t powerMode,power_notification_t notification)
|
|
{
|
|
(void)notification;
|
|
UpdateFrequencies(powerMode);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_InstallNotificationsCallback
|
|
* Description : This function installs a callback for clock notifications.
|
|
*
|
|
* @implements Clock_Ip_InstallNotificationsCallback_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_InstallNotificationsCallback(Clock_Ip_NotificationsCallbackType callback)
|
|
{
|
|
CLOCK_DEV_ASSERT(NULL_PTR != callback);
|
|
|
|
clockNotificationsCallback = callback;
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_DisableModuleClock
|
|
* Description : Disables clock for a peripheral.
|
|
*
|
|
* @implements Clock_Ip_DisableModuleClock_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_DisableModuleClock(Clock_Ip_NameType clockName)
|
|
{
|
|
|
|
uint32 callbackIndex;
|
|
|
|
callbackIndex = gateCallbackIndex[clockFeatures[clockName][CLOCK_CALLBACK]];
|
|
gateCallbacks[callbackIndex].Update(clockName,TRUE);
|
|
}
|
|
|
|
/*FUNCTION******************************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_EnableModuleClock
|
|
* Description : Enable clock for a peripheral.
|
|
*
|
|
* @implements Clock_Ip_EnableModuleClock_Activity
|
|
* END**********************************************************************************/
|
|
void Clock_Ip_EnableModuleClock(Clock_Ip_NameType clockName)
|
|
{
|
|
|
|
uint32 callbackIndex;
|
|
|
|
callbackIndex = gateCallbackIndex[clockFeatures[clockName][CLOCK_CALLBACK]];
|
|
gateCallbacks[callbackIndex].Update(clockName,FALSE);
|
|
}
|
|
|
|
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_GetClockFrequency
|
|
* Description : This function returns the frequency of a given clock
|
|
*
|
|
* @implements Clock_Ip_GetClockFrequency_Activity
|
|
* END**************************************************************************/
|
|
uint32 Clock_Ip_GetClockFrequency(Clock_Ip_NameType clockName)
|
|
{
|
|
uint32 frequency;
|
|
#if (defined(CLOCK_IP_DEV_ERROR_DETECT))
|
|
#if (CLOCK_IP_DEV_ERROR_DETECT == STD_ON)
|
|
CLOCK_DEV_ASSERT((((uint32)clockName) < ((uint32)CLOCK_NAMES_NO)) && (THE_LAST_PRODUCER_CLK != clockName));
|
|
#endif
|
|
#endif
|
|
|
|
if(((uint32)clockName) > ((uint32)THE_LAST_PRODUCER_CLK))
|
|
{
|
|
frequency = consumerClockCallbacks[((uint32)clockName) - ((uint32)THE_LAST_PRODUCER_CLK) - (uint32)1U]();
|
|
}
|
|
else
|
|
{
|
|
frequency = GetProducerClockFreq(clockName);
|
|
}
|
|
return frequency;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_Sleep.
|
|
* Description : Complete the process frequency calculations
|
|
*
|
|
*END**************************************************************************/
|
|
static void Clock_Ip_Sleep(void)
|
|
{
|
|
while(ClockCalcFreqCallIdx < (CALC_FREQ_CALLBACKS_NO-1U))
|
|
{
|
|
calcFreqCallbacks[ClockCalcFreqCallIdx]();
|
|
ClockCalcFreqCallIdx++;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_TimeDelay.
|
|
* Description : TimeDelay. Process frequency calculations on behalf of TimeDelay function.
|
|
*
|
|
*END**************************************************************************/
|
|
void Clock_Ip_TimeDelay(void)
|
|
{
|
|
calcFreqCallbacks[ClockCalcFreqCallIdx]();
|
|
|
|
if (ClockCalcFreqCallIdx < (CALC_FREQ_CALLBACKS_NO-1U))
|
|
{
|
|
ClockCalcFreqCallIdx++;
|
|
}
|
|
}
|
|
|
|
#if (defined(CLOCK_IP_ENABLE_USER_MODE_SUPPORT))
|
|
#if (STD_ON == CLOCK_IP_ENABLE_USER_MODE_SUPPORT)
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : Clock_Ip_SetUserAccessAllowed.
|
|
* Description : Set user access allowed.
|
|
*
|
|
*END**************************************************************************/
|
|
void Clock_Ip_SetUserAccessAllowed(void)
|
|
{
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_3 A function should be used in preference to a function-like macro where they are interchangeable.
|
|
*/
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_4 The comma is used to abstract the trusted call function and to determine when the return into user mode is needed.
|
|
*/
|
|
OsIf_Trusted_Call(SpecificSetUserAccessAllowed);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : ClockNotificatonsEmptyCallback.
|
|
* Description : Notification clock call back.
|
|
*
|
|
*END**************************************************************************/
|
|
static void ClockNotificatonsEmptyCallback(Clock_Ip_ClockNotificationType notification, Clock_Ip_NameType clockName)
|
|
{
|
|
/* No implementation */
|
|
(void)notification;
|
|
(void)clockName;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : ReportClockErrors
|
|
* Description : Report clock error
|
|
*
|
|
*END**************************************************************************/
|
|
void ReportClockErrors(Clock_Ip_ClockNotificationType error, Clock_Ip_NameType clockName)
|
|
{
|
|
clockNotificationsCallback(error,clockName);
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : ClockStartTimeout
|
|
* Description : Checks for timeout condition
|
|
*
|
|
*END**************************************************************************/
|
|
void ClockStartTimeout(uint32 *startTimeOut,
|
|
uint32 *elapsedTimeOut,
|
|
uint32 *timeoutTicksOut,
|
|
uint32 timeoutUs)
|
|
{
|
|
*startTimeOut = OsIf_GetCounter(CLOCK_TIMEOUT_TYPE);
|
|
*elapsedTimeOut = 0U;
|
|
*timeoutTicksOut = OsIf_MicrosToTicks(timeoutUs, CLOCK_TIMEOUT_TYPE);
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : ClockTimeoutExpired
|
|
* Description : Checks for timeout expiration condition
|
|
*
|
|
*END**************************************************************************/
|
|
boolean ClockTimeoutExpired(uint32 *startTimeInOut,
|
|
uint32 *elapsedTimeInOut,
|
|
uint32 TimeoutTicks)
|
|
{
|
|
*elapsedTimeInOut += OsIf_GetElapsed(startTimeInOut, CLOCK_TIMEOUT_TYPE);
|
|
|
|
return ((*elapsedTimeInOut >= TimeoutTicks)? TRUE : FALSE);
|
|
}
|
|
|
|
|
|
/* Clock stop section code */
|
|
#define MCU_STOP_SEC_CODE
|
|
/**
|
|
* @violates @ref Clock_Ip_c_REF_1 #include directives should only be preceded by preprocessor
|
|
* directives or comments.
|
|
*/
|
|
#include "Mcu_MemMap.h"
|
|
|
|
/*! @}*/
|
|
|
|
/*******************************************************************************
|
|
* EOF
|
|
******************************************************************************/
|