Hardware Abstraction Layer (HAL)

General Description

Interface for getting and changing clock configuration.

group_hal_syspm

The clock driver is a single API designed to allow reading and configuring any clock in the system. The driver works the same to configure System clocks as it does for Peripheral clocks. It supports both a readonly mode where any number of items can get information about the clock. Alternatively, each clock can have a single owner that is able to adjust the configuration of the clock.

This driver supports source clocks, clock dividers, and clock signal muxes. All clock objects support the get() functions. Only some clocks support setting specific attributes. Use the cyhal_clock_get_features() function to determine which features are settable for a specific clock. Calling a set() function on a clock that does not support it will return an error.

This driver makes no assumptions about how the device is currently configured. It can be used from a completely unconfigured system (eg: device just booted) to a fully pre-configured (eg: setup by the Device Configurator). The drivers query and modify the actual state of the hardware, there is no caching or remembering of state. To maximize portability of code, it is often convenient to place all system clock configuration into a Board Support Package (BSP) so the main application code is flexible and can port between devices.

cyhal_clock_get allows for getting access to a specific clock object. This clock reference can be used to call any of the get() functions at any time. If a clock needs to be modified, either cyhal_clock_allocate or cyhal_clock_init must be called to obtain a lock on the clock object and to ensure that nothing else in the application is currently using it or assuming its configuration is stable. If exclusive control of a clock is no longer needed cyhal_clock_free can be called to release it. This will remove the lock allowing something else in the system to potentially modify its state.

cyhal_clock_init and cyhal_clock_allocate are very similar. They both reserve a clock object that can then be modified. The difference between them is the argument that is passed in. cyhal_clock_init takes a specific instance that it will attemt to reserve. cyhal_clock_allocate takes in a type of clock that it will attempt to find a free instance for and reserve that.

Note
After calling cyhal_clock_free the clock object can still be used to call any of the get() functions just as is possible from the instance returned by cyhal_clock_get.
A clock only needs to be allocated ( cyhal_clock_allocate ) or initialized ( cyhal_clock_init ) if its configuration needs to be changed by calling one of the set() functions.
While the API is generic, the specific clock resource instances (cyhal_resource_inst_t) are device specific. See the implementation specific sections for more details on what clocks and hardware resources are available.

Features

Quick Start

See Snippet 1: Simple clock read only access for a code snippet that shows how to reserve and configure a clock object.

Code snippets

Note
Error handling code has been intentionally left out of snippets to highlight API usage.

Snippet 1: Simple clock read only access

The following snippet shows how get details about a clock if there is no need to adjust any of its settings (e.g. read only access). This does not require initializing a clock object.

uint32_t freq;
bool enabled = cyhal_clock_is_enabled(&clock);
if (enabled)
{
freq = cyhal_clock_get_frequency(&clock);
/* Use frequency information for something */
}

Snippet 2: Simple clock reservation and configuration

The following snippet initializes a clock object, updates its frequency then enables it.

cy_rslt_t rslt;
cyhal_clock_t clock_obj;
rslt = cyhal_clock_get(&clock_obj, &CYHAL_CLOCK_IMO);
/* Initialize, take ownership of, the specified clock instance */
rslt = cyhal_clock_init(&clock_obj);
/* Set the clock frequency to 1MHz, no tolerance restriction */
rslt = cyhal_clock_set_frequency(&clock_obj, 1000000, NULL);
/* If the clock is not already enabled, enable it */
if (!cyhal_clock_is_enabled(&clock_obj))
{
rslt = cyhal_clock_set_enabled(&clock_obj, true, true);
}
/* If no longer need to directly control the clock, it can be freed */
cyhal_clock_free(&clock_obj);

Snippet 3: Clock allocation and reuse

The following snippet shows how a clock can be allocated and reused for multiple peripheral instances.

cy_rslt_t rslt;
cyhal_clock_t clock_obj;
/* Set the clock frequency to 1MHz, no tolerance restriction */
rslt = cyhal_clock_set_frequency(&clock_obj, 1000000, NULL);
/* If the clock is not already enabled, enable it */
if (!cyhal_clock_is_enabled(&clock_obj))
{
rslt = cyhal_clock_set_enabled(&clock_obj, true, true);
}
cyhal_peripheral1_t my_peripheral1;
cyhal_peripheral2_t my_peripheral2;
rslt = cyhal_peripheral1_init(&my_peripheral1, &clock_obj);
rslt = cyhal_peripheral2_init(&my_peripheral2, &clock_obj);

