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 #if (CY_IP_MXTCPWM_INSTANCES == 1) 162 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 163 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 164 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 165 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2]; 166 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2]; 167 #endif 168 #elif (CY_IP_MXTCPWM_VERSION == 2U) 169 // PSoC™ 6 devices with trigmux vers2 also have a number of reserved input 170 // lines defined by TCPWM_TR_ONE_CNT_NR. 171 #if (CY_IP_MXTCPWM_INSTANCES == 1) 172 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 173 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 174 #elif (CY_IP_MXTCPWM_INSTANCES == 2) 175 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[2]; 176 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[2]; 177 #else 178 #warning Unhandled TCPWM instance count 179 #endif 180 #else // (CY_IP_M0S8TCPWM_VERSION == 2) 181 // PSoC™ 4 devices have a number of reserved input lines coming directly from 182 // GPIO triggers (depending on exact architecture). 183 #if defined(CY_DEVICE_PSOC4AS1) 184 // 12 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 #else 189 // 7 GPIO trigger lines reserved (but some may be unused, depending on 190 // pin package) 191 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_IDX_OFFSET[1]; 192 extern const uint16_t _CYHAL_TCPWM_TRIGGER_INPUTS_PER_BLOCK[1]; 193 #endif 194 #endif 195 196 /** \addtogroup group_hal_results_tcpwm TCPWM HAL Results 197 * TCPWM specific return codes 198 * \ingroup group_hal_results 199 * \{ *//** 200 */ 201 202 /** Bad argument. eg: null pointer */ 203 #define CYHAL_TCPWM_RSLT_ERR_BAD_ARGUMENT \ 204 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 0)) 205 /** Failed to find free input signal */ 206 #define CYHAL_TCPWM_RSLT_ERR_NO_FREE_INPUT_SIGNALS \ 207 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 1)) 208 /** Failed to find free output signal */ 209 #define CYHAL_TCPWM_RSLT_ERR_NO_FREE_OUTPUT_SIGNALS \ 210 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_IMPL_TCPWM, 2)) 211 212 /** 213 * \} 214 */ 215 216 /** TCPWM/counter input signal */ 217 typedef enum 218 { 219 CYHAL_TCPWM_INPUT_START, //!< Start signal 220 CYHAL_TCPWM_INPUT_STOP, //!< Stop signal 221 CYHAL_TCPWM_INPUT_RELOAD, //!< Reload signal 222 CYHAL_TCPWM_INPUT_COUNT, //!< Count signal 223 CYHAL_TCPWM_INPUT_CAPTURE, //!< Capture signal 224 } cyhal_tcpwm_input_t; 225 226 /** The number of unique TCPWM inputs as defined by cyhal_tcpwm_input_t */ 227 #define _CYHAL_TCPWM_INPUTS 5 228 229 /** TCPWM/counter output signal */ 230 typedef enum 231 { 232 CYHAL_TCPWM_OUTPUT_OVERFLOW, //!< Overflow signal 233 CYHAL_TCPWM_OUTPUT_UNDERFLOW, //!< Underflow signal 234 CYHAL_TCPWM_OUTPUT_COMPARE_MATCH, //!< Compare match signal 235 CYHAL_TCPWM_OUTPUT_TERMINAL_COUNT, //!< Terminal count signal (logical OR of overflow and underflow signal) 236 CYHAL_TCPWM_OUTPUT_LINE_OUT, //!< Line out signal 237 } cyhal_tcpwm_output_t; 238 239 /** The number of unique TCPWM outputs as defined by cyhal_tcpwm_output_t */ 240 #define _CYHAL_TCPWM_OUTPUTS 5 241 242 /** Handler for TCPWM interrupts */ 243 typedef void(*_cyhal_tcpwm_event_callback_t)(void *callback_arg, int event); 244 245 /** Holds data about a single TCPWM */ 246 typedef struct { 247 TCPWM_Type* base; //!< TCPWM base 248 en_clk_dst_t clock_dst; //!< TCPWM clock connections base 249 uint32_t max_count; //!< TCPWM counter width 250 uint8_t num_channels; //!< Number of channels on the TCPWM 251 uint8_t channel_offset; //!< Offset from channels on previous TCPWM 252 #if (defined (CPUSS_SYSTEM_INT_NR) && (CPUSS_SYSTEM_INT_NR >= 256)) 253 uint16_t isr_offset; //!< TCPWM base IRQn (channel 0 IRQn) 254 #else 255 uint8_t isr_offset; //!< TCPWM base IRQn (channel 0 IRQn) 256 #endif 257 } _cyhal_tcpwm_data_t; 258 259 /** Contains data about all of the TCPWMs */ 260 extern const _cyhal_tcpwm_data_t _CYHAL_TCPWM_DATA[_CYHAL_TCPWM_INSTANCES]; 261 262 #ifdef CY_DEVICE_PSOC6A256K 263 /** Contains bitfield of in use data for all TCPWM output trigger lines. There 264 * are 2 available output lines per counter */ 265 extern uint8_t _CYHAL_OUTPUT_TRIGGERS_USED[TCPWM_GRP_NR0_GRP_GRP_CNT_NR + TCPWM_GRP_NR1_GRP_GRP_CNT_NR]; 266 #endif 267 268 /** 269 * Free a timer/counter or a PWM object's shared data 270 * 271 * @param[in] obj The timer/counter or the PWM resource 272 */ 273 void _cyhal_tcpwm_free(cyhal_tcpwm_t *obj); 274 275 /** Initialize a timer/counter or PWM object's callback data. 276 * 277 * @param[in,out] tcpwm The shared data struct between timer/counter and PWM 278 */ 279 void _cyhal_tcpwm_init_data(cyhal_tcpwm_t *tcpwm); 280 281 /** The TCPWM interrupt handler registration 282 * 283 * @param[in] resource The timer/counter or PWM resource 284 * @param[in] callback The callback handler which will be invoked when the event occurs 285 * @param[in] callback_arg Generic argument that will be provided to the callback when called 286 */ 287 void _cyhal_tcpwm_register_callback(cyhal_resource_inst_t *resource, cy_israddress callback, void *callback_arg); 288 289 /** Configure TCPWM event enablement. 290 * 291 * @param[in] tcpwm The shared data struct between timer/counter and PWM 292 * @param[in] resource The timer/counter or PWM resource 293 * @param[in] event The timer/counter or PWM event type 294 * @param[in] intr_priority The priority for NVIC interrupt events 295 * @param[in] enable True to turn on events, False to turn off 296 */ 297 void _cyhal_tcpwm_enable_event(cyhal_tcpwm_t *tcpwm, cyhal_resource_inst_t *resource, uint32_t event, uint8_t intr_priority, bool enable); 298 299 /** Returns whether power management transition should be allowed. 300 * 301 * @return true if no tcpwm is actively blocking power mode transition 302 */ 303 bool _cyhal_tcpwm_pm_transition_pending(void); 304 305 /** Connects a source signal and configures and enables a TCPWM event to be 306 * triggered from that signal. These TCPWM events can be configured 307 * independently and connect to the same or different source signals. 308 * 309 * @param[in] obj TCPWM HAL object 310 * @param[in] source Source signal obtained from another driver's cyhal_<PERIPH>_enable_output 311 * @param[in] signal The TCPWM input signal 312 * @param[in] type The edge type of the signal to connect 313 * @return The status of the connection 314 * */ 315 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); 316 317 /** Enables the specified output signal from a TCPWM that will be triggered 318 * when the corresponding event occurs. Multiple output signals can be 319 * configured simultaneously. 320 * 321 * @param[in] obj TCPWM HAL object 322 * @param[in] signal The TCPWM output signal 323 * @param[out] source Pointer to user-allocated source signal object which 324 * will be initialized by enable_output. source should be passed to 325 * (dis)connect_digital functions to (dis)connect the associated endpoints. 326 * @return The status of the output enable 327 * */ 328 cy_rslt_t _cyhal_tcpwm_enable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal, cyhal_source_t *source); 329 330 /** Disconnects a source signal and disables the corresponding input to a TCPWM 331 * 332 * @param[in] obj TCPWM HAL object 333 * @param[in] source Source signal from cyhal_<PERIPH>_enable_output to disable 334 * @param[in] signal The TCPWM input signal 335 * @return The status of the disconnection 336 * */ 337 cy_rslt_t _cyhal_tcpwm_disconnect_digital(cyhal_tcpwm_t *obj, cyhal_source_t source, cyhal_tcpwm_input_t signal); 338 339 /** Disables the specified output signal from a TCPWM. 340 * 341 * @param[in] obj TCPWM HAL object 342 * @param[in] resource TCPWM resource 343 * @param[in] signal The TCPWM output signal 344 * @return The status of the output disable 345 * */ 346 cy_rslt_t _cyhal_tcpwm_disable_output(cyhal_tcpwm_t *obj, cyhal_tcpwm_output_t signal); 347 348 #if (defined(CY_IP_M0S8PERI_TR) || defined(CY_IP_MXPERI_TR) || defined(CY_IP_MXSPERI)) && \ 349 ((CY_IP_MXTCPWM_VERSION == 1) || (CY_IP_MXTCPWM_VERSION == 2) || (CY_IP_M0S8TCPWM_VERSION == 2)) 350 /** Get the destination reference for the provided TCPWM block and trigger 351 * 352 * @param[in] block TCPWM block number 353 * @param[in] trig_index The trigger index to get the destination for 354 * @return A destination that a signal can be connected to for the specified TCPWM block 355 * */ 356 cyhal_dest_t _cyhal_tpwm_calculate_dest(uint8_t block, uint8_t trig_index); 357 #endif 358 359 #if defined(__cplusplus) 360 } 361 #endif /* __cplusplus */ 362 363 #endif /* defined(CY_IP_MXTCPWM_INSTANCES) || defined(CY_IP_M0S8TCPWM_INSTANCES) */ 364 365 /** \} group_hal_impl_tcpwm_common */ 366 /** \endcond */ 367