Files
mbed-os/targets/TARGET_Cypress/TARGET_PSOC6/mtb-hal-cat1/include/cyhal_utils.h
Beslan 0ef1717155
Some checks failed
Basic Checks / license-check (push) Has been cancelled
Basic Checks / include-check (push) Has been cancelled
Basic Checks / style-check (push) Has been cancelled
Basic Checks / docs-check (push) Has been cancelled
Basic Checks / python-tests (push) Has been cancelled
Basic Checks / pin-validation (push) Has been cancelled
Basic Checks / cmake-checks (push) Has been cancelled
Basic Checks / frozen-tools-check (push) Has been cancelled
Publish or Update docker image for head of branch / prepare-tags (push) Has been cancelled
Release or update docker image for a released mbed-os version / prepare-tags (push) Has been cancelled
Publish or Update docker image for head of branch / build-container (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/amd64) (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/arm64) (push) Has been cancelled
Publish or Update docker image for head of branch / deploy-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / build-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/amd64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/arm64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / deploy-container (push) Has been cancelled
Prune temporary docker images / prune-images (push) Has been cancelled
Mirror mbed-os-6.15.0
2026-07-10 18:42:39 +03:00

339 lines
16 KiB
C

/***************************************************************************//**
* \file cyhal_utils.h
*
* \brief
* Provides utility functions for working with the CAT1/CAT2 HAL implementation.
*
********************************************************************************
* \copyright
* Copyright 2018-2021 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
/** \cond INTERNAL */
/**
* \addtogroup group_hal_impl
* \{
* Common utility macros & functions used by multiple HAL drivers.
*/
#pragma once
#include "cy_result.h"
#include "cyhal_hw_types.h"
#include "cy_utils.h"
#if defined(__cplusplus)
extern "C" {
#endif
#define _CYHAL_UTILS_NS_PER_SECOND (1000000000)
#define _CYHAL_UTILS_IRQN_OFFSET (16U) /**< Offset for implementation-defined ISR type numbers (IRQ0 = 16) */
#define _CYHAL_UTILS_GET_CURRENT_IRQN() ((IRQn_Type) (__get_IPSR() - _CYHAL_UTILS_IRQN_OFFSET)) /**< Macro to get the IRQn of the current ISR */
/**
* \addtogroup group_hal_impl_pin_package
* \{
*/
/** Attempts to reserve a resource block that connects to the specified pin from the provided resource pin mapping table.
* If the first matching block cannot be reserved, this will continue searching until either a match is successfully
* reserved or the end of the table is reached.
* This is a convenience utility for _cyhal_utils_get_resource() if the mappings is an array of known size.
*
* @param[in] pin The pin to which the reserved hardware block must connect
* @param[in] mappings The mapping of pin to hardware block
* @return The entry for the specified pin corresponding to the reserved block, if it exists and was successfully reserved.
Otherwise, NULL.
*/
#define _CYHAL_UTILS_TRY_ALLOC(pin, mappings) \
_cyhal_utils_try_alloc(pin, mappings, sizeof(mappings)/sizeof(cyhal_resource_pin_mapping_t))
/** Looks up the resource block that connects to the specified pins from the provided resource pin mapping table.
* This is a convenience utility for _cyhal_utils_get_resource() if the mappings is an array of known size.
*
* @param[in] pin The pin to lookup the hardware block for
* @param[in] mappings The mappings of pin to hardware block
* @return The entry for the specified pin if it exists, or null if it doesn't.
*/
#define _CYHAL_UTILS_GET_RESOURCE(pin, mappings) _cyhal_utils_get_resource(pin, mappings, sizeof(mappings)/sizeof(cyhal_resource_pin_mapping_t), NULL)
/** Converts the provided gpio pin to a resource instance object
*
* @param[in] pin The pin to get a resource object for
* @return The equivalent resource instance object for the provided pin.
*/
static inline cyhal_resource_inst_t _cyhal_utils_get_gpio_resource(cyhal_gpio_t pin)
{
cyhal_resource_inst_t rsc = { CYHAL_RSC_GPIO, CYHAL_GET_PORT(pin), CYHAL_GET_PIN(pin) };
return rsc;
}
/** Looks up the resource block that connects to the specified pins from the provided resource pin mapping table.
*
* @param[in] pin The pin to lookup the hardware block for
* @param[in] mappings The mappings of pin to hardware block
* @param[in] count The number of items in the mappings table
* @param[in] block_res If not NULL, find pin mapping, that belongs to specified block
* @return The entry for the specified pin if it exists, or null if it doesn't.
*/
const cyhal_resource_pin_mapping_t *_cyhal_utils_get_resource(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t* mappings, size_t count, const cyhal_resource_inst_t* block_res);
/** Attempts to reserve a resource block that connects to the specified pin from the provided resource pin mapping table.
* If the first matching block cannot be reserved, this will continue searching until either a match is successfully
* reserved or the end of the table is reached.
*
* @param[in] pin The pin to which the reserved hardware block must connect
* @param[in] mappings The mapping of pin to hardware block
* @param[in] size The number of items in the mappings table
* @return The entry for the specified pin corresponding to the reserved block, if it exists and was successfully reserved.
Otherwise, NULL.
*/
const cyhal_resource_pin_mapping_t* _cyhal_utils_try_alloc(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *mappings, size_t count);
/** Attempts to reserve the specified pin and then initialize it to connect to the item defined by the provided mapping object.
* @param[in] pin The pin to reserve and connect
* @param[in] mapping The pin/hardware block connection mapping information
* @return CY_RSLT_SUCCESS if everything was ok, else an error.
*/
cy_rslt_t _cyhal_utils_reserve_and_connect(cyhal_gpio_t pin, const cyhal_resource_pin_mapping_t *mapping);
/** Disconnects any routing for the pin from the interconnect driver and then free's the pin from the hwmgr.
*
* @param[in] pin The pin to disconnect and free
*/
void _cyhal_utils_disconnect_and_free(cyhal_gpio_t pin);
/** Checks to see if the provided pin is a no-connect (CYHAL_NC_PIN_VALUE). If not, calls
* _cyhal_utils_disconnect_and_free().
*
* @param[in] pin The pin to disconnect and free
*/
void _cyhal_utils_release_if_used(cyhal_gpio_t *pin);
/** \} group_hal_impl_pin_package */
/** Calculate a peripheral clock divider value that needs to be set to reach the frequency closest
* to the one requested.
* \note The caller may need to subtract one from the value returned in order to align with the
* API/register requirements. This is necessary if the API/register expects a value of 0 to mean
* divide by 1.
*
* @param[in] frequency The desired frequency
* @param[in] frac_bits The number of fractional bits that the divider has
* @return The calculated divider value
*/
static inline uint32_t _cyhal_utils_divider_value(uint32_t frequency, uint32_t frac_bits)
{
#if defined(COMPONENT_CAT1A)
return ((Cy_SysClk_ClkPeriGetFrequency() * (1 << frac_bits)) + (frequency / 2)) / frequency;
#elif defined(COMPONENT_CAT2)
return ((Cy_SysClk_ClkSysGetFrequency() * (1 << frac_bits)) + (frequency / 2)) / frequency;
#endif
}
/** Determine if two resources are the same. If more than two instances need to be
* compared, it is better to call \ref _cyhal_utils_resources_equal_all().
*
* @param[in] resource1 First resource to compare
* @param[in] resource2 Second resource to compare
* @return Boolean indicating whether two resources are the same
*/
bool _cyhal_utils_resources_equal(const cyhal_resource_inst_t *resource1, const cyhal_resource_inst_t *resource2);
/** Determine if the set of resources are the same. This expects at least two resource
* instances to be provided. NOTE: If only two instances are provided it is better
* to use \ref _cyhal_utils_resources_equal().
*
* @param[in] count The number of resources being provided to compare
* @param[in] ... Variable List of const cyhal_resource_inst_t* items to compare
* @return Boolean indicating whether resource instances are the same
*/
bool _cyhal_utils_resources_equal_all(uint32_t count, ...);
/** Converts a set of flags from one representation to a equivalent set of flags
* in another representation.
* For example usage see cyhal_syspm.c or cyhal_sdhc.c
*
* @param[in] map New flag values. Each index corresponds to a bit position
* from the source_flags. Index 0 is a default value if nothing
* matches.
* @param[in] count Count of the total flags in the list.
* @param[in] source_flags Source flags to be converted.
* @return Converted flags.
*/
uint32_t _cyhal_utils_convert_flags(const uint32_t map[], uint32_t count, uint32_t source_flags);
/** Converts a hal pm mode to a pdl mode
*
* @param[in] mode hal power management callback mode.
* @return Equivalent pdl syspm mode.
*/
cy_en_syspm_callback_mode_t _cyhal_utils_convert_haltopdl_pm_mode(cyhal_syspm_callback_mode_t mode);
/** Converts a pdl pm mode to a hal mode
*
* @param[in] mode pdl syspm power management callback mode.
* @return Equivalent hal pm callback mode.
*/
cyhal_syspm_callback_mode_t _cyhal_utils_convert_pdltohal_pm_mode(cy_en_syspm_callback_mode_t mode);
/**
* Utility method to check if the clock is using the new data format (true) or the old
* format (false).
* @param[out] clock The clock instance to check which format it is using.
* @return Indication of whether the provided clock is using the new format (true) or old (false)
*/
static inline bool _cyhal_utils_is_new_clock_format(const cyhal_clock_t *clock)
{
#if defined(COMPONENT_CAT1A)
return (((cyhal_clock_block_t)clock->div_type == clock->block) && (clock->div_num == clock->channel));
#else
CY_UNUSED_PARAMETER(clock);
return true;
#endif
}
/**
* Utility method to update clock format to new format if the clock is using the old data format.
*
* @param[out] clock The clock instance to check which format it is using.
*/
static inline void _cyhal_utils_update_clock_format(cyhal_clock_t *clock)
{
#if defined(COMPONENT_CAT1A)
if(((cyhal_clock_block_t)clock->div_type != clock->block) || (clock->div_num != clock->channel))
{
clock->block = (cyhal_clock_block_t)clock->div_type;
clock->channel = clock->div_num;
}
#else
CY_UNUSED_PARAMETER(clock);
#endif
}
/** Gets the peripheral divider information from a provided clock instance. The clock can be using either
* the new or the old format for clocks.
*
* @param[in] clock The clock to get peripheral divider information from
* @param[out] div_type The divider type the clock instance represents
* @param[out] div_num The divider number the clock instance represents
*/
void _cyhal_utils_get_peri_clock_details(const cyhal_clock_t *clock, cy_en_divider_types_t *div_type, uint32_t *div_num);
/**
* Calculates clock tolerance in the specified units given a desired and actual frequency
*
* @param[in] type tolerance type
* @param[in] desired_hz desired clock frequency in hertz
* @param[in] actual_hz actual clock frequency in hertz
* @return the computed tolerance
*/
int32_t _cyhal_utils_calculate_tolerance(cyhal_clock_tolerance_unit_t type, uint32_t desired_hz, uint32_t actual_hz);
/**
* Allocates a clock that can drive the specified instance.
*
* @param[out] clock The clock object to initialize
* @param[in] clocked_item The destination that the allocated clock must be able to drive
* @param[in] div The divider width that is required. This is ignored if the block is hard-wired to
* an HFCLK output
* @param[in] accept_larger If no dividers of the specified width are available, can a wider divider be
* substituted.
*/
cy_rslt_t _cyhal_utils_allocate_clock(cyhal_clock_t *clock, const cyhal_resource_inst_t *clocked_item,
cyhal_clock_block_t div, bool accept_larger);
#if defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B)
/** Function for finding most suitable divider for provided clock */
typedef cy_rslt_t (*_cyhal_utils_clk_div_func_t)(uint32_t hz_src, uint32_t desired_hz,
const cyhal_clock_tolerance_t *tolerance, bool only_below_desired, uint32_t *div);
/**
* Finds best divider for HF clock according to source and desired frequency data
*
* @param[in] hz_src clock source frequency in hertz
* @param[in] desired_hz desired clock frequency in hertz
* @param[in] tolerance desired clock tolerance to achieve. If NULL provided, all possible dividers will
* be checked and selected most suitable.
* @param[in] only_below_desired resulting clock frequencies, that are above desired_hz will be skipped
* @param[out] div resulting divider
* @return CYHAL_CLOCK_RSLT_ERR_FREQ if divider is not found, CY_RSLT_SUCCESS in other situations
*/
cy_rslt_t _cyhal_utils_find_hf_clk_div(uint32_t hz_src, uint32_t desired_hz, const cyhal_clock_tolerance_t *tolerance,
bool only_below_desired, uint32_t *div);
/**
* Attempts to set the clock to the specified frequency. This is similar to cyhal_clock_set_frequency,
* but it will also make an attempt to set the frequency for HFCLK outputs, which are not supported by the public
* API due to their limited range of supported dividers (1, 2, 4, 8)
*
* @param[in] clock The clock instance to set the frequency for.
* @param[in] hz The frequency, in hertz, to set the clock to.
* @param[in] tolerance The allowed tolerance from the desired hz that is acceptable, use NULL if no
* tolerance check is required.
*/
cy_rslt_t _cyhal_utils_set_clock_frequency(cyhal_clock_t* clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance);
/**
* Finds for provided HF clock most suitable source to achieve target clock frequency and returns it with
* corresponding divider value. No clock configuration changed in this function.
*
* @param[in] clock The HFCLK clock instance that needs clock configuration.
* @param[in] hz The maximum frequency, in hertz, that needs to be achieved. The clock will not exceed
* this value.
* @param[in] tolerance The allowed tolerance below the desired hz that is acceptable, use NULL if no
* tolerance check is required.
* @param[in] div_find_func Pointer to _cyhal_utils_clk_div_func_t - type function, that will find most suitable
* divider for provided clock.
* @param[out] hf_source Resulting HF source clock, switching to which, in combination with resulting divider,
* will provide frequency closest to desired.
* @param[out] div Resulting divider for resulting HF source clock.
*/
cy_rslt_t _cyhal_utils_find_hf_source_n_divider(cyhal_clock_t *clock, uint32_t hz,
const cyhal_clock_tolerance_t *tolerance, _cyhal_utils_clk_div_func_t div_find_func,
cyhal_clock_t *hf_source, uint32_t *div);
/**
* Attempts to set the clock to the specified frequency. This is similar to cyhal_clock_set_frequency, but it will also
* make an attempt to set the frequency for HFCLK outputs. This is an enhancement beyond _cyhal_utils_set_clock_frequency
* as this will also attemt to adjust the source clock as well as change the divider.
*
* @param[in] clock The HFCLK clock instance to set the frequency for.
* @param[in] hz The maximum frequency, in hertz, to set the clock to. The clock will not exceed this
* value.
* @param[in] tolerance The allowed tolerance below the desired hz that is acceptable, use NULL if no
* tolerance check is required.
*/
cy_rslt_t _cyhal_utils_set_clock_frequency2(cyhal_clock_t *clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance);
/* Compatibility macros until other environments are updated to not use this anymore. */
#define CY_UTILS_GET_RESOURCE(pin, mappings) _CYHAL_UTILS_GET_RESOURCE(pin, mappings)
#define cyhal_utils_get_resource(pin, mappings, count) _cyhal_utils_get_resource(pin, mappings, count, NULL)
#define cyhal_utils_get_gpio_resource(pin) _cyhal_utils_get_gpio_resource(pin)
#define CYHAL_SCB_BASE_ADDRESSES _CYHAL_SCB_BASE_ADDRESSES
#define CYHAL_TCPWM_DATA _CYHAL_TCPWM_DATA
#endif /* defined(COMPONENT_CAT1A) || defined(COMPONENT_CAT1B) */
#if defined(__cplusplus)
}
#endif
/** \} group_hal_impl_utils */
/** \} group_hal_impl */
/** \endcond */