1 /***************************************************************************//** 2 * \file cyhal_tcpwm_common.h 3 * 4 * \brief 5 * Code shared between the Infineon Timer/Counter and PWM. 6 * 7 ******************************************************************************** 8 * \copyright 9 * Copyright 2019-2021 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_tcpwm_common TCPWM Common Functionality 30 * \ingroup group_hal_impl 31 * \{ 32 * Code shared between the Infineon Timer / Counter and PWM. 33 */ 34 35 #pragma once 36 37 #include <stdint.h> 38 #include <stdbool.h> 39 #include "cyhal_hw_types.h" 40 #include "cyhal_interconnect.h" 41 42 #if defined(__cplusplus) 43 extern "C" { 44 #endif /* __cplusplus */ 45 46 // Value comes from IP limitation 47 #define _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK (4u) 48 49 #if defined(CY_IP_MXTCPWM_INSTANCES) || defined(CY_IP_M0S8TCPWM_INSTANCES) 50 51 #if defined(CY_IP_MXTCPWM_INSTANCES) 52 #if (CY_IP_MXTCPWM_VERSION == 1) 53 // Total number of TCPWM groups 54 #define _CYHAL_TCPWM_INSTANCES CY_IP_MXTCPWM_INSTANCES 55 // Counter number relative to the start of the IP block 56 #define _CYHAL_TCPWM_CNT_NUMBER(resource) ((resource).channel_num) 57 // Cobvert driver 'block' to IP block 58 #define _CYHAL_TCPWM_GET_IP_BLOCK(block) (block) 59 #else // (CY_IP_MXTCPWM_VERSION >= 2) 60 #define _CYHAL_TCPWM_GET_IP_BLOCK(block) ((block) / _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK) 61 // Used to grab the group index relative to its IP block 62 #define _CYHAL_TCPWM_GET_GRP(block) ((block) % _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK) 63 #if (CY_IP_MXTCPWM_INSTANCES == 1) 64 #define _CYHAL_TCPWM_INSTANCES TCPWM_GRP_NR 65 #define _CYHAL_TCPWM_CNT_NUMBER(resource) (((resource).block_num << 8) | (resource).channel_num) 66 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 67 #define _CYHAL_TCPWM_INSTANCES (TCPWM0_GRP_NR + TCPWM1_GRP_NR) 68 // This is based on the model of 4x continuous groups mapping to x IP blocks (0-3 to 1, 4-7 to 2, etc) 69 #define _CYHAL_TCPWM_CNT_NUMBER(resource) ((((resource).block_num % _CYHAL_TCPWM_MAX_GRPS_PER_IP_BLOCK) << 8) | (resource).channel_num) 70 #else 71 #warning Unhandled TCPWM instance count 72 #endif 73 #endif 74 #elif defined(CY_IP_M0S8TCPWM_INSTANCES) 75 #define _CYHAL_TCPWM_CNT_NUMBER(resource) ((resource).channel_num) 76 #define _CYHAL_TCPWM_INSTANCES CY_IP_M0S8TCPWM_INSTANCES 77 #define _CYHAL_TCPWM_GET_IP_BLOCK(block) (block) 78 #endif 79 80 // Used to adjust block value for indexing _CYHAL_TCPWM_DATA[] and other arrays which do not include indexes for empty blocks 81 #if (CY_IP_MXTCPWM_VERSION == 2) 82 #if (CY_IP_MXTCPWM_INSTANCES == 1) 83 #define _CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block) (block) 84 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 85 #define _CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block) ((_CYHAL_TCPWM_GET_IP_BLOCK(block) == 0) ? (block) : (_CYHAL_TCPWM_GET_GRP(block) + TCPWM0_GRP_NR)) 86 #else 87 #warning Unhandled TCPWM instance count 88 #endif 89 #else 90 #define _CYHAL_TCPWM_ADJUST_BLOCK_INDEX(block) (block) 91 #endif 92 93 #if defined(CY_IP_MXTCPWM_INSTANCES) 94 #if (CY_IP_MXTCPWM_VERSION == 1) 95 #if (CY_IP_MXTCPWM_INSTANCES == 0) 96 #define _CYHAL_TCPWM_CHANNELS (0u) 97 #elif (CY_IP_MXTCPWM_INSTANCES == 1) 98 #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR) 99 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 100 #define _CYHAL_TCPWM_CHANNELS (TCPWM0_CNT_NR + TCPWM1_CNT_NR) 101 #else 102 #warning Unhandled TCPWM instance count 103 #endif 104 #else // (CY_IP_MXTCPWM_VERSION >= 2) 105 #if (CY_IP_MXTCPWM_INSTANCES == 1) 106 #if (TCPWM_GRP_NR == 0) 107 #define _CYHAL_TCPWM_CHANNELS (0U) 108 #elif (TCPWM_GRP_NR == 1) 109 #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR) 110 #elif (TCPWM_GRP_NR == 2) 111 #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR) 112 #elif (TCPWM_GRP_NR == 3) 113 #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR) 114 #elif (TCPWM_GRP_NR == 4) 115 #define _CYHAL_TCPWM_CHANNELS (TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR + TCPWM_GRP_NR2_GRP_GRP_CNT_NR + TCPWM_GRP_NR3_GRP_GRP_CNT_NR) 116 #endif 117 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 118 #if (TCPWM0_GRP_NR == 0) 119 #define _CYHAL_TCPWM0_CHANNELS (0U) 120 #elif (TCPWM0_GRP_NR == 1) 121 #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR) 122 #elif (TCPWM0_GRP_NR == 2) 123 #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR) 124 #elif (TCPWM0_GRP_NR == 3) 125 #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR) 126 #elif (TCPWM0_GRP_NR == 4) 127 #define _CYHAL_TCPWM0_CHANNELS (TCPWM0_GRP_NR0_GRP_GRP_CNT_NR + TCPWM0_GRP_NR1_GRP_GRP_CNT_NR + TCPWM0_GRP_NR2_GRP_GRP_CNT_NR + TCPWM0_GRP_NR3_GRP_GRP_CNT_NR) 128 #endif 129 #ifndef _CYHAL_TCPWM0_CHANNELS 130 #error "Unhandled TCPWM0_GRP_NR count" 131 #endif 132 #if (TCPWM1_GRP_NR == 0) 133 #define _CYHAL_TCPWM1_CHANNELS (0U) 134 #elif (TCPWM1_GRP_NR == 1) 135 #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR) 136 #elif (TCPWM1_GRP_NR == 2) 137 #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR) 138 #elif (TCPWM1_GRP_NR == 3) 139 #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR) 140 #elif (TCPWM1_GRP_NR == 4) 141 #define _CYHAL_TCPWM1_CHANNELS (TCPWM1_GRP_NR0_GRP_GRP_CNT_NR + TCPWM1_GRP_NR1_GRP_GRP_CNT_NR + TCPWM1_GRP_NR2_GRP_GRP_CNT_NR + TCPWM1_GRP_NR3_GRP_GRP_CNT_NR) 142 #endif 143 #ifndef _CYHAL_TCPWM1_CHANNELS 144 #error "Unhandled TCPWM1_GRP_NR count" 145 #endif 146 147 #define _CYHAL_TCPWM_CHANNELS (_CYHAL_TCPWM0_CHANNELS + _CYHAL_TCPWM1_CHANNELS) 148 #else 149 #warning Unhandled TCPWM instance count 150 #endif 151 #endif 152 #elif defined(CY_IP_M0S8TCPWM_INSTANCES) 153 #if (CY_IP_M0S8TCPWM_INSTANCES == 1) 154 #define _CYHAL_TCPWM_CHANNELS (TCPWM_CNT_NR) 155 #else 156 #warning Unhandled TCPWM instance count 157 #endif 158 #endif 159 160 #if (CY_IP_MXTCPWM_VERSION == 1U) 161 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 162 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 163 #elif (CY_IP_MXTCPWM_VERSION == 2U) 164 // PSoC™ 6 devices with trigmux vers2 also have a number of reserved input 165 // lines defined by TCPWM_TR_ONE_CNT_NR. 166 #if (CY_IP_MXTCPWM_INSTANCES == 1) 167 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 168 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 169 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 170 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2]; 171 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2]; 172 #else 173 #warning Unhandled TCPWM instance count 174 #endif 175 #else // (CY_IP_M0S8TCPWM_VERSION == 2) 176 // PSoC™ 4 devices have a number of reserved input lines coming directly from 177 // GPIO triggers (depending on exact architecture). 178 #if defined(CY_DEVICE_PSOC4AS1) 179 // 12 GPIO trigger lines reserved (but some may be unused, depending on 180 // pin package) 181 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 182 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 183 #else 184 // 7 GPIO trigger lines reserved (but some may be unused, depending on 185 // pin package) 186 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 187 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 188 #endif 189 #endif 190 191 /** \addtogroup group_hal_results_tcpwm TCPWM HAL Results 192 * TCPWM specific return codes 193 * \ingroup group_hal_results 194 * \{ *//** 195 */ 196 197 /** Bad argument. eg: null pointer */ 198 #define CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT \ 199 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 0)) 200 /** Failed to find free input signal */ 201 #define CYHAL_TCPWM_RSLT_ERR_NO_FREE_INPUT_SIGNALS \ 202 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 1)) 203 /** Failed to find free output signal */ 204 #define CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS \ 205 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 2)) 206 207 /** 208 * \} 209 */ 210 211 /** TCPWM/counter input signal */ 212 typedef enum 213 { 214 CYHAL_TCPWM_INPUT_START, //!< Start signal 215 CYHAL_TCPWM_INPUT_STOP, //!< Stop signal 216 CYHAL_TCPWM_INPUT_RELOAD, //!< Reload signal 217 CYHAL_TCPWM_INPUT_COUNT, //!< Count signal 218 CYHAL_TCPWM_INPUT_CAPTURE, //!< Capture signal 219 } cyhal_tcpwm_input_t; 220 221 /** The number of unique TCPWM inputs as defined by cyhal_tcpwm_input_t */ 222 #define _CYHAL_TCPWM_INPUTS 5 223 224 /** TCPWM/counter output signal */ 225 typedef enum 226 { 227 CYHAL_TCPWM_OUTPUT_OVERFLOW, //!< Overflow signal 228 CYHAL_TCPWM_OUTPUT_UNDERFLOW, //!< Underflow signal 229 CYHAL_TCPWM_OUTPUT_COMPARE_MATCH, //!< Compare match signal 230 CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT, //!< Terminal count signal (logical OR of overflow and underflow signal) 231 CYHAL_TCPWM_OUTPUT_LINE_OUT, //!< Line out signal 232 } cyhal_tcpwm_output_t; 233 234 /** The number of unique TCPWM outputs as defined by cyhal_tcpwm_output_t */ 235 #define _CYHAL_TCPWM_OUTPUTS 5 236 237 /** Handler for TCPWM interrupts */ 238 typedef void(*_cyhal_tcpwm_event_callback_t)(void *callback_arg, int event); 239 240 /** Holds data about a single TCPWM */ 241 typedef struct { 242 TCPWM_Type* base; //!< TCPWM base 243 en_clk_dst_t clock_dst; //!< TCPWM clock connections base 244 uint32_t max_count; //!< TCPWM counter width 245 uint8_t num_channels; //!< Number of channels on the TCPWM 246 uint8_t channel_offset; //!< Offset from channels on previous TCPWM 247 #if !defined(COMPONENT_CAT1C) 248 uint8_t isr_offset; //!< TCPWM base IRQn (channel 0 IRQn) 249 #else 250 /** CAT1C device has number of interrupts, which exceeds uint8_t type max. value */ 251 uint16_t isr_offset; //!< TCPWM base IRQn (channel 0 IRQn) 252 #endif // not CAT1C or CAT1C 253 } _cyhal_tcpwm_data_t; 254 255 /** Contains data about all of the TCPWMs */ 256 extern const _cyhal_tcpwm_data_t _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_INSTANCES]; 257 258 #ifdef CY_DEVICE_PSOC6A256K 259 /** Contains bitfield of in use data for all TCPWM output trigger lines. There 260 * are 2 available output lines per counter */ 261 extern uint8_t _CYHAL_OUTPUT_TRIGGERS_USED[TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR]; 262 #endif 263 264 /** 265 * Free a timer/counter or a PWM object's shared data 266 * 267 * @param[in] obj The timer/counter or the PWM resource 268 */ 269 void _cyhal_tcpwm_free(cyhal_tcpwm_t *obj); 270 271 /** Initialize a timer/counter or PWM object's callback data. 272 * 273 * @param[in,out] tcpwm The shared data struct between timer/counter and PWM 274 */ 275 void _cyhal_tcpwm_init_data(cyhal_tcpwm_t *tcpwm); 276 277 /** The TCPWM interrupt handler registration 278 * 279 * @param[in] resource The timer/counter or PWM resource 280 * @param[in] callback The callback handler which will be invoked when the event occurs 281 * @param[in] callback_arg Generic argument that will be provided to the callback when called 282 */ 283 void _cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg); 284 285 /** Configure TCPWM event enablement. 286 * 287 * @param[in] tcpwm The shared data struct between timer/counter and PWM 288 * @param[in] resource The timer/counter or PWM resource 289 * @param[in] event The timer/counter or PWM event type 290 * @param[in] intr_priority The priority for NVIC interrupt events 291 * @param[in] enable True to turn on events, False to turn off 292 */ 293 void _cyhal_tcpwm_enable_event(cyhal_tcpwm_t *tcpwm, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable); 294 295 /** Returns whether power management transition should be allowed. 296 * 297 * @return true if no tcpwm is actively blocking power mode transition 298 */ 299 bool _cyhal_tcpwm_pm_transition_pending(void); 300 301 /** Connects a source signal and configures and enables a TCPWM event to be 302 * triggered from that signal. These TCPWM events can be configured 303 * independently and connect to the same or different source signals. 304 * 305 * @param[in] obj TCPWM HAL object 306 * @param[in] source Source signal obtained from another driver's cyhal_<PERIPH>_enable_output 307 * @param[in] signal The TCPWM input signal 308 * @param[in] type The edge type of the signal to connect 309 * @return The status of the connection 310 * */ 311 cy_rslt_t _cyhal_tcpwm_connect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal, cyhal_edge_type_t type); 312 313 /** Enables the specified output signal from a TCPWM that will be triggered 314 * when the corresponding event occurs. Multiple output signals can be 315 * configured simultaneously. 316 * 317 * @param[in] obj TCPWM HAL object 318 * @param[in] signal The TCPWM output signal 319 * @param[out] source Pointer to user-allocated source signal object which 320 * will be initialized by enable_output. source should be passed to 321 * (dis)connect_digital functions to (dis)connect the associated endpoints. 322 * @return The status of the output enable 323 * */ 324 cy_rslt_t _cyhal_tcpwm_enable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal, cyhal_source_t *source); 325 326 /** Disconnects a source signal and disables the corresponding input to a TCPWM 327 * 328 * @param[in] obj TCPWM HAL object 329 * @param[in] source Source signal from cyhal_<PERIPH>_enable_output to disable 330 * @param[in] signal The TCPWM input signal 331 * @return The status of the disconnection 332 * */ 333 cy_rslt_t _cyhal_tcpwm_disconnect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal); 334 335 /** Disables the specified output signal from a TCPWM. 336 * 337 * @param[in] obj TCPWM HAL object 338 * @param[in] resource TCPWM resource 339 * @param[in] signal The TCPWM output signal 340 * @return The status of the output disable 341 * */ 342 cy_rslt_t _cyhal_tcpwm_disable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal); 343 344 #if (defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)) && \ 345 ((CY_IP_MXTCPWM_VERSION == 1) || (CY_IP_MXTCPWM_VERSION == 2) || (CY_IP_M0S8TCPWM_VERSION == 2)) 346 /** Get the destination reference for the provided TCPWM block and trigger 347 * 348 * @param[in] block TCPWM block number 349 * @param[in] trig_index The trigger index to get the destination for 350 * @return A destination that a signal can be connected to for the specified TCPWM block 351 * */ 352 cyhal_dest_t _cyhal_tpwm_calculate_dest(uint8_t block, uint8_t trig_index); 353 #endif 354 355 #if defined(__cplusplus) 356 } 357 #endif /* __cplusplus */ 358 359 #endif /* defined(CY_IP_MXTCPWM_INSTANCES) || defined(CY_IP_M0S8TCPWM_INSTANCES) */ 360 361 /** \} group_hal_impl_tcpwm_common */ 362 /** \endcond */ 363