1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _HARDWARE_TIMER_H
8 #define _HARDWARE_TIMER_H
9 
10 #include "pico.h"
11 #include "hardware/structs/timer.h"
12 #include "hardware/regs/intctrl.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /** \file hardware/timer.h
19  *  \defgroup hardware_timer hardware_timer
20  *
21  * \brief Low-level hardware timer API
22  *
23  * This API provides medium level access to the timer HW.
24  * See also \ref pico_time which provides higher levels functionality using the hardware timer.
25  *
26  * The timer peripheral on RP-series microcontrollers supports the following features:
27  *  - RP2040 single 64-bit counter, incrementing once per microsecond
28  *  - RP2350 two 64-bit counters, ticks generated from the tick block
29  *  - Latching two-stage read of counter, for race-free read over 32 bit bus
30  *  - Four alarms: match on the lower 32 bits of counter, IRQ on match.
31  *
32  * \if rp2040_specific
33  * On RP2040, by default the timer uses a one microsecond reference that is generated in the Watchdog (see RP2040 Datasheet Section 4.8.2) which is derived
34  * from the clk_ref.
35  * \endif
36  *
37  * \if rp2350_specific
38  * On RP2350, by default the timer uses a one microsecond reference that is generated by the tick block (see RP2350 Datasheet Section 8.5)
39  * \endif
40  *
41  * The timer has 4 alarms, and can output a separate interrupt for each alarm. The alarms match on the lower 32 bits of the 64
42  * bit counter which means they can be fired a maximum of 2^32 microseconds into the future. This is equivalent to:
43  *  - 2^32 ÷ 10^6: ~4295 seconds
44  *  - 4295 ÷ 60: ~72 minutes
45  *
46  * The timer is expected to be used for short sleeps, if you want a longer alarm see the \ref hardware_rtc functions.
47  *
48  * \subsection timer_example Example
49  * \addtogroup hardware_timer
50  *
51  * \include hello_timer.c
52  *
53  * \see pico_time
54  */
55 
56 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_TIMER, Enable/disable assertions in the hardware_timer module, type=bool, default=0, group=hardware_timer
57 #ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_TIMER
58 #ifdef PARAM_ASSERTIONS_ENABLED_TIMER // backwards compatibility with SDK < 2.0.0
59 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_TIMER PARAM_ASSERTIONS_ENABLED_TIMER
60 #else
61 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_TIMER 0
62 #endif
63 #endif
64 
65 /**
66  * \def TIMER_NUM(timer)
67  * \ingroup hardware_timer
68  * \hideinitializer
69  * \brief Returns the timer number for a timer instance
70  *
71  * Note this macro is intended to resolve at compile time, and does no parameter checking
72  */
73 #ifndef TIMER_NUM
74 #if NUM_GENERIC_TIMERS == 1
75 #define TIMER_NUM(timer) ({ (void) (timer); 0; })
76 #elif NUM_GENERIC_TIMERS == 2
77 #define TIMER_NUM(timer) ((timer) == timer1_hw)
78 #endif
79 #endif
80 
81 /**
82  * \def TIMER_INSTANCE(timer_num)
83  * \ingroup hardware_timer
84  * \hideinitializer
85  * \brief Returns the timer instance with the given timer number
86  *
87  * Note this macro is intended to resolve at compile time, and does no parameter checking
88  */
89 #ifndef TIMER_INSTANCE
90 #if NUM_GENERIC_TIMERS == 1
91 #define TIMER_INSTANCE(num) timer_hw
92 #elif NUM_GENERIC_TIMERS == 2
93 #define TIMER_INSTANCE(num) ((num) ? timer1_hw : timer0_hw)
94 #endif
95 #endif
96 
97 /**
98  * \def TIMER_ALARM_IRQ_NUM(timer,alarm_num)
99  * \ingroup hardware_timer
100  * \hideinitializer
101  * \brief Returns the \ref irq_num_t for the alarm interrupt from the given alarm on the given timer instance
102  *
103  * Note this macro is intended to resolve at compile time, and does no parameter checking
104  */
105 #ifndef TIMER_ALARM_IRQ_NUM
106 #if NUM_GENERIC_TIMERS == 1
107 static_assert(TIMER_IRQ_3 == TIMER_IRQ_0 + 3, "");
108 #define TIMER_ALARM_IRQ_NUM(timer, alarm_num) ({ ((void)(timer)); (TIMER_IRQ_0 + (alarm_num)); })
109 #else
110 static_assert(TIMER1_IRQ_3 == TIMER0_IRQ_0 + 7, "");
111 #define TIMER_ALARM_IRQ_NUM(timer, alarm_num) (TIMER0_IRQ_0 + TIMER_NUM(timer) * NUM_ALARMS + (alarm_num))
112 #endif
113 #endif
114 
115 /**
116  * \def TIMER_ALARM_NUM_FROM_IRQ(irq_num)
117  * \ingroup hardware_timer
118  * \hideinitializer
119  * \brief Returns the alarm number from an \ref irq_num_t. See \ref TIMER_INSTANCE_NUM_FROM_IRQ to get the timer instance number
120  *
121  * Note this macro is intended to resolve at compile time, and does no parameter checking
122  */
123 #ifndef TIMER_ALARM_NUM_FROM_IRQ
124 #if NUM_GENERIC_TIMERS == 1
125 static_assert(TIMER_IRQ_3 == TIMER_IRQ_0 + 3, "");
126 #define TIMER_ALARM_NUM_FROM_IRQ(irq_num) (((irq_num) - TIMER_IRQ_0) & 3u)
127 #else
128 static_assert(TIMER1_IRQ_3 == TIMER0_IRQ_0 + 7, "");
129 #define TIMER_ALARM_NUM_FROM_IRQ(irq_num) (((irq_num) - TIMER0_IRQ_0) & 3u)
130 #endif
131 #endif
132 
133 /**
134  * \def TIMER_NUM_FROM_IRQ(irq_num)
135  * \ingroup hardware_timer
136  * \hideinitializer
137  * \brief Returns the alarm number from an \ref irq_num_t. See \ref TIMER_INSTANCE_NUM_FROM_IRQ to get the alarm number
138  *
139  * Note this macro is intended to resolve at compile time, and does no parameter checking
140  */
141 #ifndef TIMER_NUM_FROM_IRQ
142 #if NUM_GENERIC_TIMERS == 1
143 static_assert(TIMER_IRQ_3 == TIMER_IRQ_0 + 3, "");
144 #define TIMER_NUM_FROM_IRQ(irq_num) (((irq_num) - TIMER_IRQ_0) >> 2)
145 #else
146 static_assert(TIMER1_IRQ_3 == TIMER0_IRQ_0 + 7, "");
147 #define TIMER_NUM_FROM_IRQ(irq_num) (((irq_num) - TIMER0_IRQ_0) >> 2)
148 #endif
149 #endif
150 
151 // PICO_CONFIG: PICO_DEFAULT_TIMER, Timer instance number to use for RP2040-period hardware_timer APIs that assumed a single timer instance, min=0, max=1, default=0, group=hardware_timer
152 
153 /**
154  * \ingroup hardware_timer
155  * \brief The default timer instance number of the timer instance used for APIs that don't take an explicit timer instance
156  * \if rp2040_specific
157  * On RP2040 this must be 0 as there is only one timer instance
158  * \endif
159  * \if rp2350_specific
160  * On RP2040 this may be set to 0 or 1
161  * \endif
162  */
163 #ifndef PICO_DEFAULT_TIMER
164 #define PICO_DEFAULT_TIMER 0
165 #endif
166 
167 /**
168  * \def PICO_DEFAULT_TIMER_INSTANCE()
169  * \ingroup hardware_timer
170  * \hideinitializer
171  * \brief Returns the default timer instance on the platform based on the setting of PICO_DEFAULT_TIMER
172  *
173  * Note this macro is intended to resolve at compile time, and does no parameter checking
174  */
175 #ifndef PICO_DEFAULT_TIMER_INSTANCE
176 #if NUM_GENERIC_TIMERS == 1
177 #if PICO_DEFAULT_TIMER
178 #error Setting PICO_DEFAULT_TIMER to non zero is meaningless as there is only one TIMER instance on this platform
179 #endif
180 #define PICO_DEFAULT_TIMER_INSTANCE() timer_hw
181 #else
182 #define PICO_DEFAULT_TIMER_INSTANCE() (__CONCAT(__CONCAT(timer,PICO_DEFAULT_TIMER), _hw))
183 // also define timer_hw for backwards compatibility (just accesses the default instance)
184 #define timer_hw PICO_DEFAULT_TIMER_INSTANCE()
185 #endif
186 #endif
187 
check_hardware_alarm_num_param(__unused uint alarm_num)188 static inline void check_hardware_alarm_num_param(__unused uint alarm_num) {
189     invalid_params_if(HARDWARE_TIMER, alarm_num >= NUM_ALARMS);
190 }
191 
192 /*! \brief Return a 32 bit timestamp value in microseconds for a given timer instance
193 *  \ingroup hardware_timer
194 *
195 * Returns the low 32 bits of the hardware timer.
196 * \note This value wraps roughly every 1 hour 11 minutes and 35 seconds.
197 *
198 * \param timer the timer instance
199 * \return the 32 bit timestamp
200 * \sa time_us_32
201 */
timer_time_us_32(timer_hw_t * timer)202 static inline uint32_t timer_time_us_32(timer_hw_t *timer) {
203     return timer->timerawl;
204 }
205 
206 /*! \brief Return a 32 bit timestamp value in microseconds for the default timer instance
207 *  \ingroup hardware_timer
208 *
209 * Returns the low 32 bits of the hardware timer.
210 * \note This value wraps roughly every 1 hour 11 minutes and 35 seconds.
211 *
212 * \return the 32 bit timestamp
213 * \sa timer_time_us_32
214 */
time_us_32(void)215 static inline uint32_t time_us_32(void) {
216     return timer_time_us_32(PICO_DEFAULT_TIMER_INSTANCE());
217 }
218 
219 /*! \brief Return the current 64 bit timestamp value in microseconds for a given timer instance
220 *  \ingroup hardware_timer
221 *
222 * Returns the full 64 bits of the hardware timer. The \ref pico_time and other functions rely on the fact that this
223 * value monotonically increases from power up. As such it is expected that this value counts upwards and never wraps
224 * (we apologize for introducing a potential year 5851444 bug).
225 *
226 * \param timer the timer instance
227 * \return the 64 bit timestamp
228 * \sa time_us_64
229 */
230 uint64_t timer_time_us_64(timer_hw_t *timer);
231 
232 /*! \brief Return the current 64 bit timestamp value in microseconds for the default timer instance
233 *  \ingroup hardware_timer
234 *
235 * Returns the full 64 bits of the hardware timer. The \ref pico_time and other functions rely on the fact that this
236 * value monotonically increases from power up. As such it is expected that this value counts upwards and never wraps
237 * (we apologize for introducing a potential year 5851444 bug).
238 *
239 * \return the 64 bit timestamp
240 * \sa timer_time_us_64
241 * */
242 uint64_t time_us_64(void);
243 
244 /*! \brief Busy wait wasting cycles for the given (32 bit) number of microseconds using the given timer instance
245  *  \ingroup hardware_timer
246  *
247  * \param timer the timer instance
248  * \param delay_us delay amount in microseconds
249  * \sa busy_wait_us_32
250  */
251 void timer_busy_wait_us_32(timer_hw_t *timer, uint32_t delay_us);
252 
253 /*! \brief Busy wait wasting cycles for the given (32 bit) number of microseconds using the default timer instance
254  *  \ingroup hardware_timer
255  *
256  * \param delay_us delay amount in microseconds
257  * \sa timer_busy_wait_us_32
258  */
259 void busy_wait_us_32(uint32_t delay_us);
260 
261 /*! \brief Busy wait wasting cycles for the given (64 bit) number of microseconds using the given timer instance
262  *  \ingroup hardware_timer
263  *
264  * \param timer the timer instance
265  * \param delay_us delay amount in microseconds
266  * \sa busy_wait_us
267  */
268 void timer_busy_wait_us(timer_hw_t *timer, uint64_t delay_us);
269 
270 /*! \brief Busy wait wasting cycles for the given (64 bit) number of microseconds using the default timer instance
271  *  \ingroup hardware_timer
272  *
273  * \param delay_us delay amount in microseconds
274  * \sa timer_busy_wait_us
275  */
276 void busy_wait_us(uint64_t delay_us);
277 
278 /*! \brief Busy wait wasting cycles for the given number of milliseconds using the given timer instance
279  *  \ingroup hardware_timer
280  *
281  * \param timer the timer instance
282  * \param delay_ms delay amount in milliseconds
283  * \sa busy_wait_ms
284  */
285 void timer_busy_wait_ms(timer_hw_t *timer, uint32_t delay_ms);
286 
287 /*! \brief Busy wait wasting cycles for the given number of milliseconds using the default timer instance
288  *  \ingroup hardware_timer
289  *
290  * \param delay_ms delay amount in milliseconds
291  * \sa timer_busy_wait_ms
292  */
293 void busy_wait_ms(uint32_t delay_ms);
294 
295 /*! \brief Busy wait wasting cycles until after the specified timestamp using the given timer instance
296  *  \ingroup hardware_timer
297  *
298  * \param timer the timer instance
299  * \param t Absolute time to wait until
300  * \sa busy_wait_until
301  */
302 void timer_busy_wait_until(timer_hw_t *timer, absolute_time_t t);
303 
304 /*! \brief Busy wait wasting cycles until after the specified timestamp using the default timer instance
305  *  \ingroup hardware_timer
306  *
307  * \param t Absolute time to wait until
308  * \sa timer_busy_wait_until
309  */
310 void busy_wait_until(absolute_time_t t);
311 
312 /*! \brief Check if the specified timestamp has been reached on the given timer instance
313  *  \ingroup hardware_timer
314  *
315  * \param timer the timer instance
316  * \param t Absolute time to compare against current time
317  * \return true if it is now after the specified timestamp
318  * \sa time_reached
319  */
timer_time_reached(timer_hw_t * timer,absolute_time_t t)320 static inline bool timer_time_reached(timer_hw_t *timer, absolute_time_t t) {
321     uint64_t target = to_us_since_boot(t);
322     uint32_t hi_target = (uint32_t)(target >> 32u);
323     uint32_t hi = timer->timerawh;
324     return (hi >= hi_target && (timer->timerawl >= (uint32_t) target || hi != hi_target));
325 }
326 
327 /*! \brief Check if the specified timestamp has been reached on the default timer instance
328  *  \ingroup hardware_timer
329  *
330  * \param t Absolute time to compare against current time
331  * \return true if it is now after the specified timestamp
332  * \sa timer_time_reached
333  */
time_reached(absolute_time_t t)334 static inline bool time_reached(absolute_time_t t) {
335     return timer_time_reached(PICO_DEFAULT_TIMER_INSTANCE(), t);
336 }
337 
338 /*! Callback function type for hardware alarms
339  *  \ingroup hardware_timer
340  *
341  * Modification on the porting to Zephyr:
342  * Add parameter argument to enable referencing user data
343  *
344  * \param alarm_num the hardware alarm number
345  * \sa hardware_alarm_set_callback()
346  */
347 typedef void (*hardware_alarm_callback_t)(uint alarm_num, void *data);
348 
349 /*! \brief cooperatively claim the use of this hardware alarm_num on the given timer instance
350  *  \ingroup hardware_timer
351  *
352  * This method hard asserts if the hardware alarm is currently claimed.
353  *
354  * \param timer the timer instance
355  * \param alarm_num the hardware alarm to claim
356  * \sa hardware_alarm_claim
357  * \sa hardware_claiming
358  */
359 void timer_hardware_alarm_claim(timer_hw_t *timer, uint alarm_num);
360 
361 /*! \brief cooperatively claim the use of this hardware alarm_num on the default timer instance
362  *  \ingroup hardware_timer
363  *
364  * This method hard asserts if the hardware alarm is currently claimed.
365  *
366  * \param alarm_num the hardware alarm to claim
367  * \sa timer_hardware_alarm_claim
368  * \sa hardware_claiming
369  */
370 void hardware_alarm_claim(uint alarm_num);
371 
372 /*! \brief cooperatively claim the use of a hardware alarm_num on the given timer instance
373  *  \ingroup hardware_timer
374  *
375  * This method attempts to claim an unused hardware alarm
376  *
377  * \param timer the timer instance
378  * \param required if true the function will panic if none are available
379  * \return alarm_num the hardware alarm claimed or -1 if required was false, and none are available
380  * \sa hardware_alarm_claim_unused
381  * \sa hardware_claiming
382  */
383 int timer_hardware_alarm_claim_unused(timer_hw_t *timer, bool required);
384 
385 /*! \brief cooperatively claim the use of a hardware alarm_num on the default timer instance
386  *  \ingroup hardware_timer
387  *
388  * This method attempts to claim an unused hardware alarm
389  *
390  * \param required if true the function will panic if none are available
391  * \return alarm_num the hardware alarm claimed or -1 if required was false, and none are available
392  * \sa timer_hardware_alarm_claim_unused
393  * \sa hardware_claiming
394  */
395 int hardware_alarm_claim_unused(bool required);
396 
397 /*! \brief cooperatively release the claim on use of this hardware alarm_num on the given timer instance
398  *  \ingroup hardware_timer
399  *
400  * \param timer the timer instance
401  * \param alarm_num the hardware alarm to unclaim
402  * \sa hardware_alarm_unclaim
403  * \sa hardware_claiming
404  */
405 void timer_hardware_alarm_unclaim(timer_hw_t *timer, uint alarm_num);
406 
407 /*! \brief cooperatively release the claim on use of this hardware alarm_num on the default timer instance
408  *  \ingroup hardware_timer
409  *
410  * \param alarm_num the hardware alarm to unclaim
411  * \sa timer_hardware_alarm_unclaim
412  * \sa hardware_claiming
413  */
414 void hardware_alarm_unclaim(uint alarm_num);
415 
416 /*! \brief Determine if a hardware alarm has been claimed on the given timer instance
417  *  \ingroup hardware_timer
418  *
419  * \param timer the timer instance
420  * \param alarm_num the hardware alarm number
421  * \return true if claimed, false otherwise
422  * \sa hardware_alarm_is_claimed
423  * \sa hardware_alarm_claim
424  */
425 bool timer_hardware_alarm_is_claimed(timer_hw_t *timer, uint alarm_num);
426 
427 /*! \brief Determine if a hardware alarm has been claimed on the default timer instance
428  *  \ingroup hardware_timer
429  *
430  * \param alarm_num the hardware alarm number
431  * \return true if claimed, false otherwise
432  * \sa timer_hardware_alarm_is_claimed
433  * \sa hardware_alarm_claim
434  */
435 bool hardware_alarm_is_claimed(uint alarm_num);
436 
437 /*! \brief Enable/Disable a callback for a hardware alarm for a given timer instance on this core
438  *  \ingroup hardware_timer
439  *
440  * This method enables/disables the alarm IRQ for the specified hardware alarm on the
441  * calling core, and set the specified callback to be associated with that alarm.
442  *
443  * This callback will be used for the timeout set via hardware_alarm_set_target
444  *
445  * \note This will install the handler on the current core if the IRQ handler isn't already set.
446  * Therefore the user has the opportunity to call this up from the core of their choice
447  *
448  * \param timer the timer instance
449  * \param alarm_num the hardware alarm number
450  * \param callback the callback to install, or NULL to unset
451  *
452  * \sa hardware_alarm_set_callback
453  * \sa timer_hardware_alarm_set_target()
454  */
455 void timer_hardware_alarm_set_callback(timer_hw_t *timer, uint alarm_num, hardware_alarm_callback_t callback);
456 
457 /*! \brief Enable/Disable a callback for a hardware alarm on the default timer instance on this core
458  *  \ingroup hardware_timer
459  *
460  * This method enables/disables the alarm IRQ for the specified hardware alarm on the
461  * calling core, and set the specified callback to be associated with that alarm.
462  *
463  * This callback will be used for the timeout set via hardware_alarm_set_target
464  *
465  * \note This will install the handler on the current core if the IRQ handler isn't already set.
466  * Therefore the user has the opportunity to call this up from the core of their choice
467  *
468  * \param alarm_num the hardware alarm number
469  * \param callback the callback to install, or NULL to unset
470  *
471  * \sa timer_hardware_alarm_set_callback
472  * \sa hardware_alarm_set_target()
473  */
474 void hardware_alarm_set_callback(uint alarm_num, hardware_alarm_callback_t callback);
475 
476 /**
477  * \brief Set the current target for a specific hardware alarm on the given timer instance
478  * \ingroup hardware_timer
479  *
480  * This will replace any existing target
481  *
482  * \param timer the timer instance
483  * \param alarm_num the hardware alarm number
484  * \param t the target timestamp
485  * \return true if the target was "missed"; i.e. it was in the past, or occurred before a future hardware timeout could be set
486  * \sa hardware_alarm_set_target
487  */
488 bool timer_hardware_alarm_set_target(timer_hw_t *timer, uint alarm_num, absolute_time_t t);
489 
490 /**
491  * \brief Set the current target for the specified hardware alarm on the default timer instance
492  * \ingroup hardware_timer
493  *
494  * This will replace any existing target
495  *
496  * \param alarm_num the hardware alarm number
497  * \param t the target timestamp
498  * \return true if the target was "missed"; i.e. it was in the past, or occurred before a future hardware timeout could be set
499  * \sa timer_hardware_alarm_set_target
500  */
501 bool hardware_alarm_set_target(uint alarm_num, absolute_time_t t);
502 
503 /**
504  * \brief Cancel an existing target (if any) for a specific hardware_alarm on the given timer instance
505  * \ingroup hardware_timer
506  *
507  * \param timer the timer instance
508  * \param alarm_num the hardware alarm number
509  * \sa hardware_alarm_cancel
510  */
511 void timer_hardware_alarm_cancel(timer_hw_t *timer, uint alarm_num);
512 
513 /**
514  * \brief Cancel an existing target (if any) for the specified hardware_alarm on the default timer instance
515  * \ingroup hardware_timer
516  *
517  * \param alarm_num the hardware alarm number
518  * \sa timer_hardware_alarm_cancel
519  */
520 void hardware_alarm_cancel(uint alarm_num);
521 
522 /**
523  * \brief Force and IRQ for a specific hardware alarm on the given timer instance
524  * \ingroup hardware_timer
525  *
526  * This method will forcibly make sure the current alarm callback (if present) for the hardware
527  * alarm is called from an IRQ context after this call. If an actual callback is due at the same
528  * time then the callback may only be called once.
529  *
530  * Calling this method does not otherwise interfere with regular callback operations.
531  *
532  * \param timer the timer instance
533  * \param alarm_num the hardware alarm number
534  * \sa hardware_alarm_force_irq
535  */
536 void timer_hardware_alarm_force_irq(timer_hw_t *timer, uint alarm_num);
537 
538 /**
539  * \brief Force and IRQ for a specific hardware alarm on the default timer instance
540  * \ingroup hardware_timer
541  *
542  * This method will forcibly make sure the current alarm callback (if present) for the hardware
543  * alarm is called from an IRQ context after this call. If an actual callback is due at the same
544  * time then the callback may only be called once.
545  *
546  * Calling this method does not otherwise interfere with regular callback operations.
547  *
548  * \param alarm_num the hardware alarm number
549  * \sa timer_hardware_alarm_force_irq
550  */
551 void hardware_alarm_force_irq(uint alarm_num);
552 
553 /**
554  * \ingroup hardware_timer
555  * \brief Returns the \ref irq_num_t for the alarm interrupt from the given alarm on the given timer instance
556  * \param timer the timer instance
557  * \param alarm_num the alarm number
558  * \sa TIMER_ALARM_IRQ_NUM
559  */
timer_hardware_alarm_get_irq_num(timer_hw_t * timer,uint alarm_num)560 static inline uint timer_hardware_alarm_get_irq_num(timer_hw_t *timer, uint alarm_num) {
561     check_hardware_alarm_num_param(alarm_num);
562     return TIMER_ALARM_IRQ_NUM(timer, alarm_num);
563 }
564 
565 /**
566  * \ingroup hardware_timer
567  * \brief Returns the \ref irq_num_t for the alarm interrupt from the given alarm on the default timer instance
568  * \param alarm_num the alarm number
569  */
hardware_alarm_get_irq_num(uint alarm_num)570 static inline uint hardware_alarm_get_irq_num(uint alarm_num) {
571     return timer_hardware_alarm_get_irq_num(PICO_DEFAULT_TIMER_INSTANCE(), alarm_num);
572 }
573 
574 /**
575  * \ingroup hardware_timer
576  * \brief Returns the timer number for a timer instance
577  *
578  * \param timer the timer instance
579  * \return the timer number
580  * \sa TIMER_NUM
581  */
timer_get_index(timer_hw_t * timer)582 static inline uint timer_get_index(timer_hw_t *timer) {
583     return TIMER_NUM(timer);
584 }
585 
586 /**
587  * \ingroup hardware_timer
588  * \brief Returns the timer instance with the given timer number
589  *
590  * \param timer_num the timer number
591  * \return the timer instance
592  */
timer_get_instance(uint timer_num)593 static inline timer_hw_t *timer_get_instance(uint timer_num) {
594     invalid_params_if(HARDWARE_TIMER, timer_num >= NUM_GENERIC_TIMERS);
595     return TIMER_INSTANCE(timer_num);
596 }
597 
598 /**
599  * Modification on the porting to Zephyr:
600  * Publish as API.
601  * Add parameter argument to enable referencing user data
602  */
603 void hardware_alarm_irq_handler(void *dev);
604 #ifdef __cplusplus
605 }
606 #endif
607 #endif
608