1 /***************************************************************************//**
2 * \file cyhal_utils.h
3 *
4 * \brief
5 * Provides utility functions.
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 /** \cond INTERNAL */
28 /**
29 * \addtogroup group_hal_impl
30 * \{
31 * Common utility macros & functions used by multiple HAL drivers.
32 */
33 
34 #pragma once
35 
36 #include "cy_result.h"
37 #include "cyhal_hw_types.h"
38 #include "cy_utils.h"
39 #if !defined(COMPONENT_CAT4)
40 #include "cyhal_utils_impl.h"
41 #endif
42 
43 #if defined(__cplusplus)
44 extern "C" {
45 #endif
46 
47 #define _CYHAL_UTILS_NS_PER_SECOND   (1000000000)
48 #define _CYHAL_UTILS_US_PER_MS       (1000)
49 #define _CYHAL_UTILS_ONE_TIME_UNIT   (1)     /**< Used to do a delay in one time unit (1 ms, 1 us) */
50 
51 #define _CYHAL_UTILS_IRQN_OFFSET           (16U) /**< Offset for implementation-defined ISR type numbers (IRQ0 = 16) */
52 #define _CYHAL_UTILS_GET_CURRENT_IRQN()    ((IRQn_Type) (__get_IPSR() - _CYHAL_UTILS_IRQN_OFFSET)) /**< Macro to get the IRQn of the current ISR */
53 
54 /** Assigns the specified resource with the provided type, block_num, and channel_num
55  */
56 #define _CYHAL_UTILS_ASSIGN_RESOURCE(rsc, resource_type, map) \
57       (rsc).type = (resource_type);                           \
58       (rsc).block_num = ((map)->block_num);                   \
59       (rsc).channel_num = ((map)->channel_num)
60 
61 /**
62 * \addtogroup group_hal_impl_pin_package
63 * \{
64 */
65 
66 /** Attempts to reserve a resource block that connects to the specified pin from the provided resource pin mapping table.
67   * If the first matching block cannot be reserved, this will continue searching until either a match is successfully
68   * reserved or the end of the table is reached.
69  * This is a convenience utility for _cyhal_utils_get_resource() if the mappings is an array of known size.
70   *
71   * @param[in] pin      The pin to which the reserved hardware block must connect
72   * @param[in] rsc      The type of hardware resource being allocated
73   * @param[in] mappings The mapping of pin to hardware block
74   * @return The entry for the specified pin corresponding to the reserved block, if it exists and was successfully reserved.
75             Otherwise, NULL.
76   */
77 #define _CYHAL_UTILS_TRY_ALLOC(pin, rsc, mappings) \
78     _cyhal_utils_try_alloc(pin, rsc, mappings, sizeof(mappings)/sizeof(cyhal_resource_pin_mapping_t))
79 
80 /** Looks up the resource block that connects to the specified pins from the provided resource pin mapping table.
81  * This is a convenience utility for _cyhal_utils_get_resource() if the mappings is an array of known size.
82  *
83  * @param[in] pin        The pin to lookup the hardware block for
84  * @param[in] mappings   The mappings of pin to hardware block
85  * @return The entry for the specified pin if it exists, or null if it doesn't.
86  */
87 #define _CYHAL_UTILS_GET_RESOURCE(pin, mappings) _cyhal_utils_get_resource(pin, mappings, sizeof(mappings)/sizeof(cyhal_resource_pin_mapping_t), NULL, false)
88 
89 /** Looks up the resource block that connects to the specified pins from the provided resource pin mapping table.
90  * This is a convenience utility for _cyhal_utils_get_resource() if the mappings is an array of known size.
91  *
92  * @param[in] pin        The pin to lookup the hardware block for
93  * @param[in] mappings   The mappings of pin to hardware block
94  * @param[in] block_res  If not NULL, find pin mapping, that belongs to specified block
95  * @return The entry for the specified pin if it exists, or null if it doesn't.
96  */
97 #define _CYHAL_UTILS_GET_RESOURCE_INST(pin, mappings, block_res) _cyhal_utils_get_resource(pin, mappings, sizeof(mappings)/sizeof(cyhal_resource_pin_mapping_t), (block_res), false)
98 
99 /** Looks up the resource block that connects to the specified pins from the provided resource pin mapping table.
100  *
101  * @param[in] pin        The pin to lookup the hardware block for
102  * @param[in] mappings   The mappings of pin to hardware block
103  * @param[in] count      The number of items in the mappings table
104  * @param[in] block_res  If not NULL, find pin mapping, that belongs to specified block
105  * @param[in] ignore_channel Ignore channel differences
106  * @return The entry for the specified pin if it exists, or null if it doesn't.
107  */
108 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, bool ignore_channel);
109 
110 /** Attempts to reserve a resource block that connects to the specified pin from the provided resource pin mapping table.
111   * If the first matching block cannot be reserved, this will continue searching until either a match is successfully
112   * reserved or the end of the table is reached.
113   *
114   * @param[in] pin      The pin to which the reserved hardware block must connect
115   * @param[in] rsc      The type of hardware resource being allocated
116   * @param[in] pin_map The mapping of pin to hardware block
117   * @param[in] size     The number of items in the mappings table
118   * @return The entry for the specified pin corresponding to the reserved block, if it exists and was successfully reserved.
119             Otherwise, NULL.
120   */
121 const cyhal_resource_pin_mapping_t* _cyhal_utils_try_alloc(cyhal_gpio_t pin, cyhal_resource_t rsc, const cyhal_resource_pin_mapping_t *pin_map, size_t count);
122 
123 /** Checks to see if the provided pin is a no-connect (CYHAL_NC_PIN_VALUE). If not, calls
124  * _cyhal_utils_disconnect_and_free().
125  *
126  * @param[in] pin       The pin to disconnect and free
127  */
128 void _cyhal_utils_release_if_used(cyhal_gpio_t *pin);
129 
130 /** Determine if the two resource instances reference the same item.
131  *
132  * @param[in] resource1 The first resource instance to compare
133  * @param[in] resource2 The second resource instance to compare
134  * @return Boolean indicating whether two resources are the same
135  */
_cyhal_utils_resources_equal(const cyhal_resource_inst_t * resource1,const cyhal_resource_inst_t * resource2)136 static inline bool _cyhal_utils_resources_equal(const cyhal_resource_inst_t *resource1, const cyhal_resource_inst_t *resource2)
137 {
138     return (resource1->type == resource2->type) && (resource1->block_num == resource2->block_num) && (resource1->channel_num == resource2->channel_num);
139 }
140 
141 /** Determine if the block and channel are the same for the provided resource instance and pin map instance.
142  *
143  * @param[in] resource The resource instance to compare
144  * @param[in] map The pin map instance to compare
145  * @param[in] ignore_channel Ignore channel differences
146  * @return Boolean indicating whether two resources are the same
147  */
_cyhal_utils_map_resource_equal(const cyhal_resource_inst_t * resource,const cyhal_resource_pin_mapping_t * map,bool ignore_channel)148 static inline bool _cyhal_utils_map_resource_equal(const cyhal_resource_inst_t *resource, const cyhal_resource_pin_mapping_t *map,
149     bool ignore_channel)
150 {
151     return (resource->block_num == map->block_num) && (ignore_channel || resource->channel_num == map->channel_num);
152 }
153 
154 /** Determine if two pin map resources are the same. If more than two instances need to be
155  * compared, it is better to call \ref _cyhal_utils_map_resources_equal_all().
156  *
157  * @param[in] map1 First pin map resource to compare
158  * @param[in] map2 Second pin map resource to compare
159  * @return Boolean indicating whether two resources are the same
160  */
_cyhal_utils_map_resources_equal(const cyhal_resource_pin_mapping_t * map1,const cyhal_resource_pin_mapping_t * map2)161 static inline bool _cyhal_utils_map_resources_equal(const cyhal_resource_pin_mapping_t *map1, const cyhal_resource_pin_mapping_t *map2)
162 {
163     return (map1->block_num == map2->block_num) && (map1->channel_num == map2->channel_num);
164 }
165 
166 /** Determine if the set of pin map resources are the same. This expects at least two resource
167  * instances to be provided. NOTE: If only two instances are provided it is better
168  * to use \ref _cyhal_utils_map_resources_equal().
169  *
170  * @param[in] count The number of resources being provided to compare
171  * @param[in] ...   Variable List of const cyhal_resource_inst_t* items to compare
172  * @return Boolean indicating whether resource instances are the same
173  */
174 bool _cyhal_utils_map_resources_equal_all(uint32_t count, ...);
175 
176 /** Converts a set of flags from one representation to a equivalent set of flags
177  * in another representation.
178  * For example usage see cyhal_syspm.c or cyhal_sdhc.c
179  *
180  * @param[in] map           New flag values. Each index corresponds to a bit position
181  *                          from the source_flags. Index 0 is a default value if nothing
182  *                          matches.
183  * @param[in] count         Count of the total flags in the list.
184  * @param[in] source_flags  Source flags to be converted.
185  * @return Converted flags.
186  */
187 uint32_t _cyhal_utils_convert_flags(const uint32_t map[], uint32_t count, uint32_t source_flags);
188 
189 #if defined(__cplusplus)
190 }
191 #endif
192 
193 /** \} group_hal_impl_utils */
194 /** \} group_hal_impl */
195 /** \endcond */
196