Initial commit of firmware

This commit is contained in:
2025-04-12 13:30:57 +01:00
commit 264a3462e0
374 changed files with 332649 additions and 0 deletions

View File

@@ -0,0 +1,661 @@
/***************************************************************************//**
* @file
* @brief Clock Manager APIs.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_CLOCK_MANAGER_H
#define SL_CLOCK_MANAGER_H
#include <stdbool.h>
#include <stdlib.h>
#include "sl_status.h"
#include "sl_enum.h"
#include "sl_device_clock.h"
#include "sl_code_classification.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup clock_manager Clock Manager
*
* @details
* ## Overview
*
* Clock Manager is a platform-level software module that manages
* the device's oscillators and clock tree.
* The Clock Manager module is split into two main parts: The Initialization part
* and the Runtime part. The runtime part has its component
* \a clock_manager_runtime and can be used independently from the initialization
* part. The \a clock_manager component includes both the initialization part and the
* runtime part and it should be the component added to your project slcp file.
*
* ## Initialization
* The initialization part includes the configuration files
* \a sl_clock_manager_oscillator_config.h and \a sl_clock_manager_tree_config.h.
* As their name indicates, those C header files are used to configure the different
* device oscillators and the device clock tree. Those header files use the CMSIS
* Configuration Wizard Annotations and are specific to each device.
* The API function sl_clock_manager_init() is used to initialize the Clock Manager
* module based on the configuration values specified in the two configuration files.
* This function must be called early during your initialization sequence.
* If the SL System component (@ref system) is used by your application, the
* sl_clock_manager_init() call will be added automatically to your initialization
* sequence.
*
* ### Oscillators Configuration
* Oscillators' configurations are all grouped in the \a sl_clock_manager_oscillator_config.h
* file. Crystal-based oscillators, HFXO and LFXO, have an enable/disable configuration to
* indicate if the required crystal is present or not. In the absence of the required
* crystal, the configuration must be disabled and the associated oscillator will
* not be initialized.
*
* The HFXO configuration also provides the configuration for the Crystal Sharing
* feature when supported by the device. This feature allows to use the dedicated
* HFCLKOUT pin to output a sinusoidal clock that can be used as the HFXO
* input for another EFR device. In the configuration, you need to specify if your
* device is the leader or the follower. The leader will be the one outputting the
* clock and the follower, the one receiving the clock signal. In the leader configuration,
* the GPIO pin is used to receive the request from the follower. You can refer to your
* device datasheet to know the available location for the HFXO BUFOUT_REQ pin.
* In the follower mode, the pin configuration can be used to send an HFXO request
* signal to the leader. The "High Frequency Clock Ouput" section of your device
* reference manual also provides more details about this feature.
*
* The first HFRCO module, whose output clock is called HFRCODPLL, can be connected to
* the DPLL module to have a better precision clock. When the DPLL is enabled through
* the configuration define \a SL_CLOCK_MANAGER_HFRCO_DPLL_EN, the DPLL settings
* take precedence over the HFRCO band configuration.
*
* ### Clock Tree Configuration
* The device clock tree configurations are all grouped in the
* \a sl_clock_manager_tree_config.h file. Refer to your device's reference manual for
* the clock tree diagram and see which peripherals are connected to which clock branches.
* In the configuration file, each clock branch can be independently configured.
* However, to facilitate the clock setup for users, two additional configurations
* were added: \a SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE and
* \a SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE. Those configurations allow the selection
* of the default high-frequency and low-frequency oscillators to be used inside the clock
* tree. Every clock branch that can benefit from those default selections will use them
* by default.
* On certain devices, the @ref power_manager module offers an Execution Modes feature
* with the \a SL_POWER_MANAGER_EXECUTION_MODES_FEATURE_EN configuration. When this feature
* is enabled, the \a SL_CLOCK_MANAGER_SYSCLK_SOURCE configuration could be overriden by the
* Execution Modes feature. Refer to the description of \a SL_CLOCK_MANAGER_SYSCLK_SOURCE in
* \a sl_clock_manager_tree_config.h file to know if this is the case.
*
* Some peripherals have an internal clock divider. Those are not handled by the
* Clock Manager configuration. The peripheral driver will usually expose the divider
* configuration when such a divider is present inside the peripheral module.
*
* The Clock tree configuration is available at compile-time only. The Clock Manager
* module does not offer API functions to manipulate the clock tree at runtime.
*
* The more oscillators are used by different clock branches the more power
* consumption you will have. To limit your power consumption, you can try to limit the
* number of oscillators used. So for example, only use one High-frequency oscillator
* and one Low-frequency oscillator across the clock tree. However, if the
* application is radio-based, the HFXO oscillator is mandatory for the Radio
* clock branch and if the Radio clock branch is connected to the SYSCLK branch,
* this will limit you to use HFXO for SYSCLK as well. In this specific case, SYSCLK
* could also be configured to use HFRCO with DPLL, but the chosen frequency must be two
* times the HFXO frequency so that the Radio module can retrieve the HF crystal frequency
* with its divider. This will also come with an increase in power consumption since both
* HFXO and HFRCO oscillators will be used. Refer to your device reference manual to know
* if your Radio clock is connected to the SYSCLK clock branch or not.
*
* @note The Clock Manager Initialization is incompatible with the \a device_init_clocks
* (@ref device_init_clocks), \a device_init_hfxo (@ref device_init_hfxo),
* \a device_init_hfrco (@ref device_init_hfrco) \a device_init_dpll (@ref device_init_dpll),
* \a device_init_rffpll (@ref device_init_rffpll), \a device_init_usbpll (@ref device_init_usbpll),
* \a device_init_lfxo (@ref device_init_lfxo) and \a device_init_lfrco (@ref device_init_lfrco)
* components.
* This does not mean that the \a device_init component (@ref device_init) is incompatible with the
* \a clock_manager component. The \a device_init component can pull other initialization
* modules like EMU and DCDC that are not related to clocks. Therefore, both
* \a device_init and \a clock_manager should be present in your project file. SLC will
* take care of pulling only the sub \a device_init_xxx components that are needed.
*
* The runtime part, which is associated with the \a clock_manager_runtime component,
* has also an initialization function of its own, sl_clock_manager_runtime_init().
* This function must also be part of the initialization sequence. If the SL System
* component (@ref system) is used by your application, the
* sl_clock_manager_runtime_init() call will be added automatically to your
* initialization sequence.
*
* ## Functionalities
* The Runtime part includes functionalities related to oscillators, clock tree
* and the CMU hardware module features. The main functionalities are:
* - Retrieving the frequency or precision of an oscillator or clock branch
* - Enabling/Disabling modules' bus clock
* - Retrieving or setting calibration values for oscillators
* - Exporting clocks to GPIO
* - Starting an RCO Calibration process based on a reference clock source
*
* ### Retrieve the frequency or precision of an oscillator or clock branch
* API functions sl_clock_manager_get_oscillator_frequency() and
* sl_clock_manager_get_oscillator_precision() allow retrieving respectively
* the frequency and precision of a given oscillator. Similar functions
* exist for clock branches: sl_clock_manager_get_clock_branch_frequency() and
* sl_clock_manager_get_clock_branch_precision().
*
* To retrieve the frequency or precision of a specific peripheral, you will
* first need to retrieve to which clock branch this peripheral is connected.
* To do so, the Device Manager and its @ref device_peripheral
* can be used. The below code example shows how to retrieve the clock branch
* of the TIMER0 peripheral.
*
* @code{.c}
* #include "sl_clock_manager.h"
* #include "sl_device_peripheral.h"
*
* sl_status_t status;
* uint32_t freq;
* sl_clock_branch_t clock_branch;
*
* clock_branch = sl_device_peripheral_get_clock_branch(SL_PERIPHERAL_TIMER0);
* status = sl_clock_manager_get_clock_branch_frequency(clock_branch, &freq);
* @endcode
*
* ### Enable/Disable modules' bus clock
* Before accessing a peripheral's register interface, its bus clock must be enabled,
* or else a bus fault exception will be triggered. API functions
* sl_clock_manager_enable_bus_clock() and sl_clock_manager_disable_bus_clock()
* allow to perform such operations.
*
* Note that the peripheral clock will automatically be enabled when a peripheral
* is enabled with the clock on-demand feature.
*
* ### Oscillator Calibration
* The Clock Manager initialization, if present, will calibrate the different
* oscillators during the initialization sequence, but sometimes calibration
* values must be updated during runtime in certain conditions, for example, if
* the device temperature changes too much. This is considered an advanced
* functionality and users must be careful as to when to use this functionality.
*
* API functions sl_clock_manager_set_rc_oscillator_calibration() and
* sl_clock_manager_get_rc_oscillator_calibration() allow to set or get the
* CAL register of HFRCO and LFRCO oscillators. Not all devices have an LFRCO
* module with a CAL register. Some LFRCO modules will have a high-precision
* configuration allowing to use the HFXO to auto-calibrate the LFRCO. Refer
* to your device reference manual to retrieve oscillator specifications.
*
* API functions sl_clock_manager_set_hfxo_calibration() and
* sl_clock_manager_get_hfxo_calibration() allow to set or get the \a COREBIASANA
* inside the HFXO \a XTALCTRL register. The HFXO module has a Core Bias Optimization
* stage at the end of the oscillator startup sequence that allows to further
* optimize current consumption. This optimization will automatically set the
* \a COREBIASANA bitfield when finished. Upon reset, this optimization will run
* the first time HFXO is started and afterwards, the \a XTALCTRL->SKIPCOREBIASOPT
* bit will automatically be set so that next time HFXO is started during the
* application lifetime, the optimization stage will be skipped. This optimization
* stage takes a while to run, in the order of hundreds of milliseconds, therefore
* we don't want it to run each time HFXO is started.
* With the function sl_clock_manager_set_hfxo_calibration() it is possible to
* manually set the \a COREBIASANA bitfield and set the \a SKIPCOREBIASOPT bit.
* This function will usually be used in the context of an EM4 wake-up where to
* save on the initialization sequence time, we want to skip the Core Bias Optimization
* stage and manually set the value that would have previously been retrieved with
* sl_clock_manager_get_hfxo_calibration() and saved in an EM4 retained memory.
* In this context, sl_clock_manager_set_hfxo_calibration() will need to be called
* early in the initialization sequence, before the usual clock initialization
* function.
*
* slx_clock_manager_hfxo_set_ctune(), slx_clock_manager_hfxo_get_ctune() and
* slx_clock_manager_hfxo_calibrate_ctune() functions allow to manipulate the
* HFXO tuning capacitances. Changing the CTUNE value while HFXO is running
* can result in significant clock glitches for one clock period. Therefore,
* those functions should be used with caution. The difference between the
* slx_clock_manager_hfxo_set_ctune() and slx_clock_manager_hfxo_calibrate_ctune()
* functions is that the calibration one will also start and wait for the HFXO
* Core Bias Optimization stage to complete.
*
* API functions sl_clock_manager_set_lfxo_calibration() and
* sl_clock_manager_get_lfxo_calibration() allow to set and get the LFXO CTUNE
* value.
*
* ### Export clocks to GPIO
* The CMU module offers the functionality to export a given clock source to a
* GPIO pin. Refer to function sl_clock_manager_set_gpio_clock_output() for more
* details and the #sl_clock_manager_export_clock_source_t enum for a list of
* acceptable clock sources. Note that there is a specific clock branch named
* EXPCLK that is usually connected to the SYSCLK and offers an additional divider.
*
* ### RCO Calibration
* The CMU module also offers RCO Calibration hardware support. This can be
* used to calibrate at runtime HFRCO and LFRCO oscillators using a high-precision
* reference clock. Refer to your device reference manual for more
* details about this functionality. API function
* sl_clock_manager_configure_rco_calibration() can be used to configure the
* calibration process. Then sl_clock_manager_start_rco_calibration() and
* sl_clock_manager_stop_rco_calibration() can be called to start/stop the
* process. sl_clock_manager_wait_rco_calibration() function can be called to
* actively wait for the process to finish. And finally,
* sl_clock_manager_get_rco_calibration_count() can be called to retrieve the
* calibration process result.
*
* @{
******************************************************************************/
/// Export clock source.
/// This is to be used with the sl_clock_manager_set_gpio_clock_output() API function.
SL_ENUM(sl_clock_manager_export_clock_source_t) {
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_DISABLED, ///< Export Clock Source Disabled
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_FSRCO, ///< Export Clock Source FSRCO
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_HFXO, ///< Export Clock Source HFXO
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_HFRCODPLL, ///< Export Clock Source HFRCODPLL
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_HFRCOEM23, ///< Export Clock Source HFRCOEM23
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_HFEXPCLK, ///< Export Clock Source HFEXPCLK
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_LFXO, ///< Export Clock Source LFXO
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_PLFRCO, ///< Export Clock Source PLFRCO
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_LFRCO, ///< Export Clock Source LFRCO
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_ULFRCO, ///< Export Clock Source ULFRCO
SL_CLOCK_MANAGER_EXPORT_CLOCK_SOURCE_HCLK, ///< Export Clock Source HCLK
};
/// Export clock output selection.
/// This is to be used with the sl_clock_manager_set_gpio_clock_output() API function.
SL_ENUM(sl_clock_manager_export_clock_output_select_t) {
SL_CLOCK_MANAGER_EXPORT_CLOCK_OUTPUT_SELECT_0 = 0, ///< Export Clock Output #0
SL_CLOCK_MANAGER_EXPORT_CLOCK_OUTPUT_SELECT_1, ///< Export Clock Output #1
SL_CLOCK_MANAGER_EXPORT_CLOCK_OUTPUT_SELECT_2, ///< Export Clock Output #2
};
/// Clocks available for Calibration.
/// This is to be used with the sl_clock_manager_configure_rco_calibration() API function.
SL_ENUM(sl_clock_manager_clock_calibration_t) {
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_HCLK, ///< Clock Calibration HCLK
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_PRS, ///< Clock Calibration PRS
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_HFXO, ///< Clock Calibration HFXO
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_LFXO, ///< Clock Calibration LFXO
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_HFRCODPLL, ///< Clock Calibration HFRCODPLL
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_HFRCOEM23, ///< Clock Calibration HFRCOEM23
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_FSRCO, ///< Clock Calibration FSRCO
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_LFRCO, ///< Clock Calibration LFRCO
SL_CLOCK_MANAGER_CLOCK_CALIBRATION_ULFRCO ///< Clock Calibration ULFRCO
};
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* Performs Clock Manager runtime initialization.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_runtime_init(void);
/***************************************************************************//**
* Gets frequency of given oscillator.
*
* @param[in] oscillator Oscillator
*
* @param[out] frequency Oscillator's frequency in Hertz
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sl_clock_manager_get_oscillator_frequency(sl_oscillator_t oscillator,
uint32_t *frequency);
/***************************************************************************//**
* Gets precision of given oscillator.
*
* @param[in] oscillator Oscillator
*
* @param[out] precision Oscillator's precision in PPM
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_get_oscillator_precision(sl_oscillator_t oscillator,
uint16_t *precision);
/***************************************************************************//**
* Gets frequency of given clock branch.
*
* @param[in] clock_branch Clock Branch
*
* @param[out] frequency Clock Branch's frequency in Hertz
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sl_clock_manager_get_clock_branch_frequency(sl_clock_branch_t clock_branch,
uint32_t *frequency);
/***************************************************************************//**
* Gets precision of given clock branch.
*
* @param[in] clock_branch Clock Branch
*
* @param[out] precision Clock Branch's precision in PPM
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_get_clock_branch_precision(sl_clock_branch_t clock_branch,
uint16_t *precision);
/***************************************************************************//**
* Enables the given module's bus clock.
*
* @param[in] module_bus_clock module's bus clock to enable.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note modules' bus clocks are defined in the
* @ref device_clock in the Bus Clock Defines section.
******************************************************************************/
sl_status_t sl_clock_manager_enable_bus_clock(sl_bus_clock_t module_bus_clock);
/***************************************************************************//**
* Disables the given module's bus clock.
*
* @param[in] module_bus_clock module's bus clock to disable.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note modules' bus clocks are defined in the
* @ref device_clock in the Bus Clock Defines section.
******************************************************************************/
sl_status_t sl_clock_manager_disable_bus_clock(sl_bus_clock_t module_bus_clock);
/***************************************************************************//**
* Configures one clock export output with specified clock source.
*
* @param[in] export_clock_source One of the exportable clock source.
*
* @param[in] output_select Selected export clock output channel.
*
* @param[in] hfexp_divider HFEXP clock divider (1 to 32).
* Note: This parameter only affects the EXPCLK
* branch frequency.
*
* @param[in] port GPIO port to output exported clock.
*
* @param[in] pin GPIO pin number to output exported clock.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_set_gpio_clock_output(sl_clock_manager_export_clock_source_t export_clock_source,
sl_clock_manager_export_clock_output_select_t output_select,
uint16_t hfexp_divider,
uint32_t port,
uint32_t pin);
/***************************************************************************//**
* Sets the RC oscillator frequency tuning control.
*
* @param[in] oscillator RC Oscillator to set tuning value for.
*
* @param[in] val The RC oscillator frequency tuning setting to use.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note RC Oscillator tuning is done during production, and the tuning value is
* loaded after a reset by the Clock Manager initialization code.
* Changing the tuning value from the calibrated value is for more advanced
* use. Certain oscillators also have build-in tuning optimization.
*
* @note Supported RC oscillators include:
* - SL_OSCILLATOR_HFRCODPLL
* - SL_OSCILLATOR_HFRCOEM23
* - SL_OSCILLATOR_LFRCO
******************************************************************************/
sl_status_t sl_clock_manager_set_rc_oscillator_calibration(sl_oscillator_t oscillator,
uint32_t val);
/***************************************************************************//**
* Gets the RC oscillator frequency tuning setting.
*
* @param[in] oscillator An RC oscillator to get tuning value for.
*
* @param[out] val The RC oscillator frequency tuning setting in use.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note Supported RC oscillators include:
* - SL_OSCILLATOR_HFRCODPLL
* - SL_OSCILLATOR_HFRCOEM23
* - SL_OSCILLATOR_LFRCO
******************************************************************************/
sl_status_t sl_clock_manager_get_rc_oscillator_calibration(sl_oscillator_t oscillator,
uint32_t *val);
/***************************************************************************//**
* Sets the HFXO calibration value.
*
* @param[in] val
* The HFXO calibration setting to use.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_set_hfxo_calibration(uint32_t val);
/***************************************************************************//**
* Gets the HFXO calibration value.
*
* @param[out] val The current HFXO calibration value.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_get_hfxo_calibration(uint32_t *val);
/***************************************************************************//**
* Sets the HFXO's CTUNE.
*
* @param[in] ctune The HFXO's CTUNE value.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note Sets the XI value to the given ctune value and sets the XO value based
* on that same value, but with an offset that is hardware dependent.
* Updating CTune while the crystal oscillator is running can
* result in significant clock glitches for one XO clock period.
* Should be used with caution.
******************************************************************************/
sl_status_t slx_clock_manager_hfxo_set_ctune(uint32_t ctune);
/***************************************************************************//**
* Gets the HFXO's CTUNE.
*
* @param[out] ctune The returned HFXO's CTUNE value.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note This function only returns the CTUNE XI value.
* The XO value follows the XI value with a fixed delta that is
* hardware dependent.
******************************************************************************/
sl_status_t slx_clock_manager_hfxo_get_ctune(uint32_t *ctune);
/***************************************************************************//**
* Updates the tuning capacitances and calibrate the Core Bias Current.
*
* @param[in] ctune The HFXO's CTUNE value.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note Calibrating the CTUNE is time consuming and will cause glitches on the
* HFXO's clock. Care and caution should be taken when using this API.
******************************************************************************/
sl_status_t slx_clock_manager_hfxo_calibrate_ctune(uint32_t ctune);
/***************************************************************************//**
* Sets the LFXO frequency tuning control.
*
* @param[in] val The LFXO frequency tuning setting to use.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_set_lfxo_calibration(uint32_t val);
/***************************************************************************//**
* Gets the LFXO frequency tuning setting.
*
* @param[out] val The LFXO frequency tuning setting to use.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_get_lfxo_calibration(uint32_t *val);
/***************************************************************************//**
* Configures the RCO calibration.
*
* @param[in] cycles Number of cycles to run calibration. Increasing this
* number increases precision, but the calibration will
* take more time.
*
* @param[in] down_counter_selection
* The clock which will be counted down cycles.
*
* @param[in] up_counter_selection
* The number of cycles generated by this clock will be counted and
* added up, the result can be given with
* sl_clock_manager_get_rco_calibration_count().
*
* @param[in] continuous_calibration
* Flag when true configures continuous calibration.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note RCO calibration related functions are not thread-safe and should
* therefore not be called across multiple tasks.
******************************************************************************/
sl_status_t sl_clock_manager_configure_rco_calibration(uint32_t cycles,
sl_clock_manager_clock_calibration_t down_counter_selection,
sl_clock_manager_clock_calibration_t up_counter_selection,
bool continuous_calibration);
/***************************************************************************//**
* Starts the RCO calibration.
*
* @note RCO calibration related functions are not thread-safe and should
* therefore not be called across multiple tasks.
******************************************************************************/
void sl_clock_manager_start_rco_calibration(void);
/***************************************************************************//**
* Stops the RCO calibration.
*
* @note RCO calibration related functions are not thread-safe and should
* therefore not be called across multiple tasks.
******************************************************************************/
void sl_clock_manager_stop_rco_calibration(void);
/***************************************************************************//**
* Waits for the RCO calibration to finish.
*
* @note RCO calibration related functions are not thread-safe and should
* therefore not be called across multiple tasks.
******************************************************************************/
void sl_clock_manager_wait_rco_calibration(void);
/***************************************************************************//**
* Gets calibration count value, returns the value of the up counter.
*
* @param[out] count Calibration count value.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note RCO calibration related functions are not thread-safe and should
* therefore not be called across multiple tasks.
******************************************************************************/
sl_status_t sl_clock_manager_get_rco_calibration_count(uint32_t *count);
/***************************************************************************//**
* Waits for USBPLL clock to be ready.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_wait_usbpll(void);
/***************************************************************************//**
* When this callback function is called, it means that HFXO failed twice in
* a row to start with normal configurations. This may mean that there is a
* bad crystal. When getting this callback, HFXO is running but its properties
* (frequency, precision) are not guaranteed. This should be considered as an
* error situation.
*
* @note This callback will be called only when the
* SL_CLOCK_MANAGER_HFXO_SLEEPY_CRYSTAL_SUPPORT config is enabled
******************************************************************************/
void sl_clock_manager_hfxo_notify_consecutive_failed_startups(void);
/***************************************************************************//**
* Sets the external FLASH reference clock.
*
* @param[in] oscillator Oscillator used to clock the external FLASH.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
*
* @note This API is not thread-safe and should therefore not be called
* across multiple tasks.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sl_clock_manager_set_ext_flash_clk(sl_oscillator_t oscillator);
/***************************************************************************//**
* Gets the external FLASH clock source.
*
* @param[out] oscillator Oscillator used to clock the external FLASH.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sl_clock_manager_get_ext_flash_clk(sl_oscillator_t *oscillator);
/** @} (end addtogroup clock_manager) */
#ifdef __cplusplus
}
#endif
#endif // SL_CLOCK_MANAGER_H

