1 /***************************************************************************//** 2 * \file cyhal_timer.h 3 * 4 * \brief 5 * Provides a high level interface for interacting with the Infineon Timer/Counter. 6 * This interface abstracts out the chip specific details. If any chip specific 7 * functionality is necessary, or performance is critical the low level functions 8 * can be used directly. 9 * 10 ******************************************************************************** 11 * \copyright 12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or 13 * an affiliate of Cypress Semiconductor Corporation 14 * 15 * SPDX-License-Identifier: Apache-2.0 16 * 17 * Licensed under the Apache License, Version 2.0 (the "License"); 18 * you may not use this file except in compliance with the License. 19 * You may obtain a copy of the License at 20 * 21 * http://www.apache.org/licenses/LICENSE-2.0 22 * 23 * Unless required by applicable law or agreed to in writing, software 24 * distributed under the License is distributed on an "AS IS" BASIS, 25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 * See the License for the specific language governing permissions and 27 * limitations under the License. 28 *******************************************************************************/ 29 30 /** 31 * \addtogroup group_hal_timer Timer (Timer/Counter) 32 * \ingroup group_hal 33 * \{ 34 * High level interface for interacting with the Timer/Counter hardware resource. 35 * 36 * The timer block is commonly used to measure the time of occurrence of an event, 37 * to measure the time difference between two events or perform an action after 38 * a specified period of time. The driver also allows the user to invoke a callback function 39 * when a particular event occurs. 40 * 41 * Some use case scenarios of timer - 42 * 43 * * Creating a periodic interrupt for executing periodic tasks 44 * * Measuring time between two events 45 * * Triggering other system resources after a certain number of events 46 * * Capturing time stamps when events occur 47 * 48 * \section subsection_timer_features Features 49 * * Runtime configurable parameters like period and compare value - \ref cyhal_timer_cfg_t 50 * * Configurable counting direction - \ref cyhal_timer_direction_t 51 * * Interrupt on various events - \ref cyhal_timer_event_t 52 * * Continuous or One Shot run modes 53 * 54 * \section subsection_timer_quickstart Quick Start 55 * 56 * \ref cyhal_timer_init can be used for timer initialization by providing the timer object - \ref cyhal_timer_t, 57 * and shared clock source - <b> clk </b> (optional). The timer parameters needs to be populated in \ref cyhal_timer_cfg_t structure. 58 * The timer then needs to be configured by using the \ref cyhal_timer_configure function. 59 * 60 * \note A default frequency is set when an existing clock divider - <b> clk </b> is not provided to \ref cyhal_timer_init which is 61 * defined by the macro - \ref CYHAL_TIMER_DEFAULT_FREQ. 62 * 63 * \warning Currently there is no support for pin connections to Timer using this driver. So, the <b> pin </b> should be 64 * assigned as \ref NC while using the \ref cyhal_timer_init to initialize the timer. 65 * 66 * 67 * See \ref subsection_timer_snippet_1. 68 * 69 * \section subsection_timer_sample_snippets Code Snippets 70 * 71 * \subsection subsection_timer_snippet_1 Snippet 1: Measuring time of an operation 72 * The following snippet initializes a Timer and measures the time between two events. 73 * The <b>clk</b> need not be provided, in which case a clock resource is assigned. 74 * \snippet hal_timer.c snippet_cyhal_timer_event_measure 75 * 76 * \subsection subsection_timer_snippet_2 Snippet 2: Handling an event in a callback function 77 * The following snippet initializes a Timer and triggers an event after every one second. 78 * The <b>clk</b> need not be provided (NULL), in which case a clock resource is assigned. 79 * \snippet hal_timer.c snippet_cyhal_timer_event_interrupt 80 * 81 */ 82 83 #pragma once 84 85 #include <stdint.h> 86 #include <stdbool.h> 87 #include "cy_result.h" 88 #include "cyhal_hw_types.h" 89 #if defined(COMPONENT_CAT5) 90 #include "cyhal_t2timer.h" 91 #endif 92 93 #if defined(__cplusplus) 94 extern "C" { 95 #endif 96 97 /** \addtogroup group_hal_results_timer Timer HAL Results 98 * Timer specific return codes 99 * \ingroup group_hal_results 100 * \{ *//** 101 */ 102 103 /** Bad argument. eg: null pointer */ 104 #define CYHAL_TIMER_RSLT_ERR_BAD_ARGUMENT \ 105 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 0)) 106 /** Failed to initialize Timer clock */ 107 #define CYHAL_TIMER_RSLT_ERR_CLOCK_INIT \ 108 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 1)) 109 /** Failed to initialize Timer */ 110 #define CYHAL_TIMER_RSLT_ERR_INIT \ 111 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 2)) 112 /** Cannot change the timer frequency when a shared clock divider is in use */ 113 #define CYHAL_TIMER_RSLT_ERR_SHARED_CLOCK \ 114 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 3)) 115 /** Feature unsupported with this Timer */ 116 #define CYHAL_TIMER_RSLT_ERR_UNSUPPORTED \ 117 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_TIMER, 4)) 118 119 /** 120 * \} 121 */ 122 123 /******************************************************************************* 124 * Enumerations 125 *******************************************************************************/ 126 127 /** Timer directions */ 128 typedef enum 129 { 130 CYHAL_TIMER_DIR_UP, //!< Counts up 131 CYHAL_TIMER_DIR_DOWN, //!< Counts down 132 CYHAL_TIMER_DIR_UP_DOWN, //!< Counts up and down, terminal count occurs on both overflow and underflow. 133 } cyhal_timer_direction_t; 134 135 /** Timer/counter interrupt triggers */ 136 typedef enum { 137 CYHAL_TIMER_IRQ_NONE = 0, /**< No interrupt handled **/ 138 CYHAL_TIMER_IRQ_TERMINAL_COUNT = 1 << 0, /**< Interrupt when terminal count is reached **/ 139 CYHAL_TIMER_IRQ_CAPTURE_COMPARE = 1 << 1, /**< Interrupt when Compare/Capture value is reached **/ 140 CYHAL_TIMER_IRQ_ALL = (1 << 2) - 1, /**< Interrupt on terminal count and Compare/Capture values **/ 141 } cyhal_timer_event_t; 142 143 /** Timer/counter input signal */ 144 typedef enum 145 { 146 CYHAL_TIMER_INPUT_START, //!< Start signal 147 CYHAL_TIMER_INPUT_STOP, //!< Stop signal 148 CYHAL_TIMER_INPUT_RELOAD, //!< Reload signal 149 CYHAL_TIMER_INPUT_COUNT, //!< Count signal 150 CYHAL_TIMER_INPUT_CAPTURE, //!< Capture signal 151 } cyhal_timer_input_t; 152 153 /** Timer/counter output signal */ 154 typedef enum 155 { 156 CYHAL_TIMER_OUTPUT_OVERFLOW, //!< Overflow signal 157 CYHAL_TIMER_OUTPUT_UNDERFLOW, //!< Underflow signal 158 CYHAL_TIMER_OUTPUT_COMPARE_MATCH, //!< Compare Match signal 159 CYHAL_TIMER_OUTPUT_TERMINAL_COUNT, //!< Terminal count signal (logical OR of overflow and underflow signal) 160 } cyhal_timer_output_t; 161 162 /******************************************************************************* 163 * Data Structures 164 *******************************************************************************/ 165 166 /** @brief Describes the current configuration of a timer/counter */ 167 typedef struct 168 { 169 /** 170 * Whether the timer is set to continuously run. 171 * If true, the timer will run forever. 172 * Otherwise, the timer will run once and stop (one shot). 173 */ 174 bool is_continuous; //!< Whether the timer/counter operates continuous (true) or one shot (false) 175 cyhal_timer_direction_t direction; //!< Direction the timer/counter is running 176 bool is_compare; //!< Is it in compare (true) or capture (false) mode 177 uint32_t period; //!< Timer/counter period 178 uint32_t compare_value; //!< Timer/counter comparison value 179 uint32_t value; //!< Default value of the timer/counter. \ref cyhal_timer_reset() will also change counter to this value when called. 180 } cyhal_timer_cfg_t; 181 182 /******************************************************************************* 183 * Typedefs 184 *******************************************************************************/ 185 186 /** Handler for timer events */ 187 typedef void(*cyhal_timer_event_callback_t)(void *callback_arg, cyhal_timer_event_t event); 188 189 /******************************************************************************* 190 * Defines 191 *******************************************************************************/ 192 193 /** Default timer frequency, used when an existing clock divider is not provided to \ref cyhal_timer_init() */ 194 #define CYHAL_TIMER_DEFAULT_FREQ (1000000u) 195 196 /******************************************************************************* 197 * Functions 198 *******************************************************************************/ 199 200 /** Initialize the timer/counter peripheral and configure the pin. <br> 201 * See \ref subsection_timer_snippet_1. 202 * 203 * @param[out] obj Pointer to a timer/counter object. The caller must allocate the memory 204 * for this object but the init function will initialize its contents. 205 * @param[in] pin optional - The timer/counter compare/capture pin to initialize 206 * @param[in] clk optional - The shared clock to use, if not provided a new clock will be allocated 207 * and the timer frequency will be set to \ref CYHAL_TIMER_DEFAULT_FREQ 208 * @return The status of the init request 209 */ 210 cy_rslt_t cyhal_timer_init(cyhal_timer_t *obj, cyhal_gpio_t pin, const cyhal_clock_t *clk); 211 212 /** Initialize the Timer peripheral using a configurator generated configuration struct 213 * 214 * @param[out] obj Pointer to a Timer object. The caller must allocate the memory 215 * for this object but the init function will initialize its contents. 216 * @param[in] cfg Configuration structure generated by a configurator. 217 * @return The status of the init request 218 */ 219 cy_rslt_t cyhal_timer_init_cfg(cyhal_timer_t *obj, const cyhal_timer_configurator_t *cfg); 220 221 /** Deinitialize the timer/counter object 222 * 223 * @param[in,out] obj The timer/counter object 224 */ 225 void cyhal_timer_free(cyhal_timer_t *obj); 226 227 /** Updates the configuration and counter value of the timer/counter object. <br> 228 * This function may temporary stop the timer if it is currently running. 229 * See \ref subsection_timer_snippet_1. 230 * @param[in] obj The timer/counter object 231 * @param[in] cfg The configuration of the timer/counter 232 * @return The status of the configure request 233 */ 234 cy_rslt_t cyhal_timer_configure(cyhal_timer_t *obj, const cyhal_timer_cfg_t *cfg); 235 236 /** Configures the timer frequency. 237 * \note This is only valid to call if a null clock divider was provided to \ref cyhal_timer_init. 238 * If a custom clock was provided its frequency should be adjusted directly. 239 * 240 * See \ref subsection_timer_snippet_1. 241 * @param[in] obj The timer/counter object 242 * @param[in] hz The frequency rate in Hz 243 * @return The status of the set_frequency request 244 */ 245 cy_rslt_t cyhal_timer_set_frequency(cyhal_timer_t *obj, uint32_t hz); 246 247 /** Starts the timer/counter with the pre-set configuration from \ref cyhal_timer_configure. 248 * This does not reset the counter. The count value will start from the value that was 249 * set by the last operation to modify it. See \ref cyhal_timer_configure, and \ref 250 * cyhal_timer_reset for how the value can be changed. If none of these functions have 251 * been called, it will start from 0.<br> 252 * See \ref subsection_timer_snippet_1. 253 * 254 * @param[in] obj The timer/counter object 255 * @return The status of the start request 256 */ 257 cy_rslt_t cyhal_timer_start(cyhal_timer_t *obj); 258 259 /** Stops the timer/counter. Does not reset counter value. <br> 260 * 261 * @param[in] obj The timer/counter object 262 * @return The status of the stop request 263 */ 264 cy_rslt_t cyhal_timer_stop(cyhal_timer_t *obj); 265 266 /** Reset the timer/counter value to the default value set from \ref cyhal_timer_configure. 267 * If \ref cyhal_timer_configure was never called, this will reset timer/counter value to 0. 268 * This function may temporary stop the timer. <br> 269 * 270 * @param[in] obj The timer/counter object 271 * @return The status of the reset request 272 */ 273 cy_rslt_t cyhal_timer_reset(cyhal_timer_t *obj); 274 275 /** Reads the current value from the timer/counter <br> 276 * See \ref subsection_timer_snippet_1. 277 * 278 * @param[in] obj The timer/counter object 279 * @return The current value of the timer/counter 280 */ 281 uint32_t cyhal_timer_read(const cyhal_timer_t *obj); 282 283 /** Register a timer/counter callback handler<br> 284 * 285 * This function will be called when one of the events enabled by \ref cyhal_timer_enable_event occurs. 286 * 287 * See \ref subsection_timer_snippet_2. 288 * 289 * @param[in] obj The timer/counter object 290 * @param[in] callback The callback handler which will be invoked when the event occurs 291 * @param[in] callback_arg Generic argument that will be provided to the callback when called 292 */ 293 void cyhal_timer_register_callback(cyhal_timer_t *obj, cyhal_timer_event_callback_t callback, void *callback_arg); 294 295 /** Configure timer/counter event enablement <br> 296 * 297 * When an enabled event occurs, the function specified by \ref cyhal_timer_register_callback will be called. 298 * 299 * See \ref subsection_timer_snippet_2. 300 * 301 * @param[in] obj The timer/counter object 302 * @param[in] event The timer/counter event type 303 * @param[in] intr_priority The priority for NVIC interrupt events 304 * @param[in] enable True to turn on interrupts, False to turn off 305 */ 306 void cyhal_timer_enable_event(cyhal_timer_t *obj, cyhal_timer_event_t event, uint8_t intr_priority, bool enable); 307 308 /** Connects a source signal and configures and enables a timer event to be 309 * triggered from that signal. These timer events can be configured 310 * independently and connect to the same or different source signals. 311 * @note For "edge" signals, this function will default to rising edge. To control the edge type, 312 * use @ref cyhal_timer_connect_digital2 313 * 314 * @param[in] obj Timer obj 315 * @param[in] source Source signal obtained from another driver's cyhal_<PERIPH>_enable_output 316 * @param[in] signal The timer input signal 317 * @return The current status of the connection 318 * */ 319 cy_rslt_t cyhal_timer_connect_digital(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal); 320 321 /** Connects a source signal and configures and enables a timer event to be 322 * triggered from that signal with a configurable edge type. These timer events 323 * can be configured independently and connect to the same or different source signals. 324 * 325 * @param[in] obj Timer obj 326 * @param[in] source Source signal obtained from another driver's cyhal_<PERIPH>_enable_output 327 * @param[in] signal The timer input signal 328 * @param[in] edge_type The edge type that should trigger the event. This must be consistent with the 329 * edge type of `source`. If `source` produces a "level" signal, the only valid 330 * value is @ref CYHAL_EDGE_TYPE_LEVEL. If `source` produces an "edge" signal, then 331 * @ref CYHAL_EDGE_TYPE_LEVEL is not a valid value. 332 * @return The current status of the connection 333 * */ 334 cy_rslt_t cyhal_timer_connect_digital2(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal, cyhal_edge_type_t edge_type); 335 336 /** Enables the specified output signal from a tcpwm that will be triggered 337 * when the corresponding event occurs. Multiple output signals can be 338 * configured simultaneously. 339 * 340 * @param[in] obj Timer obj 341 * @param[in] signal The timer output signal 342 * @param[out] source Pointer to user-allocated source signal object which 343 * will be initialized by enable_output. \p source should be passed to 344 * (dis)connect_digital functions to (dis)connect the associated endpoints. 345 * @return The current status of the output enable 346 * */ 347 cy_rslt_t cyhal_timer_enable_output(cyhal_timer_t *obj, cyhal_timer_output_t signal, cyhal_source_t *source); 348 349 /** Disconnects a source signal and disables the timer event. 350 * 351 * @param[in] obj Timer obj 352 * @param[in] source Source signal from cyhal_<PERIPH>_enable_output to disable 353 * @param[in] signal The timer input signal 354 * @return The status of the disconnection 355 * */ 356 cy_rslt_t cyhal_timer_disconnect_digital(cyhal_timer_t *obj, cyhal_source_t source, cyhal_timer_input_t signal); 357 358 /** Disables the specified output signal from a timer. 359 * 360 * @param[in] obj Timer obj 361 * @param[in] signal The timer output signal 362 * @return The status of the output disable 363 * */ 364 cy_rslt_t cyhal_timer_disable_output(cyhal_timer_t *obj, cyhal_timer_output_t signal); 365 366 #if defined(__cplusplus) 367 } 368 #endif 369 370 #ifdef CYHAL_TIMER_IMPL_HEADER 371 #include CYHAL_TIMER_IMPL_HEADER 372 #endif /* CYHAL_TIMER_IMPL_HEADER */ 373 374 /** \} group_hal_timer */ 375