Snippet 4: Change clock source

The following snippet shows how a to change the source of a clock.

cy_rslt_t rslt;
cyhal_clock_t clock_pll, clock_hf;
#if defined(COMPONENT_PSOC6)
rslt = cyhal_clock_get(&clock_hf, &CYHAL_CLOCK_HF[1]);
#else
rslt = cyhal_clock_get(&clock_hf, &CYHAL_CLOCK_HF);
#endif
/* Initialize, take ownership of, the specified clock instance */
rslt = cyhal_clock_init(&clock_hf);
/* Allocate a generic PLL instance */
/* Set the clock frequency to 90.316MHz (44.1, 32-bit sample) */
rslt = cyhal_clock_set_frequency(&clock_pll, 90316000, NULL);
/* If the clock is not already enabled, enable it */
if (!cyhal_clock_is_enabled(&clock_pll))
{
rslt = cyhal_clock_set_enabled(&clock_pll, true, true);
}
/* Change the source for the High Frequency clock to be the allocated PLL */
rslt = cyhal_clock_set_source(&clock_hf, &clock_pll);

Snippet 5: System initialization

Note
This example is device specific. See Snippet: System initialization for specific implementation.

API Reference

 Clock HAL Results
 Clock specific return codes.
 
 Group_hal_tolerance
 

Data Structures

struct  cyhal_clock_tolerance_t
 Structure defining a clock tolerance. More...
 

Enumerations

enum  cyhal_clock_feature_t {
  CYHAL_CLOCK_FEATURE_NONE = (0),
  CYHAL_CLOCK_FEATURE_ENABLE = (1 << 0),
  CYHAL_CLOCK_FEATURE_FREQUENCY = (1 << 1),
  CYHAL_CLOCK_FEATURE_DIVIDER = (1 << 2),
  CYHAL_CLOCK_FEATURE_SOURCE = (1 << 4)
}
 Enum defining the different features each clock can support of clocks. More...
 
enum  cyhal_clock_tolerance_unit_t {
  CYHAL_TOLERANCE_HZ,
  CYHAL_TOLERANCE_PPM,
  CYHAL_TOLERANCE_PERCENT
}
 Enum defining the different ways of specifying the acceptable clock tolerance. More...
 

Functions

cy_rslt_t cyhal_clock_allocate (cyhal_clock_t *clock, cyhal_clock_block_t block)
 Allocates and Initializes a Clock instance, of the provided block type, for use. More...
 
cy_rslt_t cyhal_clock_get (cyhal_clock_t *clock, const cyhal_resource_inst_t *resource)
 Get a Clock instance for readonly use. More...
 
cy_rslt_t cyhal_clock_init (cyhal_clock_t *clock)
 Initialize a Clock instance for read/write use. More...
 
cyhal_clock_feature_t cyhal_clock_get_features (const cyhal_clock_t *clock)
 Gets the features supported by the specified clock. More...
 
bool cyhal_clock_is_enabled (const cyhal_clock_t *clock)
 Gets whether the specified clock is currently enabled and locked, if appropriate. More...
 
cy_rslt_t cyhal_clock_set_enabled (cyhal_clock_t *clock, bool enabled, bool wait_for_lock)
 Attempts to update the enablement of the specified clock. More...
 
uint32_t cyhal_clock_get_frequency (const cyhal_clock_t *clock)
 Gets the frequency (in Hz) the clock is currently operating at. More...
 
cy_rslt_t cyhal_clock_set_frequency (cyhal_clock_t *clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance)
 Attempts to update the operating frequency of the clock. More...
 
cy_rslt_t cyhal_clock_set_divider (cyhal_clock_t *clock, uint32_t divider)
 Attempts to update the divider, and by extension the operating frequency, of the clock. More...
 
cy_rslt_t cyhal_clock_get_sources (const cyhal_clock_t *clock, const cyhal_resource_inst_t **sources[], uint32_t *count)
 Gets the clocks that can serve as inputs to the current clock. More...
 
cy_rslt_t cyhal_clock_set_source (cyhal_clock_t *clock, const cyhal_clock_t *source)
 Attempts to update the source for the specified clock. More...
 
void cyhal_clock_free (cyhal_clock_t *clock)
 Releases the exclusive lock the clock. More...
 

Data Structure Documentation

◆ cyhal_clock_tolerance_t

struct cyhal_clock_tolerance_t
Data Fields
cyhal_clock_tolerance_unit_t type The type of the clock tolerance value.
uint32_t value The tolerance value to use.

