1 /******************************************************************************* 2 * File Name: cyhal_clock.h 3 * 4 * Description: 5 * Provides a high level interface for interacting with the Clocks on the device. 6 * 7 ******************************************************************************** 8 * \copyright 9 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or 10 * an affiliate of Cypress Semiconductor Corporation 11 * 12 * SPDX-License-Identifier: Apache-2.0 13 * 14 * Licensed under the Apache License, Version 2.0 (the "License"); 15 * you may not use this file except in compliance with the License. 16 * You may obtain a copy of the License at 17 * 18 * http://www.apache.org/licenses/LICENSE-2.0 19 * 20 * Unless required by applicable law or agreed to in writing, software 21 * distributed under the License is distributed on an "AS IS" BASIS, 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 * See the License for the specific language governing permissions and 24 * limitations under the License. 25 *******************************************************************************/ 26 27 /** 28 * \addtogroup group_hal_clock Clock 29 * \ingroup group_hal 30 * \{ 31 * Interface for getting and changing clock configuration. 32 * 33 * The clock driver is a single API designed to allow reading and configuring 34 * any clock in the system. The driver works the same to configure System clocks 35 * as it does for Peripheral clocks. It supports both a readonly mode where any 36 * number of items can get information about the clock. Alternatively, each 37 * clock can have a single owner that is able to adjust the configuration of the 38 * clock. 39 * 40 * This driver supports source clocks, clock dividers, and clock signal muxes. 41 * All clock objects support the get() functions. Only some clocks support 42 * setting specific attributes. Use the \ref cyhal_clock_get_features() function 43 * to determine which features are settable for a specific clock. Calling a set() 44 * function on a clock that does not support it will return an error. 45 * 46 * This driver makes no assumptions about how the device is currently configured. 47 * It can be used from a completely unconfigured system (eg: device just booted) 48 * to a fully pre-configured (eg: setup by the Device Configurator). The drivers 49 * query and modify the actual state of the hardware, there is no caching or 50 * remembering of state. To maximize portability of code, it is often convenient 51 * to place all system clock configuration into a Board Support Package (BSP) so 52 * the main application code is flexible and can port between devices. 53 * 54 * All System Clock instances are available as constant variables in the 55 * implementation specific header. These clocks can be used directly to call 56 * any get() function. Similarly, \ref cyhal_clock_get allows for getting 57 * access to a specific clock object given a resource instance. Like the 58 * constant variables, this clock reference can be used to call any of the 59 * get() functions at any time. If a clock needs to be modified, either 60 * \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called to 61 * obtain a lock on the clock object and to ensure that nothing else in the 62 * application is currently using it or assuming its configuration is stable. 63 * If exclusive control of a clock is no longer needed \ref cyhal_clock_free 64 * can be called to release it. This will remove the lock allowing something 65 * else in the system to potentially modify its state. 66 * 67 * \ref cyhal_clock_reserve and \ref cyhal_clock_allocate are very similar. They 68 * both reserve a clock object that can then be modified. The difference between 69 * them is the argument that is passed in. \ref cyhal_clock_reserve takes a 70 * specific instance that it will attempt to reserve. \ref cyhal_clock_allocate 71 * takes in a type of clock that it will attempt to find a free instance for and 72 * reserve that. 73 * 74 * \note After calling \ref cyhal_clock_free the clock object can still be used 75 * to call any of the get() functions just as is possible from the instance 76 * returned by \ref cyhal_clock_get or using any of the constant clock variables. 77 * 78 * \note A clock only needs to be allocated ( \ref cyhal_clock_allocate ) or 79 * reserved ( \ref cyhal_clock_reserve ) if its configuration needs to be changed 80 * by calling one of the set() functions. 81 * 82 * \note While the API is generic, the specific clock resource instances 83 * (\ref cyhal_resource_inst_t) are device specific. See the implementation 84 * specific sections for more details on what clocks and hardware resources are 85 * available. 86 * 87 * \section section_clock_features Features 88 * * Queryable clock features 89 * * Configurable clock enablement 90 * * Configurable clock frequency/divider 91 * * Configurable clock sources 92 * * Reserve or share clock objects 93 * 94 * \section section_clock_quickstart Quick Start 95 * 96 * See \ref subsection_clock_snippet_1 for a code snippet that shows how to reserve 97 * and configure a clock object. 98 * 99 * \section section_clock_snippets Code snippets 100 * \note Error handling code has been intentionally left out of snippets to highlight API usage. 101 * 102 * \subsection subsection_clock_snippet_1 Snippet 1: Simple clock read only access 103 * The following snippet shows how get details about a clock if there is no need to adjust any of its 104 * settings (e.g. read only access). This does not require initializing a clock object. 105 * \snippet hal_clock.c snippet_cyhal_clock_simple_access 106 * 107 * \subsection subsection_clock_snippet_2 Snippet 2: Simple clock reservation and configuration 108 * The following snippet initializes a clock object, updates its frequency then enables it. 109 * \snippet hal_clock.c snippet_cyhal_clock_simple_init 110 * 111 * \subsection subsection_clock_snippet_3 Snippet 3: Clock allocation and reuse 112 * The following snippet shows how a clock can be allocated and reused for multiple peripheral instances. 113 * \snippet hal_clock.c snippet_cyhal_clock_simple_allocate 114 * 115 * \subsection subsection_clock_snippet_4 Snippet 4: Change clock source 116 * The following snippet shows how a to change the source of a clock. 117 * \snippet hal_clock.c snippet_cyhal_clock_change_source 118 * 119 * \subsection subsection_clock_snippet_5 Snippet 5: System initialization 120 * \note This example is device specific. See \ref subsection_clock_snippet_5_impl for specific implementation. 121 * 122 */ 123 124 #pragma once 125 126 #include <stdint.h> 127 #include <stdbool.h> 128 #include "cy_result.h" 129 #include "cyhal_hw_types.h" 130 131 #if defined(__cplusplus) 132 extern "C" 133 { 134 #endif 135 136 /** \addtogroup group_hal_results_clock Clock HAL Results 137 * Clock specific return codes 138 * \ingroup group_hal_results 139 * \{ *//** 140 */ 141 142 143 /** Error configuring clock frequency, divider, or multiplier. */ 144 #define CYHAL_CLOCK_RSLT_ERR_FREQ \ 145 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 0)) 146 /** Invalid source clock. */ 147 #define CYHAL_CLOCK_RSLT_ERR_SOURCE \ 148 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 1)) 149 /** Specified operation is not supported by the current clock. */ 150 #define CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED \ 151 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 2)) 152 /** The specified resource is not valid. */ 153 #define CYHAL_CLOCK_RSLT_ERR_RESOURCE \ 154 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 3)) 155 /** The clock did not lock after being enabled. */ 156 #define CYHAL_CLOCK_RSLT_ERR_LOCK \ 157 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 4)) 158 /** Source clock for the clock being configured is turned off. */ 159 #define CYHAL_CLOCK_RSLT_ERR_SOURCE_DISABLED \ 160 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_CLOCK, 5)) 161 162 /** 163 * \} 164 */ 165 166 /** \addtogroup group_hal_tolerance 167 * \{ *//** 168 * \{ @name Clock Tolerance 169 */ 170 171 /** Clock tolerance 0 percent */ 172 extern const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_0_P; 173 /** Clock tolerance 1 percent */ 174 extern const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_1_P; 175 /** Clock tolerance 5 percent */ 176 extern const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_5_P; 177 178 /** 179 * \} \} 180 */ 181 182 /** Enum defining the different features each clock can support of clocks. These are bit masks. 183 * These can be used to determine which set() APIs are legal for a particular clock. */ 184 typedef enum 185 { 186 CYHAL_CLOCK_FEATURE_NONE = (0), //!< No features of the clock are configurable. 187 CYHAL_CLOCK_FEATURE_ENABLE = (1 << 0), //!< The clock can be enabled & disabled \ref cyhal_clock_set_enabled. 188 CYHAL_CLOCK_FEATURE_FREQUENCY = (1 << 1), //!< The clock frequency can be adjusted \ref cyhal_clock_set_frequency. 189 CYHAL_CLOCK_FEATURE_DIVIDER = (1 << 2), //!< The clock divider can be adjusted \ref cyhal_clock_set_divider. 190 // Not available on any supported device yet. 191 // CYHAL_CLOCK_FEATURE_MULTIPLIER = (1 << 3), //!< The clock multiplier can be adjusted \ref cyhal_clock_set_multiplier. 192 CYHAL_CLOCK_FEATURE_SOURCE = (1 << 4), //!< The clock source can be adjusted \ref cyhal_clock_set_source. 193 } cyhal_clock_feature_t; 194 195 196 /** Get a Clock instance for readonly use. This clock object can be used to call 197 * any of the get() functions. To call any of the set() functions, \ref 198 * cyhal_clock_reserve must be called to get exclusive access to the clock object 199 * to allow it to be modified. 200 * 201 * @param[out] clock The clock object to store the initialized data into. The 202 * caller must allocate the memory for this object but the init function will 203 * initialize its contents. 204 * @param[in] resource The clock resource instance to initialize. 205 * @return The status of the get request. This will only return an error if the provided 206 * resource instance is not a valid clock object. 207 */ 208 cy_rslt_t cyhal_clock_get(cyhal_clock_t *clock, const cyhal_resource_inst_t *resource); 209 210 /** Reserves the specified Clock instance. 211 * Once the clock has been reserved the get() and set() functions can be used. If 212 * at any time the clock is no longer needed, it can be released by calling 213 * \ref cyhal_clock_free. 214 * \note This does not change the clock configuration or connections. 215 * 216 * @param[out] clock The clock object to initialize. The caller must allocate 217 * the memory for this object but the init function will initialize its contents. 218 * @param[in] clock_ The constant clock object to reserve 219 * @return The status of the reserve request. 220 */ 221 cy_rslt_t cyhal_clock_reserve(cyhal_clock_t *clock, const cyhal_clock_t *clock_); 222 223 /** Allocates and Reserves a Clock instance, of the provided block type, for use. 224 * This should be used when needing a specific type of clock but the exact instance 225 * does not matter. This does everything that is done by \ref cyhal_clock_reserve. 226 * Once the clock has been allocated the get() and set() functions can be used. If 227 * at any time the clock is no longer needed, it can be released by calling 228 * \ref cyhal_clock_free. 229 * \note This does not change the clock configuration or connections. 230 * \note This is generally only supported for clock blocks that have multiple instances 231 * 232 * @param[out] clock The clock object to initialize. The caller must allocate 233 * the memory for this object but the init function will initialize its contents. 234 * @param[in] block The specific type of clock to allocate 235 * @return The status of the allocate request. 236 */ 237 cy_rslt_t cyhal_clock_allocate(cyhal_clock_t *clock, cyhal_clock_block_t block); 238 239 /** Gets the features supported by the specified clock. This can be used to determine which 240 * set() APIs are legal to be called for this clock. 241 * 242 * @param[in] clock The clock object to get features for. 243 * @return The feature set that can be configured by this clock. Features are bit mask values. 244 */ 245 cyhal_clock_feature_t cyhal_clock_get_features(const cyhal_clock_t *clock); 246 247 /** Gets whether the specified clock is currently enabled and locked, if appropriate. While 248 * most clocks simply have an enabled state, Crystals, PLL, and a few others may also check 249 * to make sure the clock has locked and is stable before returning true. 250 * 251 * \note External clocks which cannot be enabled/disabled directly will return true 252 * if a frequency has been set for them, and false otherwise 253 * 254 * @param[in] clock The clock object to check if it is enabled. 255 * @return Whether the specified clock is enabled or not. 256 */ 257 bool cyhal_clock_is_enabled(const cyhal_clock_t *clock); 258 259 /** Attempts to update the enablement of the specified clock. This is only legal to call 260 * if the \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_ENABLE. 261 * 262 * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b> 263 * instance before using this function. 264 * 265 * \note If disabled, any clocks or peripherals that are using this will stop working. Make sure 266 * to switch the clock source (\ref cyhal_clock_set_source) of any downstream clocks if necessary 267 * to keep them running prior to disabling their source. 268 * 269 * @param[in] clock The clock object to update the enablement of. 270 * @param[in] enabled Whether the clock should be enabled (true) or disabled (false). 271 * @param[in] wait_for_lock Whether to wait for the clock to enable & lock (true), or just send 272 * the request and return (false). Most clocks behave the same either 273 * way, however Crystals, PLLs, and similar require time to lock. If 274 * false, \ref cyhal_clock_is_enabled needs to be used to check that 275 * it is running before using the clock. 276 * @return The status of the requested to change the clocks enablement. 277 */ 278 cy_rslt_t cyhal_clock_set_enabled(cyhal_clock_t *clock, bool enabled, bool wait_for_lock); 279 280 /** Gets the frequency (in Hz) the clock is currently operating at. 281 * 282 * @param[in] clock The clock object to get the frequency of. 283 * @return The frequency the clock is currently running at. 0 if the clock is disabled. 284 */ 285 uint32_t cyhal_clock_get_frequency(const cyhal_clock_t *clock); 286 287 /** Attempts to update the operating frequency of the clock. This is only legal to call 288 * if the \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_FREQUENCY. 289 * 290 * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b> 291 * instance before using this function. 292 * 293 * \note Some clocks (eg: FLLs & PLLs) may need to be stopped before their frequency can 294 * be changed. This function will take care of disabling & re-enabling as necessary, however, 295 * this can cause a temporary glitch on anything that is running off of the clock at the time. 296 * If glitch free operation is required, change the source of any downstream clocks the 297 * application before changing the clock frequency. 298 * 299 * @param[in] clock The clock object to set the frequency for. 300 * @param[in] hz The frequency, in hertz, to set the clock to. 301 * @param[in] tolerance The allowed tolerance from the desired hz that is acceptable, use NULL if no 302 * tolerance check is required. 303 * @return The status of the request to set the clock frequency. 304 */ 305 cy_rslt_t cyhal_clock_set_frequency(cyhal_clock_t *clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance); 306 307 /** Attempts to update the divider, and by extension the operating frequency, of the clock. This is only 308 * legal to call if the \ref cyhal_clock_get_features API indicates support for 309 * \ref CYHAL_CLOCK_FEATURE_DIVIDER. 310 * 311 * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b> 312 * instance before using this function. 313 * 314 * @param[in] clock The clock object to set the divider for. 315 * @param[in] divider The divider value to use. 316 * @return The status of the request to set the clock divider. 317 */ 318 cy_rslt_t cyhal_clock_set_divider(cyhal_clock_t *clock, uint32_t divider); 319 320 /** Gets the clocks that can serve as inputs to the current clock. 321 * 322 * @param[in] clock The clock object to get legal sources for. 323 * @param[out] sources The sources that are legal for the current clock. 324 * \note the array does not need to be allocated before calling this 325 * the pointer will be updated to point to an existing const array. 326 * @param[out] count The number of clock sources contained in the <b>sources</b> variable. 327 * @return The status of the request to get clock sources. 328 */ 329 cy_rslt_t cyhal_clock_get_sources(const cyhal_clock_t *clock, const cyhal_resource_inst_t **sources[], uint32_t *count); 330 331 /** Attempts to update the source for the specified clock. This is only legal to call if the 332 * \ref cyhal_clock_get_features API indicates support for \ref CYHAL_CLOCK_FEATURE_SOURCE. 333 * 334 * \note \ref cyhal_clock_allocate or \ref cyhal_clock_reserve must be called on the <b>clock</b> 335 * instance before using this function. 336 * 337 * \note Some clocks (eg: FLLs & PLLs) may need to be stopped before their source can be changed. 338 * This function will take care of disabling & re-enabling as necessary, however, this can cause 339 * a temporary glitch on anything that is running off of the clock at the time. If glitch free 340 * operation is required, change the source for any downstream clocks in the application before 341 * changing the source clock. 342 * 343 * \note No checking is done to verify that the source clock is running. This needs to be done 344 * by the caller. 345 * 346 * @param[in] clock The clock object to set a new source for. 347 * @param[in] source The source clock to update to. 348 * @return The status of the request to set the source of the clock 349 */ 350 cy_rslt_t cyhal_clock_set_source(cyhal_clock_t *clock, const cyhal_clock_t *source); 351 352 /** Releases the exclusive lock the clock. This instance can no longer be used to with any set() 353 * functions. It can still be used for readonly access to Clock APIs just like is possible after 354 * calling \ref cyhal_clock_get. 355 * 356 * \note This does not change the behavior (e.g.: enablement) of the clock. 357 * 358 * @param[in,out] clock The clock object to free 359 */ 360 void cyhal_clock_free(cyhal_clock_t *clock); 361 362 #if defined(__cplusplus) 363 } 364 #endif 365 366 #ifdef CYHAL_CLOCK_IMPL_HEADER 367 #include CYHAL_CLOCK_IMPL_HEADER 368 #endif /* CYHAL_CLOCK_IMPL_HEADER */ 369 370 /** \} group_hal_clock */ 371