View File

@@ -0,0 +1,62 @@
/***************************************************************************//**
* @file
* @brief Clock Manager Init APIs.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_CLOCK_MANAGER_INIT_H
#define SL_CLOCK_MANAGER_INIT_H
#include "sl_status.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup clock_manager Clock Manager
* @{
******************************************************************************/
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* Initializes Oscillators and Clock branches.
*
* @return Status code.
* SL_STATUS_OK if successful. Error code otherwise.
******************************************************************************/
sl_status_t sl_clock_manager_init(void);
/** @} (end addtogroup clock_manager) */
#ifdef __cplusplus
}
#endif
#endif // SL_CLOCK_MANAGER_INIT_H

View File

@@ -0,0 +1,64 @@
/***************************************************************************//**
* @file
* @brief Clock Manager Private API definition.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SLI_CLOCK_MANAGER_H
#define SLI_CLOCK_MANAGER_H
#include "sl_clock_manager.h"
#include "sl_status.h"
#include "sl_compiler.h"
#include "sl_code_classification.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* Set SYSCLK clock source.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_set_sysclk_source(sl_oscillator_t source);
/***************************************************************************//**
* Get SYSCLK clock source.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_get_sysclk_source(sl_oscillator_t *source);
/***************************************************************************//**
* When this callback function is called, it means that HFXO is ready.
******************************************************************************/
__WEAK void sli_clock_manager_notify_hfxo_ready(void);
#ifdef __cplusplus
}
#endif
#endif // SLI_CLOCK_MANAGER_H