Enumeration Type Documentation

◆ cyhal_clock_feature_t

Enum defining the different features each clock can support of clocks.

These are bit masks. These can be used to determine which set() APIs are legal for a particular clock.

Enumerator
CYHAL_CLOCK_FEATURE_NONE 

No features of the clock are configurable.

CYHAL_CLOCK_FEATURE_ENABLE 

The clock can be enabled & disabled cyhal_clock_set_enabled.

CYHAL_CLOCK_FEATURE_FREQUENCY 

The clock frequency can be adjusted cyhal_clock_set_frequency.

CYHAL_CLOCK_FEATURE_DIVIDER 

The clock divider can be adjusted cyhal_clock_set_divider.

CYHAL_CLOCK_FEATURE_SOURCE 

The clock source can be adjusted cyhal_clock_set_source.

◆ cyhal_clock_tolerance_unit_t

Enum defining the different ways of specifying the acceptable clock tolerance.

Enumerator
CYHAL_TOLERANCE_HZ 

Clock tolerance specified directly in Hertz.

CYHAL_TOLERANCE_PPM 

Clock tolerance specified in parts-per-million.

CYHAL_TOLERANCE_PERCENT 

Clock tolerance specified in a percent.

Function Documentation

◆ cyhal_clock_allocate()

cy_rslt_t cyhal_clock_allocate ( cyhal_clock_t clock,
cyhal_clock_block_t  block 
)

Allocates and Initializes a Clock instance, of the provided block type, for use.

This should be used when needing a specific type of clock but the exact instance does not matter. This does everything that is done by cyhal_clock_get and cyhal_clock_init. Once the clock has been allocated the get() and set() functions can be used. If at any time the clock is no longer needed, it can be released by calling cyhal_clock_free.

Note
This does not change the clock configuration or connections.
Parameters
[out]clockThe clock object to initialize. The caller must allocate the memory for this object but the init function will initialize its contents.
[in]blockThe specific type of clock to allocate
Returns
The status of the allocate request.

◆ cyhal_clock_get()

cy_rslt_t cyhal_clock_get ( cyhal_clock_t clock,
const cyhal_resource_inst_t resource 
)

Get a Clock instance for readonly use.

This clock object can be used to call any of the get() functions. To call any of the set() functions, cyhal_clock_init must be called to get exclusive access to the clock object to allow it to be modified.

Parameters
[out]clockThe clock object to store the initialized data into. The caller must allocate the memory for this object but the init function will initialize its contents.
[in]resourceThe clock resource instance to initialize.
Returns
The status of the get request. This will only return an error if the provided resource instance is not a valid clock object.

◆ cyhal_clock_init()

cy_rslt_t cyhal_clock_init ( cyhal_clock_t clock)

Initialize a Clock instance for read/write use.

This instance should be what was returned from cyhal_clock_get.

Note
This does not change the behavior (e.g.: enablement) of the clock.
Parameters
[in,out]clockThe clock object to store the initialized data into.
Returns
The status of the init request.

◆ cyhal_clock_get_features()

cyhal_clock_feature_t cyhal_clock_get_features ( const cyhal_clock_t clock)

Gets the features supported by the specified clock.

This can be used to determine which set() APIs are legal to be called for this clock.

Parameters
[in]clockThe clock object to get features for.
Returns
The feature set that can be configured by this clock. Features are bit mask values.

◆ cyhal_clock_is_enabled()

bool cyhal_clock_is_enabled ( const cyhal_clock_t clock)

Gets whether the specified clock is currently enabled and locked, if appropriate.

While most clocks simply have an enabled state, Crystals, PLL, and a few others may also check to make sure the clock has locked and is stable before returning true.

Note
External clocks which cannot be enabled/disabled directly will return true if a frequency has been set for them, and false otherwise
Parameters
[in]clockThe clock object to check if it is enabled.
Returns
Whether the specified clock is enabled or not.

◆ cyhal_clock_set_enabled()

cy_rslt_t cyhal_clock_set_enabled ( cyhal_clock_t clock,
bool  enabled,
bool  wait_for_lock 
)

Attempts to update the enablement of the specified clock.

This is only legal to call if the cyhal_clock_get_features API indicates support for CYHAL_CLOCK_FEATURE_ENABLE.