View File

@@ -0,0 +1,313 @@
/***************************************************************************//**
* @file
* @brief Clock Manager API implementations.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sli_clock_manager.h"
#include "sl_clock_manager.h"
#include "sli_clock_manager.h"
#include "sli_clock_manager_hal.h"
#include "sl_assert.h"
#include "cmsis_compiler.h"
/***************************************************************************//**
* Performs Clock Manager runtime initialization.
******************************************************************************/
sl_status_t sl_clock_manager_runtime_init(void)
{
return sli_clock_manager_hal_runtime_init();
}
/***************************************************************************//**
* Gets frequency of given oscillator.
******************************************************************************/
sl_status_t sl_clock_manager_get_oscillator_frequency(sl_oscillator_t oscillator,
uint32_t *frequency)
{
if (frequency == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_oscillator_frequency(oscillator, frequency);
}
/***************************************************************************//**
* Gets precision of given oscillator.
******************************************************************************/
sl_status_t sl_clock_manager_get_oscillator_precision(sl_oscillator_t oscillator,
uint16_t *precision)
{
if (precision == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_oscillator_precision(oscillator, precision);
}
/***************************************************************************//**
* Gets frequency of given clock branch.
******************************************************************************/
sl_status_t sl_clock_manager_get_clock_branch_frequency(sl_clock_branch_t clock_branch,
uint32_t *frequency)
{
if (frequency == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_clock_branch_frequency(clock_branch, frequency);
}
/***************************************************************************//**
* Gets precision of given clock branch.
******************************************************************************/
sl_status_t sl_clock_manager_get_clock_branch_precision(sl_clock_branch_t clock_branch,
uint16_t *precision)
{
if (precision == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_clock_branch_precision(clock_branch, precision);
}
/***************************************************************************//**
* Enables the given module's bus clock.
******************************************************************************/
sl_status_t sl_clock_manager_enable_bus_clock(sl_bus_clock_t module_bus_clock)
{
return sli_clock_manager_hal_enable_bus_clock(module_bus_clock, true);
}
/***************************************************************************//**
* Disables the given module's bus clock.
******************************************************************************/
sl_status_t sl_clock_manager_disable_bus_clock(sl_bus_clock_t module_bus_clock)
{
return sli_clock_manager_hal_enable_bus_clock(module_bus_clock, false);
}
/***************************************************************************//**
* Configures one clock export output with specified clock source.
******************************************************************************/
sl_status_t sl_clock_manager_set_gpio_clock_output(sl_clock_manager_export_clock_source_t export_clock_source,
sl_clock_manager_export_clock_output_select_t output_select,
uint16_t hfexp_divider,
uint32_t port,
uint32_t pin)
{
return sli_clock_manager_hal_set_gpio_clock_output(export_clock_source, output_select, hfexp_divider, port, pin);
}
/***************************************************************************//**
* Sets the RC oscillator frequency tuning control.
******************************************************************************/
sl_status_t sl_clock_manager_set_rc_oscillator_calibration(sl_oscillator_t oscillator,
uint32_t val)
{
return sli_clock_manager_hal_set_rc_oscillator_calibration(oscillator, val);
}
/***************************************************************************//**
* Gets the RC oscillator frequency tuning setting.
******************************************************************************/
sl_status_t sl_clock_manager_get_rc_oscillator_calibration(sl_oscillator_t oscillator,
uint32_t *val)
{
if (val == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_rc_oscillator_calibration(oscillator, val);
}
/***************************************************************************//**
* Sets the HFXO calibration value.
******************************************************************************/
sl_status_t sl_clock_manager_set_hfxo_calibration(uint32_t val)
{
return sli_clock_manager_hal_set_hfxo_calibration(val);
}
/***************************************************************************//**
* Gets the HFXO calibration value.
******************************************************************************/
sl_status_t sl_clock_manager_get_hfxo_calibration(uint32_t *val)
{
if (val == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_hfxo_calibration(val);
}
/***************************************************************************//**
* Sets the HFXO CTUNE setting.
******************************************************************************/
sl_status_t slx_clock_manager_hfxo_set_ctune(uint32_t ctune)
{
return sli_clock_manager_hal_hfxo_set_ctune(ctune);
}
/***************************************************************************//**
* Gets the HFXO CTUNE setting.
******************************************************************************/
sl_status_t slx_clock_manager_hfxo_get_ctune(uint32_t *ctune)
{
if (ctune == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_hfxo_get_ctune(ctune);
}
/***************************************************************************//**
* Updates the tuning capacitances and calibrate the Core Bias Current.
******************************************************************************/
sl_status_t slx_clock_manager_hfxo_calibrate_ctune(uint32_t ctune)
{
return sli_clock_manager_hal_hfxo_calibrate_ctune(ctune);
}
/***************************************************************************//**
* Sets the LFXO frequency tuning control.
******************************************************************************/
sl_status_t sl_clock_manager_set_lfxo_calibration(uint32_t val)
{
return sli_clock_manager_hal_set_lfxo_calibration(val);
}
/***************************************************************************//**
* Gets the LFXO frequency tuning setting.
******************************************************************************/
sl_status_t sl_clock_manager_get_lfxo_calibration(uint32_t *val)
{
if (val == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_lfxo_calibration(val);
}
/***************************************************************************//**
* Configures the RCO calibration.
******************************************************************************/
sl_status_t sl_clock_manager_configure_rco_calibration(uint32_t cycles,
sl_clock_manager_clock_calibration_t down_counter_selection,
sl_clock_manager_clock_calibration_t up_counter_selection,
bool continuous_calibration)
{
return sli_clock_manager_hal_configure_rco_calibration(cycles, down_counter_selection, up_counter_selection, continuous_calibration);
}
/***************************************************************************//**
* Starts the RCO calibration.
******************************************************************************/
void sl_clock_manager_start_rco_calibration(void)
{
sli_clock_manager_hal_start_rco_calibration();
}
/***************************************************************************//**
* Stops the RCO calibration.
******************************************************************************/
void sl_clock_manager_stop_rco_calibration(void)
{
sli_clock_manager_hal_stop_rco_calibration();
}
/***************************************************************************//**
* Waits for the RCO calibration to finish.
******************************************************************************/
void sl_clock_manager_wait_rco_calibration(void)
{
sli_clock_manager_hal_wait_rco_calibration();
}
/***************************************************************************//**
* Gets calibration count value.
******************************************************************************/
sl_status_t sl_clock_manager_get_rco_calibration_count(uint32_t *count)
{
if (count == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_rco_calibration_count(count);
}
/***************************************************************************//**
* Sets SYSCLK clock source.
******************************************************************************/
sl_status_t sli_clock_manager_set_sysclk_source(sl_oscillator_t source)
{
return sli_clock_manager_hal_set_sysclk_source(source);
}
/***************************************************************************//**
* Gets SYSCLK clock source.
******************************************************************************/
sl_status_t sli_clock_manager_get_sysclk_source(sl_oscillator_t *source)
{
if (source == NULL) {
return SL_STATUS_NULL_POINTER;
}
return sli_clock_manager_hal_get_sysclk_source(source);
}
/***************************************************************************//**
* Waits for USBPLL clock to be ready.
******************************************************************************/
sl_status_t sl_clock_manager_wait_usbpll(void)
{
return sli_clock_manager_hal_wait_usbpll();
}
/***************************************************************************//**
* When this callback function is called, it means that HFXO failed twice in
* a row to start with normal configurations. This may mean that there is a
* bad crystal. When getting this callback, HFXO is running but its properties
* (frequency, precision) are not guaranteed. This should be considered as an
* error situation.
******************************************************************************/
__WEAK void sl_clock_manager_hfxo_notify_consecutive_failed_startups(void)
{
EFM_ASSERT(false);
}
/***************************************************************************//**
* Sets the external FLASH reference clock.
******************************************************************************/
sl_status_t sl_clock_manager_set_ext_flash_clk(sl_oscillator_t oscillator)
{
return sli_clock_manager_hal_set_ext_flash_clk(oscillator);
}
/***************************************************************************//**
* Gets the external FLASH clock source.
******************************************************************************/
sl_status_t sl_clock_manager_get_ext_flash_clk(sl_oscillator_t *oscillator)
{
return sli_clock_manager_hal_get_ext_flash_clk(oscillator);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/***************************************************************************//**
* @file
* @brief Clock Manager Init API implementations.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_clock_manager_init.h"
#include "sli_clock_manager_init_hal.h"
/***************************************************************************//**
* Initializes Oscillators and Clock branches.
******************************************************************************/
sl_status_t sl_clock_manager_init(void)
{
return sli_clock_manager_hal_init();
}

View File

@@ -0,0 +1,886 @@
/***************************************************************************//**
* @file
* @brief Clock Manager Init HAL API implementations.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_clock_manager_oscillator_config.h"
#include "sl_clock_manager_tree_config.h"
#include "sli_clock_manager_init_hal.h"
#include "sl_clock_manager.h"
#include "sl_status.h"
#include "sl_assert.h"
#include "em_device.h"
#include "em_cmu.h"
#include "sl_gpio.h"
#if defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
#include "sli_clock_manager_runtime_configuration.h"
#endif
#if defined(RFFPLL_PRESENT)
#if defined(SL_CLOCK_MANAGER_RFFPLL_BAND) && (SL_CLOCK_MANAGER_RFFPLL_BAND == 7)
#ifdef SL_CLOCK_MANAGER_AUTO_BAND_VALID
#include "rail_config.h"
#endif
#endif
#endif
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
// Fetch HFXO CTUNE value from USERDATA page as a manufacturing token
#define MFG_CTUNE_HFXO_ADDR 0x0FE00100UL
#define MFG_CTUNE_HFXO_VAL (*((uint16_t *) (MFG_CTUNE_HFXO_ADDR)))
// Fetch LFXO CTUNE value from USERDATA page as a manufacturing token
#define MFG_CTUNE_LFXO_ADDR 0x0FE0009CUL
#define MFG_CTUNE_LFXO_VAL (*((uint8_t *) (MFG_CTUNE_LFXO_ADDR)))
#if defined(RFFPLL_PRESENT)
// If RADIO_CONFIG_RFFPLL_CONFIG_PRESENT is not defined, either there is no
// radio configuration in the project or the radio configuration that is
// present does not include an RFFPLL configuration.
// In either case, the Auto-Band feature cannot work, so fall back to the
// default band (Band 9xx).
#if defined(SL_CLOCK_MANAGER_RFFPLL_BAND) && (SL_CLOCK_MANAGER_RFFPLL_BAND == 7)
#ifndef RADIO_CONFIG_RFFPLL_CONFIG_PRESENT
#undef SL_CLOCK_MANAGER_RFFPLL_BAND
#define SL_CLOCK_MANAGER_RFFPLL_BAND 6
#endif
#endif
#endif
// Allocated PRS channel for crystal sharing
#if defined(_HFXO_CTRL_PRSSTATUSSEL0_MASK)
#define HFXO_CRYSTSAL_SHARING_PRS_CHANNEL 0
#endif
#if defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
#define FUNCTION_SCOPE
#else
#define FUNCTION_SCOPE static
#endif
/*******************************************************************************
****************************** TYPEDEFS ***********************************
******************************************************************************/
#if defined(RFFPLL_PRESENT)
typedef struct {
uint32_t frequency; // Host target frequency.
uint8_t divider_y; // Divider Y for digital.
uint8_t divider_x; // Divider X for Radio.
uint8_t divider_n; // Feedback divider N.
} clock_manager_rffpll_config_t;
#endif
/*******************************************************************************
************************** LOCAL VARIABLES ********************************
******************************************************************************/
#if defined(RFFPLL_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1) \
&& (SL_CLOCK_MANAGER_RFFPLL_CUSTOM_BAND == 0) \
&& !((SL_CLOCK_MANAGER_RFFPLL_BAND == 7) && defined(RADIO_CONFIG_RFFPLL_CONFIG_PRESENT))
// Table of possible radio frequency bands and their associated settings.
static clock_manager_rffpll_config_t rffpll_band_config_39MHz[] = {
{ 97500000, 23, 7, 115 }, // Band 450 MHz
{ 98380000, 22, 7, 111 }, // Band 470 MHz
{ 97500000, 23, 7, 115 }, // Band 780 MHz
{ 97500000, 20, 6, 100 }, // Band 863 MHz
{ 97500000, 23, 7, 115 }, // Band 896 MHz
{ 96520000, 20, 6, 99 }, // Band 928 MHz
{ 97500000, 20, 6, 100 } // Band 9xx MHz (covers from 901 to 928 MHz)
};
#endif
/*******************************************************************************
************************** GLOBAL VARIABLES *******************************
******************************************************************************/
#if defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
uint32_t SLI_CLOCK_MANAGER_HFXO_MODE = SL_CLOCK_MANAGER_HFXO_MODE;
uint32_t SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY = SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY_DEFAULT;
uint32_t SLI_CLOCK_MANAGER_HFRCO_BAND = SL_CLOCK_MANAGER_HFRCO_BAND;
#endif
/*******************************************************************************
*************************** LOCAL FUNCTIONS *******************************
******************************************************************************/
#if defined(HFXO_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && SL_CLOCK_MANAGER_HFXO_EN == 1
/***************************************************************************//**
* Initializes HFXO Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_hfxo(void)
{
CMU_HFXOInit_TypeDef clock_manager_hfxo_init = CMU_HFXOINIT_DEFAULT;
clock_manager_hfxo_init.mode = SLI_CLOCK_MANAGER_HFXO_MODE >> _HFXO_CFG_MODE_SHIFT;
if (SLI_CLOCK_MANAGER_HFXO_MODE == cmuHfxoOscMode_ExternalSine) {
clock_manager_hfxo_init = (CMU_HFXOInit_TypeDef)CMU_HFXOINIT_EXTERNAL_SINE;
#if defined(_HFXO_CFG_MODE_EXTCLKPKDET)
} else if (SLI_CLOCK_MANAGER_HFXO_MODE == cmuHfxoOscMode_ExternalSinePkDet) {
clock_manager_hfxo_init = (CMU_HFXOInit_TypeDef)CMU_HFXOINIT_EXTERNAL_SINEPKDET;
#endif
}
int ctune = -1;
#if defined(_DEVINFO_MODXOCAL_HFXOCTUNEXIANA_MASK)
// Use HFXO tuning value from DEVINFO if available (PCB modules)
if ((DEVINFO->MODULEINFO & _DEVINFO_MODULEINFO_HFXOCALVAL_MASK) == 0) {
ctune = DEVINFO->MODXOCAL & _DEVINFO_MODXOCAL_HFXOCTUNEXIANA_MASK;
}
#endif
// Use HFXO tuning value from MFG token in UD page if not already set
if ((ctune == -1)
#if defined(SL_CLOCK_MANAGER_CTUNE_MFG_HFXO_EN)
&& (SL_CLOCK_MANAGER_CTUNE_MFG_HFXO_EN == 1)
#endif
&& (MFG_CTUNE_HFXO_VAL <= (_HFXO_XTALCTRL_CTUNEXIANA_MASK >> _HFXO_XTALCTRL_CTUNEXIANA_SHIFT))) {
ctune = MFG_CTUNE_HFXO_VAL;
}
// Use HFXO tuning value from configurations as fallback
if (ctune == -1) {
ctune = SL_CLOCK_MANAGER_HFXO_CTUNE;
}
// Configure CTUNE XI and XO.
if (ctune != -1) {
clock_manager_hfxo_init.ctuneXiAna = (uint8_t)ctune;
// Ensure CTUNE XO plus a delta is within the correct range. The delta accounts for internal chip
// load imbalance on some series 2 chips.
ctune += CMU_HFXOCTuneDeltaGet();
if (ctune < 0) {
ctune = 0;
} else if (ctune > ((int)(_HFXO_XTALCTRL_CTUNEXOANA_MASK >> _HFXO_XTALCTRL_CTUNEXOANA_SHIFT))) {
ctune = (int)(_HFXO_XTALCTRL_CTUNEXOANA_MASK >> _HFXO_XTALCTRL_CTUNEXOANA_SHIFT);
}
clock_manager_hfxo_init.ctuneXoAna = ctune;
}
#if defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
if (SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY != SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY_DEFAULT) {
clock_manager_hfxo_init.ctuneFixAna = SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY;
}
#endif
#if defined(SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_EN) && (SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_EN == 1)
// Set port and pin.
GPIO_Port_TypeDef port = SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_GPIO_PORT;
unsigned int pin = SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_GPIO_PIN;
// Enable HFXO and GPIO bus clocks.
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_HFXO0);
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
#if defined(SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_FOLLOWER_EN) && (SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_FOLLOWER_EN == 1)
// Initialize Crystal sharing follower.
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_PRS);
EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
uint32_t mask = 0U, value = 0U;
bool was_locked = HFXO0->STATUS & HFXO_STATUS_LOCK_LOCKED ? true : false;
// Unlock register interface.
HFXO0->LOCK = HFXO_LOCK_LOCKKEY_UNLOCK;
HFXO0->IEN_SET = HFXO_IEN_BUFOUTRDY;
BUS_RegMaskedWrite(&HFXO0->CTRL, _HFXO_CTRL_PRSSTATUSSEL0_MASK, (_HFXO_CTRL_PRSSTATUSSEL0_ENS << _HFXO_CTRL_PRSSTATUSSEL0_SHIFT));
if (was_locked) {
HFXO0->LOCK = ~HFXO_LOCK_LOCKKEY_UNLOCK;
}
value = _PRS_ASYNC_CH_CTRL_AUXSEL_DEFAULT << _PRS_ASYNC_CH_CTRL_AUXSEL_SHIFT
| _PRS_ASYNC_CH_CTRL_FNSEL_A << _PRS_ASYNC_CH_CTRL_FNSEL_SHIFT
| _PRS_ASYNC_CH_CTRL_SOURCESEL_HFXO0L << _PRS_ASYNC_CH_CTRL_SOURCESEL_SHIFT
| _PRS_ASYNC_CH_CTRL_SIGSEL_HFXO0LSTATUS << _PRS_ASYNC_CH_CTRL_SIGSEL_SHIFT;
mask = _PRS_ASYNC_CH_CTRL_AUXSEL_MASK
| _PRS_ASYNC_CH_CTRL_FNSEL_MASK
| _PRS_ASYNC_CH_CTRL_SOURCESEL_MASK
| _PRS_ASYNC_CH_CTRL_SIGSEL_MASK;
BUS_RegMaskedWrite(&(PRS->ASYNC_CH[HFXO_CRYSTSAL_SHARING_PRS_CHANNEL].CTRL), mask, value);
GPIO_PinModeSet(port, pin, gpioModeWiredOrPullDown, 0U);
(&(GPIO->PRSROUTE[0].ASYNCH0ROUTE))[HFXO_CRYSTSAL_SHARING_PRS_CHANNEL] = pin << _GPIO_PRS_ASYNCH0ROUTE_PIN_SHIFT
| port << _GPIO_PRS_ASYNCH0ROUTE_PORT_SHIFT;
GPIO->PRSROUTE[0].ROUTEEN = 1U << (_GPIO_PRS_ROUTEEN_ASYNCH0PEN_SHIFT + HFXO_CRYSTSAL_SHARING_PRS_CHANNEL);
//sl_clock_manager_disable_bus_clock(SL_BUS_CLOCK_PRS);
#elif defined(SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_LEADER_EN) && (SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_LEADER_EN == 1)
EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
// Configure Bufout request GPIO.
GPIO_PinModeSet(port, pin, gpioModeInput, 0U);
GPIO->SYXOROUTE[0].BUFOUTREQINASYNCROUTE = pin << _GPIO_SYXO_BUFOUTREQINASYNCROUTE_PIN_SHIFT
| port << _GPIO_SYXO_BUFOUTREQINASYNCROUTE_PORT_SHIFT;
bool was_locked = HFXO0->STATUS & HFXO_STATUS_LOCK_LOCKED ? true : false;
// Unlock register interface.
HFXO0->LOCK = HFXO_LOCK_LOCKKEY_UNLOCK;
HFXO0->CTRL_CLR = _HFXO_CTRL_BUFOUTFREEZE_MASK | _HFXO_CTRL_DISONDEMANDBUFOUT_MASK;
BUS_RegMaskedWrite(&HFXO0->BUFOUTCTRL,
_HFXO_BUFOUTCTRL_MINIMUMSTARTUPDELAY_MASK
| _HFXO_BUFOUTCTRL_TIMEOUTSTARTUP_MASK,
((uint32_t)SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_LEADER_MIN_STARTUP_DELAY_EN) << _HFXO_BUFOUTCTRL_MINIMUMSTARTUPDELAY_SHIFT
| SL_CLOCK_MANAGER_HFXO_CRYSTAL_SHARING_LEADER_TIMEOUT_STARTUP);
if (was_locked) {
HFXO0->LOCK = ~HFXO_LOCK_LOCKKEY_UNLOCK;
}
#endif
#endif
SystemHFXOClockSet(SL_CLOCK_MANAGER_HFXO_FREQ);
CMU_HFXOInit(&clock_manager_hfxo_init);
CMU_HFXOPrecisionSet(SL_CLOCK_MANAGER_HFXO_PRECISION);
#if defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
if (SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY == SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY_DEFAULT) {
SLI_CLOCK_MANAGER_HFXO_CTUNE_FIXED_STEADY = (HFXO0->XTALCTRL & _HFXO_XTALCTRL_CTUNEFIXANA_MASK) >> _HFXO_XTALCTRL_CTUNEFIXANA_SHIFT;
}
#endif
return SL_STATUS_OK;
}
#endif
#if defined(LFXO_PRESENT) \
&& defined(SL_CLOCK_MANAGER_LFXO_EN) && SL_CLOCK_MANAGER_LFXO_EN == 1
/***************************************************************************//**
* Initializes LFXO Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_lfxo(void)
{
CMU_LFXOInit_TypeDef clock_manager_lfxo_init = CMU_LFXOINIT_DEFAULT;
clock_manager_lfxo_init.mode = SL_CLOCK_MANAGER_LFXO_MODE >> _LFXO_CFG_MODE_SHIFT;
clock_manager_lfxo_init.timeout = SL_CLOCK_MANAGER_LFXO_TIMEOUT >> _LFXO_CFG_TIMEOUT_SHIFT;
clock_manager_lfxo_init.capTune = 0xFF;
#ifndef _SILICON_LABS_32B_SERIES_2_CONFIG_9
#if defined(_DEVINFO_MODXOCAL_LFXOCAPTUNE_MASK)
// Use LFXO tuning value from DEVINFO if available (PCB modules)
if ((DEVINFO->MODULEINFO & _DEVINFO_MODULEINFO_LFXOCALVAL_MASK) == _DEVINFO_MODULEINFO_LFXOCALVAL_VALID) {
clock_manager_lfxo_init.capTune = DEVINFO->MODXOCAL & _DEVINFO_MODXOCAL_LFXOCAPTUNE_MASK;
}
#endif
#endif
if ((clock_manager_lfxo_init.capTune == 0xFF)
#if defined(SL_CLOCK_MANAGER_CTUNE_MFG_LFXO_EN)
&& (SL_CLOCK_MANAGER_CTUNE_MFG_LFXO_EN == 1)
#endif
&& (MFG_CTUNE_LFXO_VAL <= (_LFXO_CAL_CAPTUNE_MASK >> _LFXO_CAL_CAPTUNE_SHIFT))) {
clock_manager_lfxo_init.capTune = MFG_CTUNE_LFXO_VAL;
}
if (clock_manager_lfxo_init.capTune == 0xFF) {
clock_manager_lfxo_init.capTune = SL_CLOCK_MANAGER_LFXO_CTUNE;
}
CMU_LFXOInit(&clock_manager_lfxo_init);
CMU_LFXOPrecisionSet(SL_CLOCK_MANAGER_LFXO_PRECISION);
return SL_STATUS_OK;
}
#endif
/***************************************************************************//**
* Initializes Clock Input CLKIN0.
******************************************************************************/
static sl_status_t init_clkin0(void)
{
sl_status_t status = SL_STATUS_OK;
#if (defined(SL_CLOCK_MANAGER_SYSCLK_SOURCE) && (SL_CLOCK_MANAGER_SYSCLK_SOURCE == CMU_SYSCLKCTRL_CLKSEL_CLKIN0)) \
|| (defined(SL_CLOCK_MANAGER_DPLL_REFCLK) && (SL_CLOCK_MANAGER_DPLL_REFCLK == CMU_DPLLREFCLKCTRL_CLKSEL_CLKIN0)) \
|| (defined(SL_CLOCK_MANAGER_EM01GRPBCLK_SOURCE) && (SL_CLOCK_MANAGER_EM01GRPBCLK_SOURCE == CMU_EM01GRPBCLKCTRL_CLKSEL_CLKIN0))
#if !defined(SL_CLOCK_MANAGER_CLKIN0_PORT) || !defined(SL_CLOCK_MANAGER_CLKIN0_PIN)
#error "Invalid configuration: CLKIN0 reference can't be use without configuring SL_CLOCK_MANAGER_CLKIN0 with a valid port and pin."
#endif
sl_gpio_t clkin0_gpio = { SL_CLOCK_MANAGER_CLKIN0_PORT, SL_CLOCK_MANAGER_CLKIN0_PIN };
status = sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
if (status != SL_STATUS_OK) {
return status;
}
status = sl_gpio_set_pin_mode(&clkin0_gpio, SL_GPIO_MODE_INPUT, false);
if (status == SL_STATUS_OK) {
GPIO->CMUROUTE.CLKIN0ROUTE = (clkin0_gpio.port << _GPIO_CMU_CLKIN0ROUTE_PORT_SHIFT)
| (clkin0_gpio.pin << _GPIO_CMU_CLKIN0ROUTE_PIN_SHIFT);
}
#endif
return status;
}
#if defined(HFRCO_PRESENT)
/***************************************************************************//**
* Initializes HFRCODPLL Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_hfrcodpll(void)
{
#if defined(SL_CLOCK_MANAGER_HFRCO_DPLL_EN) && (SL_CLOCK_MANAGER_HFRCO_DPLL_EN == 1)
CMU_DPLLInit_TypeDef clock_manager_dpll_init = {
.frequency = SL_CLOCK_MANAGER_DPLL_FREQ,
.n = SL_CLOCK_MANAGER_DPLL_N,
.m = SL_CLOCK_MANAGER_DPLL_M,
.edgeSel = SL_CLOCK_MANAGER_DPLL_EDGE,
.lockMode = SL_CLOCK_MANAGER_DPLL_LOCKMODE,
.autoRecover = SL_CLOCK_MANAGER_DPLL_AUTORECOVER,
.ditherEn = SL_CLOCK_MANAGER_DPLL_DITHER
};
// Convert the DPLL Reference clock configuration to emlib CMU_Select_TypeDef type.
switch (SL_CLOCK_MANAGER_DPLL_REFCLK) {
case CMU_DPLLREFCLKCTRL_CLKSEL_HFXO:
clock_manager_dpll_init.refClk = cmuSelect_HFXO;
break;
case CMU_DPLLREFCLKCTRL_CLKSEL_LFXO:
clock_manager_dpll_init.refClk = cmuSelect_LFXO;
break;
case CMU_DPLLREFCLKCTRL_CLKSEL_CLKIN0:
clock_manager_dpll_init.refClk = cmuSelect_CLKIN0;
break;
default:
return SL_STATUS_INVALID_CONFIGURATION;
}
CMU_Select_TypeDef selected_sysclk = CMU_ClockSelectGet(cmuClock_SYSCLK);
if (selected_sysclk == cmuSelect_HFRCODPLL) {
// The CMU should not be running from the HFRCO. If necessary, the CMU
// should switch to the FSRCO until after the DPLL has locked to avoid
// over-clocking due to overshoot.
CMU->SYSCLKCTRL = (CMU->SYSCLKCTRL & ~_CMU_SYSCLKCTRL_CLKSEL_MASK) | CMU_SYSCLKCTRL_CLKSEL_FSRCO;
}
#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
CMU_ClockEnable(cmuClock_DPLL0, true);
#endif
bool success = CMU_DPLLLock(&clock_manager_dpll_init);
// If CMU was initially running from HFRCO switch back from FSRCO.
if (selected_sysclk == cmuSelect_HFRCODPLL) {
CMU->SYSCLKCTRL = (CMU->SYSCLKCTRL & ~_CMU_SYSCLKCTRL_CLKSEL_MASK) | CMU_SYSCLKCTRL_CLKSEL_HFRCODPLL;
}
// If DPLL lock was unsuccessful, return status fail.
if (!success) {
// Disable DPLL0 if lock failed.
#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
CMU_ClockEnable(cmuClock_DPLL0, false);
#endif
return SL_STATUS_FAIL;
}
#else
CMU_HFRCODPLLBandSet(SLI_CLOCK_MANAGER_HFRCO_BAND);
#endif
return SL_STATUS_OK;
}
#endif
#if defined(HFRCOEM23_PRESENT)
/***************************************************************************//**
* Initializes HFRCOEM23 Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_hfrcoem23(void)
{
CMU_HFRCOEM23BandSet(SL_CLOCK_MANAGER_HFRCOEM23_BAND);
return SL_STATUS_OK;
}
#endif
#if defined(LFRCO_PRESENT)
/***************************************************************************//**
* Initializes LFRCO Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_lfrco(void)
{
#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
CMU_ClockEnable(cmuClock_LFRCO, true);
#endif
#if defined(PLFRCO_PRESENT)
#if !(defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1))
EFM_ASSERT(SL_CLOCK_MANAGER_LFRCO_PRECISION != cmuPrecisionHigh);
#endif
CMU_LFRCOSetPrecision(SL_CLOCK_MANAGER_LFRCO_PRECISION);
#endif
return SL_STATUS_OK;
}
#endif
#if defined(RFFPLL_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1)
/***************************************************************************//**
* Initializes RFFPLL Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_rffpll(void)
{
CMU_RFFPLL_Init_TypeDef rffpll_init = CMU_RFFPLL_DEFAULT;
// Overwrite default configurations.
#if (SL_CLOCK_MANAGER_RFFPLL_CUSTOM_BAND == 1)
// Custom settings provided by the user.
rffpll_init.frequency = SL_CLOCK_MANAGER_RFFPLL_FREQ;
rffpll_init.dividerY = SL_CLOCK_MANAGER_RFFPLL_DIV_Y;
rffpll_init.dividerX = SL_CLOCK_MANAGER_RFFPLL_DIV_X;
rffpll_init.dividerN = SL_CLOCK_MANAGER_RFFPLL_DIV_N;
#elif (SL_CLOCK_MANAGER_RFFPLL_BAND == 7) && defined(RADIO_CONFIG_RFFPLL_CONFIG_PRESENT)
// Settings from the RAIL lib.
rffpll_init.frequency = radioConfigRffpllConfig->sysclkFreqHz;
rffpll_init.dividerY = ((radioConfigRffpllConfig->dividers & RAIL_RFFPLL_DIVIDERY_MASK) >> RAIL_RFFPLL_DIVIDERY_SHIFT);
rffpll_init.dividerX = ((radioConfigRffpllConfig->dividers & RAIL_RFFPLL_DIVIDERX_MASK) >> RAIL_RFFPLL_DIVIDERX_SHIFT);
rffpll_init.dividerN = ((radioConfigRffpllConfig->dividers & RAIL_RFFPLL_DIVIDERN_MASK) >> RAIL_RFFPLL_DIVIDERN_SHIFT);
#else
// Pre-determined settings.
rffpll_init.frequency = rffpll_band_config_39MHz[SL_CLOCK_MANAGER_RFFPLL_BAND].frequency;
rffpll_init.dividerY = rffpll_band_config_39MHz[SL_CLOCK_MANAGER_RFFPLL_BAND].divider_y;
rffpll_init.dividerX = rffpll_band_config_39MHz[SL_CLOCK_MANAGER_RFFPLL_BAND].divider_x;
rffpll_init.dividerN = rffpll_band_config_39MHz[SL_CLOCK_MANAGER_RFFPLL_BAND].divider_n;
#endif
// Initialize RFFPLL.
CMU_RFFPLLInit(&rffpll_init);
// Update RFFPLL frequency in System file
SystemRFFPLLClockSet(rffpll_init.frequency);
// At this point, RFFPLL has been initialized. The clock source for SYSCLK can be
// RFFPLLSYS input clock. If you want RFFPLLSYS, configure SL_CLOCK_MANAGER_SYSCLK_SOURCE
// to CMU_SYSCLKCTRL_CLKSEL_RFFPLL0SYS.
return SL_STATUS_OK;
}
#endif
#if defined(USBPLL_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1)
/***************************************************************************//**
* Initializes USBPLL Oscillator.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_usbpll(void)
{
CMU_USBPLL_Init_TypeDef usbpll_config;
uint32_t hfxo_freq = SystemHFXOClockGet();
// Validate that HFXO frequency is adequate for USB PLL and set the right frequency.
switch (hfxo_freq) {
case 38000000:
usbpll_config.hfxoRefFreq = cmuHFXORefFreq_38M0Hz;
break;
case 38400000:
usbpll_config.hfxoRefFreq = cmuHFXORefFreq_38M4Hz;
break;
case 39000000:
usbpll_config.hfxoRefFreq = cmuHFXORefFreq_39M0Hz;
break;
case 40000000:
usbpll_config.hfxoRefFreq = cmuHFXORefFreq_40M0Hz;
break;
default:
return SL_STATUS_FAIL;
}
// Set additional configurations.
usbpll_config.shuntRegEn = false;
usbpll_config.disOnDemand = false;
usbpll_config.regLock = true;
// Set Force Enable feature at first to force the PLL to start and validate it works.
usbpll_config.forceEn = true;
// Initialize USB PLL and wait for it to be ready.
CMU_USBPLLInit(&usbpll_config);
// Remove the Force Enable feature to let PLL module on-demand.
usbpll_config.forceEn = false;
// Re-initialized without the Force Enable feature.
CMU_USBPLLInit(&usbpll_config);
return SL_STATUS_OK;
}
#endif
/***************************************************************************//**
* Initializes Clock branches.
******************************************************************************/
FUNCTION_SCOPE sl_status_t init_clock_branches(void)
{
// Initialize SYSCLK clock branch.
#if defined(SL_CLOCK_MANAGER_SYSCLK_SOURCE)
sli_em_cmu_SYSCLKInitPreClockSelect();
#if (SL_CLOCK_MANAGER_SYSCLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(SYSCLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(SYSCLK, SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(SYSCLK, SL_CLOCK_MANAGER_SYSCLK_SOURCE);
#endif
sli_em_cmu_SYSCLKInitPostClockSelect(false);
CMU->SYSCLKCTRL = (CMU->SYSCLKCTRL & ~(_CMU_SYSCLKCTRL_HCLKPRESC_MASK | _CMU_SYSCLKCTRL_PCLKPRESC_MASK))
| SL_CLOCK_MANAGER_HCLK_DIVIDER
| SL_CLOCK_MANAGER_PCLK_DIVIDER;
#else
EFM_ASSERT(false);
#endif
// Initialize TRACECLK clock branch.
#if defined(CoreDebug_DEMCR_TRCENA_Msk)
// Disable the Core Debug module if already enabled
bool trace_on = CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk;
if (trace_on) {
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
}
#endif
#if defined(SL_CLOCK_MANAGER_TRACECLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(TRACECLK, SL_CLOCK_MANAGER_TRACECLK_SOURCE);
#endif
#if defined(SL_CLOCK_MANAGER_TRACECLK_DIVIDER)
CMU->TRACECLKCTRL |= SL_CLOCK_MANAGER_TRACECLK_DIVIDER;
#endif
#if defined(CoreDebug_DEMCR_TRCENA_Msk)
// Enable back the Core Debug module if it was already enabled
if (trace_on) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
}
#endif
// Ensure TraceClk configs are defined if TraceClk is present.
#if defined(_CMU_TRACECLKCTRL_MASK) && !(defined(SL_CLOCK_MANAGER_TRACECLK_SOURCE) || defined(SL_CLOCK_MANAGER_TRACECLK_DIVIDER))
EFM_ASSERT(false);
#endif
// Initialize EM01GRPACLK clock branch.
#if defined(SL_CLOCK_MANAGER_EM01GRPACLK_SOURCE)
#if (SL_CLOCK_MANAGER_EM01GRPACLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EM01GRPACLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(EM01GRPACLK, SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(EM01GRPACLK, SL_CLOCK_MANAGER_EM01GRPACLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
// Initialize EM01GRPBCLK clock branch.
#if defined(PDM_PRESENT)
#if defined(SL_CLOCK_MANAGER_EM01GRPBCLK_SOURCE)
#if (SL_CLOCK_MANAGER_EM01GRPBCLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EM01GRPBCLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(EM01GRPBCLK, SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(EM01GRPBCLK, SL_CLOCK_MANAGER_EM01GRPBCLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize EM01GRPCCLK clock branch.
#if defined(_CMU_EM01GRPCCLKCTRL_MASK)
#if defined(SL_CLOCK_MANAGER_EM01GRPCCLK_SOURCE)
#if (SL_CLOCK_MANAGER_EM01GRPCCLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EM01GRPCCLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(EM01GRPCCLK, SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(EM01GRPCCLK, SL_CLOCK_MANAGER_EM01GRPCCLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize IADCCLK clock branch.
#if defined(SL_CLOCK_MANAGER_IADCCLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(IADCCLK, SL_CLOCK_MANAGER_IADCCLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
// Initialize LESENSEHFCLK clock branch.
#if defined(LESENSE_PRESENT)
#if defined(SL_CLOCK_MANAGER_LESENSEHFCLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(LESENSEHFCLK, SL_CLOCK_MANAGER_LESENSEHFCLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize EM23GRPACLK clock branch.
#if defined(SL_CLOCK_MANAGER_EM23GRPACLK_SOURCE)
#if (SL_CLOCK_MANAGER_EM23GRPACLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EM23GRPACLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(EM23GRPACLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(EM23GRPACLK, SL_CLOCK_MANAGER_EM23GRPACLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
// Initialize EM4GRPACLK clock branch.
#if defined(SL_CLOCK_MANAGER_EM4GRPACLK_SOURCE)
#if (SL_CLOCK_MANAGER_EM4GRPACLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EM4GRPACLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(EM4GRPACLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(EM4GRPACLK, SL_CLOCK_MANAGER_EM4GRPACLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
// Initialize RTCC clock branch.
#if defined(RTCC_PRESENT)
#if defined(SL_CLOCK_MANAGER_RTCCCLK_SOURCE)
#if (SL_CLOCK_MANAGER_RTCCCLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(RTCCCLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(RTCCCLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(RTCCCLK, SL_CLOCK_MANAGER_RTCCCLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize SYSRTC clock branch.
#if defined(SYSRTC_PRESENT)
#if defined(SL_CLOCK_MANAGER_SYSRTCCLK_SOURCE)
#if (SL_CLOCK_MANAGER_SYSRTCCLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(SYSRTC0CLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(SYSRTC0CLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(SYSRTC0CLK, SL_CLOCK_MANAGER_SYSRTCCLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize WDOG0 clock branch.
#if defined(SL_CLOCK_MANAGER_WDOG0CLK_SOURCE)
#if (SL_CLOCK_MANAGER_WDOG0CLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(WDOG0CLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(WDOG0CLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(WDOG0CLK, SL_CLOCK_MANAGER_WDOG0CLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
// Initialize WDOG1 clock branch.
#if WDOG_COUNT > 1
#if defined(SL_CLOCK_MANAGER_WDOG1CLK_SOURCE)
#if (SL_CLOCK_MANAGER_WDOG1CLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(WDOG1CLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(WDOG1CLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(WDOG1CLK, SL_CLOCK_MANAGER_WDOG1CLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize LCD clock branch.
#if defined(LCD_PRESENT)
#if defined(SL_CLOCK_MANAGER_LCDCLK_SOURCE)
#if (SL_CLOCK_MANAGER_LCDCLK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(LCDCLK, CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(LCDCLK, SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION));
#else
CLOCK_MANAGER_CLOCK_SELECT_SET(LCDCLK, SL_CLOCK_MANAGER_LCDCLK_SOURCE);
#endif
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize PCNT0 clock branch.
#if defined(PCNT_PRESENT)
#if defined(SL_CLOCK_MANAGER_PCNT0CLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(PCNT0CLK, SL_CLOCK_MANAGER_PCNT0CLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize EUSART0
#if defined(EUSART_PRESENT)
#if defined(SL_CLOCK_MANAGER_EUSART0CLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EUSART0CLK, SL_CLOCK_MANAGER_EUSART0CLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize EUART
#if defined(EUART_PRESENT)
#if defined(SL_CLOCK_MANAGER_EUART0CLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(EUART0CLK, SL_CLOCK_MANAGER_EUART0CLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
#endif
// Initialize SYSTICK clock branch.
#if defined(SL_CLOCK_MANAGER_SYSTICKCLK_SOURCE)
#if (SL_CLOCK_MANAGER_SYSTICKCLK_SOURCE == 1)
CMU_CLOCK_SELECT_SET(SYSTICK, EM23GRPACLK);
#elif (SL_CLOCK_MANAGER_SYSTICKCLK_SOURCE == 0)
CMU_CLOCK_SELECT_SET(SYSTICK, HCLK);
#else
EFM_ASSERT(false);
#endif
#else
EFM_ASSERT(false);
#endif
// Initialize VDAC0 clock branch.
#if defined(VDAC_PRESENT)
#if defined(SL_CLOCK_MANAGER_VDAC0CLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(VDAC0CLK, SL_CLOCK_MANAGER_VDAC0CLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
// Initialize VDAC1 clock branch.
#if VDAC_COUNT > 1
#if defined(SL_CLOCK_MANAGER_VDAC1CLK_SOURCE)
CLOCK_MANAGER_CLOCK_SELECT_SET(VDAC1CLK, SL_CLOCK_MANAGER_VDAC1CLK_SOURCE);
#else
EFM_ASSERT(false);
#endif
#endif
#endif
return SL_STATUS_OK;
}
/*******************************************************************************
********************** GLOBAL INTERNAL FUNCTIONS **************************
******************************************************************************/
/***************************************************************************//**
* Initializes Oscillators and Clock branches.
******************************************************************************/
sl_status_t sli_clock_manager_hal_init(void)
{
sl_status_t status;
#if defined(SYSRTC_PRESENT)
status = sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_SYSRTC0);
if (status != SL_STATUS_OK) {
return status;
}
#endif
// Initialize Oscillators
#if defined(LFXO_PRESENT) \
&& defined(SL_CLOCK_MANAGER_LFXO_EN) && (SL_CLOCK_MANAGER_LFXO_EN == 1)
status = init_lfxo();
if (status != SL_STATUS_OK) {
return status;
}
#endif
#if defined(HFXO_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1)
status = init_hfxo();
if (status != SL_STATUS_OK) {
return status;
}
#endif
status = init_clkin0();
if (status != SL_STATUS_OK) {
return status;
}
#if defined(HFRCO_PRESENT)
status = init_hfrcodpll();
if (status != SL_STATUS_OK) {
return status;
}
#endif
#if defined(HFRCOEM23_PRESENT)
status = init_hfrcoem23();
if (status != SL_STATUS_OK) {
return status;
}
#endif
#if defined(LFRCO_PRESENT)
status = init_lfrco();
if (status != SL_STATUS_OK) {
return status;
}
#endif
#if defined(RFFPLL_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1)
status = init_rffpll();
if (status != SL_STATUS_OK) {
return status;
}
#endif
#if defined(USBPLL_PRESENT) \
&& defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1)
status = init_usbpll();
if (status != SL_STATUS_OK) {
return status;
}
#endif
// Initialize Clock branches
status = init_clock_branches();
if (status != SL_STATUS_OK) {
return status;
}
return SL_STATUS_OK;
}

View File

@@ -0,0 +1,198 @@
/***************************************************************************//**
* @file
* @brief Clock Manager HAL APIs.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_CLOCK_MANAGER_HAL_H
#define SL_CLOCK_MANAGER_HAL_H
#include "sl_clock_manager.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* Performs Clock Manager runtime initialization.
******************************************************************************/
sl_status_t sli_clock_manager_hal_runtime_init(void);
/***************************************************************************//**
* Gets frequency of given oscillator.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_hal_get_oscillator_frequency(sl_oscillator_t oscillator,
uint32_t *frequency);
/***************************************************************************//**
* Gets precision of given oscillator.
******************************************************************************/
sl_status_t sli_clock_manager_hal_get_oscillator_precision(sl_oscillator_t oscillator,
uint16_t *precision);
/***************************************************************************//**
* Gets frequency of given clock branch.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_hal_get_clock_branch_frequency(sl_clock_branch_t clock_branch,
uint32_t *frequency);
/***************************************************************************//**
* Gets precision of given clock branch.
******************************************************************************/
sl_status_t sli_clock_manager_hal_get_clock_branch_precision(sl_clock_branch_t clock_branch,
uint16_t *precision);
/***************************************************************************//**
* Enables/Disables the bus clock associated with the given module.
******************************************************************************/
sl_status_t sli_clock_manager_hal_enable_bus_clock(sl_bus_clock_t module,
bool enable);
/***************************************************************************//**
* Configures the exported clock feature on CMU to output user selected
* clock source specified GPIO pin.
******************************************************************************/
sl_status_t sli_clock_manager_hal_set_gpio_clock_output(sl_clock_manager_export_clock_source_t export_clock_source,
sl_clock_manager_export_clock_output_select_t output_select,
uint16_t divider,
uint32_t port,
uint32_t pin);
/***************************************************************************//**
* Sets the RC oscillator frequency tuning control.
******************************************************************************/
sl_status_t sli_clock_manager_hal_set_rc_oscillator_calibration(sl_oscillator_t oscillator,
uint32_t val);
/***************************************************************************//**
* Gets the RC oscillator frequency tuning setting.
******************************************************************************/
sl_status_t sli_clock_manager_hal_get_rc_oscillator_calibration(sl_oscillator_t oscillator,
uint32_t *val);
/***************************************************************************//**
* Sets the HFXO calibration value.
******************************************************************************/
sl_status_t sli_clock_manager_hal_set_hfxo_calibration(uint32_t val);
/***************************************************************************//**
* Gets the HFXO calibration value.
******************************************************************************/
sl_status_t sli_clock_manager_hal_get_hfxo_calibration(uint32_t *val);
/***************************************************************************//**
* Sets the HFXO CTUNE setting.
******************************************************************************/
sl_status_t sli_clock_manager_hal_hfxo_set_ctune(uint32_t ctune);
/***************************************************************************//**
* Gets the HFXO CTUNE setting.
******************************************************************************/
sl_status_t sli_clock_manager_hal_hfxo_get_ctune(uint32_t *ctune);
/***************************************************************************//**
* Updates the tuning capacitances and calibrate the Core Bias Current.
******************************************************************************/
sl_status_t sli_clock_manager_hal_hfxo_calibrate_ctune(uint32_t ctune);
/***************************************************************************//**
* Sets the LFXO frequency tuning control.
******************************************************************************/
sl_status_t sli_clock_manager_hal_set_lfxo_calibration(uint32_t val);
/***************************************************************************//**
* Gets the LFXO frequency tuning setting.
******************************************************************************/
sl_status_t sli_clock_manager_hal_get_lfxo_calibration(uint32_t *val);
/***************************************************************************//**
* Configures the RCO calibration.
*****************************************************************************/
sl_status_t sli_clock_manager_hal_configure_rco_calibration(uint32_t cycles,
sl_clock_manager_clock_calibration_t down_counter_selection,
sl_clock_manager_clock_calibration_t up_counter_selection,
bool continuous_calibration);
/***************************************************************************//**
* Starts the RCO calibration.
******************************************************************************/
void sli_clock_manager_hal_start_rco_calibration (void);
/***************************************************************************//**
* Stops the RCO calibration.
******************************************************************************/
void sli_clock_manager_hal_stop_rco_calibration(void);
/***************************************************************************//**
* Waits for the RCO calibration to finish.
******************************************************************************/
void sli_clock_manager_hal_wait_rco_calibration(void);
/***************************************************************************//**
* Gets calibration count value.
******************************************************************************/
sl_status_t sli_clock_manager_hal_get_rco_calibration_count(uint32_t *count);
/***************************************************************************//**
* Sets SYSCLK clock source.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_hal_set_sysclk_source(sl_oscillator_t source);
/***************************************************************************//**
* Gets SYSCLK clock source.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_hal_get_sysclk_source(sl_oscillator_t *source);
/***************************************************************************//**
* Waits for USBPLL clock to be ready.
******************************************************************************/
sl_status_t sli_clock_manager_hal_wait_usbpll(void);
/***************************************************************************//**
* Sets the external FLASH reference clock.
*
* @note This API is not thread-safe and should therefore not be called
* across multiple tasks.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_hal_set_ext_flash_clk(sl_oscillator_t oscillator);
/***************************************************************************//**
* Gets the external FLASH clock source.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_CLOCK_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_clock_manager_hal_get_ext_flash_clk(sl_oscillator_t *oscillator);
#ifdef __cplusplus
}
#endif
#endif // SL_CLOCK_MANAGER_HAL_H

View File

@@ -0,0 +1,111 @@
/***************************************************************************//**
* @file
* @brief Clock Manager Init HAL APIs.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_CLOCK_MANAGER_INIT_HAL_H
#define SL_CLOCK_MANAGER_INIT_HAL_H
#include "sl_status.h"
#include "sl_clock_manager_tree_config.h"
#include "sl_clock_manager_oscillator_config.h"
#include "em_device.h"
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
******************************** MACROS ************************************
******************************************************************************/
#if (SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_HFRCODPLL)
#define SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION _HFRCODPLL
#elif (SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_HFXO)
#define SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION _HFXO
#elif (SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_FSRCO)
#define SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE_CONCATENATION _FSRCO
#else
#error "SL_CLOCK_MANAGER_DEFAULT_HF_CLOCK_SOURCE configuration value is invalid."
#endif
#if (SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_LFRCO)
#define SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION _LFRCO
#elif (SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_LFXO)
#define SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION _LFXO
#elif (SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE == SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_ULFRCO)
#define SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE_CONCATENATION _ULFRCO
#else
#error "SL_CLOCK_MANAGER_DEFAULT_LF_CLOCK_SOURCE configuration value is invalid."
#endif
#define CLOCK_MANAGER_CLOCK_SELECT_SET(clock_branch, clock_source) \
do { \
CMU->clock_branch##CTRL = (CMU->clock_branch##CTRL & ~_CMU_##clock_branch##CTRL_CLKSEL_MASK) \
| clock_source; \
} while (0)
#define CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE_NX(clock_branch, clock_source) CMU_##clock_branch##CTRL_CLKSEL##clock_source
#define CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE(clock_branch, clock_source) CLOCK_MANAGER_GET_DEFAULT_CLOCK_SOURCE_NX(clock_branch, clock_source)
#if !defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
#define SLI_CLOCK_MANAGER_HFXO_MODE SL_CLOCK_MANAGER_HFXO_MODE
#define SLI_CLOCK_MANAGER_HFRCO_BAND SL_CLOCK_MANAGER_HFRCO_BAND
#endif // #if !defined(SLI_CLOCK_MANAGER_RUNTIME_CONFIGURATION)
#if defined(SL_CLOCK_MANAGER_SOCPLL_EN) && (SL_CLOCK_MANAGER_SOCPLL_EN == 1)
#if defined(SL_CLOCK_MANAGER_SOCPLL_ADVANCED_SETTINGS) && (SL_CLOCK_MANAGER_SOCPLL_ADVANCED_SETTINGS == 0)
#if defined(SL_CATALOG_RAIL_LIB_PRESENT) || (defined(SL_CLOCK_MANAGER_HFXO_EN) && (SL_CLOCK_MANAGER_HFXO_EN == 1))
#define SL_CLOCK_MANAGER_SOCPLL_REFCLK SOCPLL_CTRL_REFCLKSEL_REF_HFXO
#define SL_CLOCK_MANAGER_SOCPLL_REFCLK_FREQ SL_CLOCK_MANAGER_HFXO_FREQ
#else
#define SL_CLOCK_MANAGER_SOCPLL_REFCLK SOCPLL_CTRL_REFCLKSEL_REF_HFRCO
#define SL_CLOCK_MANAGER_SOCPLL_REFCLK_FREQ SL_CLOCK_MANAGER_HFRCO_BAND
#endif
#define SL_CLOCK_MANAGER_SOCPLL_FRACTIONAL_EN 1
// SOCPLL Formula: SOCPLL_FREQ = REFCLK_FREQ * (DIVN+2 + DIVF/1024) / 6
// SL_CLOCK_MANAGER_SOCPLL_DIVN is rounded down and SL_CLOCK_MANAGER_SOCPLL_DIVF is rounded to the closest integer.
#define SL_CLOCK_MANAGER_SOCPLL_DIVN (6ULL * SL_CLOCK_MANAGER_SOCPLL_FREQ / SL_CLOCK_MANAGER_SOCPLL_REFCLK_FREQ - 2ULL)
#define SL_CLOCK_MANAGER_SOCPLL_DIVF ((6ULL * 1024ULL * SL_CLOCK_MANAGER_SOCPLL_FREQ + SL_CLOCK_MANAGER_SOCPLL_REFCLK_FREQ / 2ULL) / SL_CLOCK_MANAGER_SOCPLL_REFCLK_FREQ - 1024ULL * (SL_CLOCK_MANAGER_SOCPLL_DIVN + 2ULL))
#endif
#endif
/*******************************************************************************
****************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* Initializes Oscillators and Clock branches.
******************************************************************************/
sl_status_t sli_clock_manager_hal_init(void);
#ifdef __cplusplus
}
#endif
#endif // SL_CLOCK_MANAGER_INIT_HAL_H