Note
cyhal_clock_allocate or cyhal_clock_init must be called on the clock instace before using this function.
If disabled, any clocks or peripherals that are using this will stop working. Make sure to switch the clock source (cyhal_clock_set_source) of any downstream clocks if necessary to keep them running prior to disabling their source.
Parameters
[in]clockThe clock object to update the enablement of.
[in]enabledWhether the clock should be enabled (true) or disabled (false).
[in]wait_for_lockWhether to wait for the clock to enable & lock (true), or just send the request and return (false). Most clocks behave the same either way, however Crystals, PLLs, and similar require time to lock. If false, cyhal_clock_is_enabled needs to be used to check that it is running before using the clock.
Returns
The status of the requested to change the clocks enablement.

◆ cyhal_clock_get_frequency()

uint32_t cyhal_clock_get_frequency ( const cyhal_clock_t clock)

Gets the frequency (in Hz) the clock is currently operating at.

Parameters
[in]clockThe clock object to get the frequency of.
Returns
The frequency the clock is currently running at. 0 if the clock is disabled.

◆ cyhal_clock_set_frequency()

cy_rslt_t cyhal_clock_set_frequency ( cyhal_clock_t clock,
uint32_t  hz,
const cyhal_clock_tolerance_t tolerance 
)

Attempts to update the operating frequency of the clock.

This is only legal to call if the cyhal_clock_get_features API indicates support for CYHAL_CLOCK_FEATURE_FREQUENCY.

Note
cyhal_clock_allocate or cyhal_clock_init must be called on the clock instace before using this function.
Some clocks (eg: FLLs & PLLs) may need to be stopped before their frequency can be changed. This function will take care of disabling & re-enabling as necessary, however, this can cause a temporary glitch on anything that is running off of the clock at the time. If glitch free operation is required, change the source of any downstream clocks the application before changing the clock frequency.
Parameters
[in]clockThe clock object to set the frequency for.
[in]hzThe frequency, in hertz, to set the clock to.
[in]toleranceThe allowed tolerance from the desired hz that is acceptable, use NULL if no tolerance check is required.
Returns
The status of the request to set the clock frequency.

◆ cyhal_clock_set_divider()

cy_rslt_t cyhal_clock_set_divider ( cyhal_clock_t clock,
uint32_t  divider 
)

Attempts to update the divider, and by extension the operating frequency, of the clock.

This is only legal to call if the cyhal_clock_get_features API indicates support for CYHAL_CLOCK_FEATURE_DIVIDER.

Note
cyhal_clock_allocate or cyhal_clock_init must be called on the clock instace before using this function.
Parameters
[in]clockThe clock object to set the divider for.
[in]dividerThe divider value to use.
Returns
The status of the request to set the clock divider.

◆ cyhal_clock_get_sources()

cy_rslt_t cyhal_clock_get_sources ( const cyhal_clock_t clock,
const cyhal_resource_inst_t **  sources[],
uint32_t *  count 
)

Gets the clocks that can serve as inputs to the current clock.

Parameters
[in]clockThe clock object to get legal sources for.
[out]sourcesThe sources that are legal for the current clock.
Note
the array does not need to be allocated before calling this the pointer will be updated to point to an existing const array.
Parameters
[out]countThe number of clock sources contained in the sources variable.
Returns
The status of the request to get clock sources.

◆ cyhal_clock_set_source()

cy_rslt_t cyhal_clock_set_source ( cyhal_clock_t clock,
const cyhal_clock_t source 
)

Attempts to update the source for the specified clock.

This is only legal to call if the cyhal_clock_get_features API indicates support for CYHAL_CLOCK_FEATURE_SOURCE.

Note
cyhal_clock_allocate or cyhal_clock_init must be called on the clock instace before using this function.
Some clocks (eg: FLLs & PLLs) may need to be stopped before their source can be changed. This function will take care of disabling & re-enabling as necessary, however, this can cause a temporary glitch on anything that is running off of the clock at the time. If glitch free operation is required, change the source for any downstream clocks in the application before changing the source clock.
No checking is done to verify that the source clock is running. This needs to be done by the caller.
Parameters
[in]clockThe clock object to set a new source for.
[in]sourceThe source clock to update to.
Returns
The status of the request to set the source of the clock

◆ cyhal_clock_free()

void cyhal_clock_free ( cyhal_clock_t clock)

Releases the exclusive lock the clock.

This instance can no longer be used to with any set() functions. It can still be used for readonly access to Clock APIs just like is possible after calling cyhal_clock_get.

Note
This does not change the behavior (e.g.: enablement) of the clock.
Parameters
[in,out]clockThe clock object to free