1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef _HARDWARE_IRQ_H
8 #define _HARDWARE_IRQ_H
9
10 // These two config items are also used by assembler, so keeping separate
11 // PICO_CONFIG: PICO_MAX_SHARED_IRQ_HANDLERS, Maximum number of shared IRQ handlers, default=4, advanced=true, group=hardware_irq
12 #ifndef PICO_MAX_SHARED_IRQ_HANDLERS
13 #define PICO_MAX_SHARED_IRQ_HANDLERS 4
14 #endif
15
16 // PICO_CONFIG: PICO_DISABLE_SHARED_IRQ_HANDLERS, Disable shared IRQ handlers, type=bool, default=0, group=hardware_irq
17 #ifndef PICO_DISABLE_SHARED_IRQ_HANDLERS
18 #define PICO_DISABLE_SHARED_IRQ_HANDLERS 0
19 #endif
20
21 // PICO_CONFIG: PICO_VTABLE_PER_CORE, User is using separate vector tables per core, type=bool, default=0, group=hardware_irq
22 #ifndef PICO_VTABLE_PER_CORE
23 #define PICO_VTABLE_PER_CORE 0
24 #endif
25
26 #ifndef __ASSEMBLER__
27
28 #include "pico.h"
29 #include "hardware/address_mapped.h"
30 #include "hardware/regs/intctrl.h"
31
32 #include "pico/platform/cpu_regs.h"
33
34 /** \file irq.h
35 * \defgroup hardware_irq hardware_irq
36 *
37 * \brief Hardware interrupt handling API
38 *
39 * The RP2040 uses the standard ARM nested vectored interrupt controller (NVIC).
40 *
41 * Interrupts are identified by a number from 0 to 31.
42 *
43 * On the RP2040, only the lower 26 IRQ signals are connected on the NVIC; IRQs 26 to 31 are tied to zero (never firing).
44 *
45 * There is one NVIC per core, and each core's NVIC has the same hardware interrupt lines routed to it, with the exception of the IO interrupts
46 * where there is one IO interrupt per bank, per core. These are completely independent, so, for example, processor 0 can be
47 * interrupted by GPIO 0 in bank 0, and processor 1 by GPIO 1 in the same bank.
48 *
49 * \note That all IRQ APIs affect the executing core only (i.e. the core calling the function).
50 *
51 * \note You should not enable the same (shared) IRQ number on both cores, as this will lead to race conditions
52 * or starvation of one of the cores. Additionally, don't forget that disabling interrupts on one core does not disable interrupts
53 * on the other core.
54 *
55 * There are three different ways to set handlers for an IRQ:
56 * - Calling irq_add_shared_handler() at runtime to add a handler for a multiplexed interrupt (e.g. GPIO bank) on the current core. Each handler, should check and clear the relevant hardware interrupt source
57 * - Calling irq_set_exclusive_handler() at runtime to install a single handler for the interrupt on the current core
58 * - Defining the interrupt handler explicitly in your application (e.g. by defining void `isr_dma_0` will make that function the handler for the DMA_IRQ_0 on core 0, and
59 * you will not be able to change it using the above APIs at runtime). Using this method can cause link conflicts at runtime, and offers no runtime performance benefit (i.e, it should not generally be used).
60 *
61 * \note If an IRQ is enabled and fires with no handler installed, a breakpoint will be hit and the IRQ number will
62 * be in register r0.
63 *
64 * \section interrupt_nums Interrupt Numbers
65 *
66 * A set of defines is available (intctrl.h) with these names to avoid using the numbers directly.
67 *
68 * \if rp2040_specific
69 * On RP2040 the interrupt numbers are as follows:
70 *
71 * IRQ | Interrupt Source
72 * ----|-----------------
73 * 0 | TIMER_IRQ_0
74 * 1 | TIMER_IRQ_1
75 * 2 | TIMER_IRQ_2
76 * 3 | TIMER_IRQ_3
77 * 4 | PWM_IRQ_WRAP
78 * 5 | USBCTRL_IRQ
79 * 6 | XIP_IRQ
80 * 7 | PIO0_IRQ_0
81 * 8 | PIO0_IRQ_1
82 * 9 | PIO1_IRQ_0
83 * 10 | PIO1_IRQ_1
84 * 11 | DMA_IRQ_0
85 * 12 | DMA_IRQ_1
86 * 13 | IO_IRQ_BANK0
87 * 14 | IO_IRQ_QSPI
88 * 15 | SIO_IRQ_PROC0
89 * 16 | SIO_IRQ_PROC1
90 * 17 | CLOCKS_IRQ
91 * 18 | SPI0_IRQ
92 * 19 | SPI1_IRQ
93 * 20 | UART0_IRQ
94 * 21 | UART1_IRQ
95 * 22 | ADC0_IRQ_FIFO
96 * 23 | I2C0_IRQ
97 * 24 | I2C1_IRQ
98 * 25 | RTC_IRQ
99 * \endif
100 *
101 * \if rp2350_specific
102 * On RP2350 the interrupt numbers are as follows:
103 *
104 * IRQ | Interrupt Source
105 * ----|-----------------
106 * 0 | TIMER0_IRQ_0
107 * 1 | TIMER0_IRQ_1
108 * 2 | TIMER0_IRQ_2
109 * 3 | TIMER0_IRQ_3
110 * 4 | TIMER1_IRQ_0
111 * 5 | TIMER1_IRQ_1
112 * 6 | TIMER1_IRQ_2
113 * 7 | TIMER1_IRQ_3
114 * 8 | PWM_IRQ_WRAP_0
115 * 9 | PWM_IRQ_WRAP_1
116 * 10 | DMA_IRQ_0
117 * 11 | DMA_IRQ_1
118 * 12 | DMA_IRQ_2
119 * 13 | DMA_IRQ_3
120 * 14 | USBCTRL_IRQ
121 * 15 | PIO0_IRQ_0
122 * 16 | PIO0_IRQ_1
123 * 17 | PIO1_IRQ_0
124 * 18 | PIO1_IRQ_1
125 * 19 | PIO2_IRQ_0
126 * 20 | PIO2_IRQ_1
127 * 21 | IO_IRQ_BANK0
128 * 22 | IO_IRQ_BANK0_NS
129 * 23 | IO_IRQ_QSPI
130 * 24 | IO_IRQ_QSPI_NS
131 * 25 | SIO_IRQ_FIFO
132 * 26 | SIO_IRQ_BELL
133 * 27 | SIO_IRQ_FIFO_NS
134 * 28 | SIO_IRQ_BELL_NS
135 * 29 | SIO_IRQ_MTIMECMP
136 * 30 | CLOCKS_IRQ
137 * 31 | SPI0_IRQ
138 * 32 | SPI1_IRQ
139 * 33 | UART0_IRQ
140 * 34 | UART1_IRQ
141 * 35 | ADC_IRQ_FIFO
142 * 36 | I2C0_IRQ
143 * 37 | I2C1_IRQ
144 * 38 | OTP_IRQ
145 * 39 | TRNG_IRQ
146 * 40 | PROC0_IRQ_CTI
147 * 41 | PROC1_IRQ_CTI
148 * 42 | PLL_SYS_IRQ
149 * 43 | PLL_USB_IRQ
150 * 44 | POWMAN_IRQ_POW
151 * 45 | POWMAN_IRQ_TIMER
152 * 46 | SPAREIRQ_IRQ_0
153 * 47 | SPAREIRQ_IRQ_1
154 * 48 | SPAREIRQ_IRQ_2
155 * 49 | SPAREIRQ_IRQ_3
156 * 50 | SPAREIRQ_IRQ_4
157 * 51 | SPAREIRQ_IRQ_5
158 * \endif
159 */
160
161 // PICO_CONFIG: PICO_DEFAULT_IRQ_PRIORITY, Define the default IRQ priority, default=0x80, group=hardware_irq
162 #ifndef PICO_DEFAULT_IRQ_PRIORITY
163 #define PICO_DEFAULT_IRQ_PRIORITY 0x80
164 #endif
165
166 #define PICO_LOWEST_IRQ_PRIORITY 0xff
167 #define PICO_HIGHEST_IRQ_PRIORITY 0x00
168
169 // PICO_CONFIG: PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY, Set default shared IRQ order priority, default=0x80, group=hardware_irq
170 #ifndef PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY
171 #define PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY 0x80
172 #endif
173
174 #define PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY 0xff
175 #define PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY 0x00
176
177 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_IRQ, Enable/disable assertions in the hardware_irq module, type=bool, default=0, group=hardware_irq
178 #ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_IRQ
179 #ifdef PARAM_ASSERTIONS_ENABLED_IRQ // backwards compatibility with SDK < 2.0.0
180 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_IRQ PARAM_ASSERTIONS_ENABLED_IRQ
181 #else
182 #define PARAM_ASSERTIONS_ENABLED_HARDWARE_IRQ 0
183 #endif
184 #endif
185
186 #ifdef __cplusplus
187 extern "C" {
188 #endif
189
190 /*! \brief Interrupt handler function type
191 * \ingroup hardware_irq
192 *
193 * All interrupts handlers should be of this type, and follow normal ARM EABI register saving conventions
194 */
195 typedef void (*irq_handler_t)(void);
196
check_irq_param(__unused uint num)197 static inline void check_irq_param(__unused uint num) {
198 invalid_params_if(HARDWARE_IRQ, num >= NUM_IRQS);
199 }
200
201 /*! \brief Set specified interrupt's priority
202 * \ingroup hardware_irq
203 *
204 * \param num Interrupt number \ref interrupt_nums
205 * \param hardware_priority Priority to set.
206 * Numerically-lower values indicate a higher priority. Hardware priorities
207 * range from 0 (highest priority) to 255 (lowest priority). To make it easier to specify
208 * higher or lower priorities than the default, all IRQ priorities are
209 * initialized to PICO_DEFAULT_IRQ_PRIORITY by the SDK runtime at startup.
210 * PICO_DEFAULT_IRQ_PRIORITY defaults to 0x80
211 *
212 * \if rp2040_specific
213 * Only the top 2 bits are significant on ARM Cortex-M0+ on RP2040.
214 * \endif
215 *
216 * \if rp2350_specific
217 * Only the top 4 bits are significant on ARM Cortex-M33 or Hazard3 (RISC-V) on RP2350.
218 * Note that this API uses the same (inverted) ordering as ARM on RISC-V
219 * \endif
220 */
221 void irq_set_priority(uint num, uint8_t hardware_priority);
222
223 /*! \brief Get specified interrupt's priority
224 * \ingroup hardware_irq
225 *
226 * Numerically-lower values indicate a higher priority. Hardware priorities
227 * range from 0 (highest priority) to 255 (lowest priority). To make it easier to specify
228 * higher or lower priorities than the default, all IRQ priorities are
229 * initialized to PICO_DEFAULT_IRQ_PRIORITY by the SDK runtime at startup.
230 * PICO_DEFAULT_IRQ_PRIORITY defaults to 0x80
231 *
232 * \if rp2040_specific
233 * Only the top 2 bits are significant on ARM Cortex-M0+ on RP2040.
234 * \endif
235 *
236 * \if rp2350_specific
237 * Only the top 4 bits are significant on ARM Cortex-M33 or Hazard3 (RISC-V) on RP2350.
238 * Note that this API uses the same (inverted) ordering as ARM on RISC-V
239 * \endif
240 *
241 * \param num Interrupt number \ref interrupt_nums
242 * \return the IRQ priority
243 */
244 uint irq_get_priority(uint num);
245
246 /*! \brief Enable or disable a specific interrupt on the executing core
247 * \ingroup hardware_irq
248 *
249 * \param num Interrupt number \ref interrupt_nums
250 * \param enabled true to enable the interrupt, false to disable
251 */
252 void irq_set_enabled(uint num, bool enabled);
253
254 /*! \brief Determine if a specific interrupt is enabled on the executing core
255 * \ingroup hardware_irq
256 *
257 * \param num Interrupt number \ref interrupt_nums
258 * \return true if the interrupt is enabled
259 */
260 bool pico_irq_is_enabled(uint num);
261
262 /*! \brief Enable/disable multiple interrupts on the executing core
263 * \ingroup hardware_irq
264 *
265 * \param mask 32-bit mask with one bits set for the interrupts to enable/disable \ref interrupt_nums
266 * \param enabled true to enable the interrupts, false to disable them.
267 */
268 void irq_set_mask_enabled(uint32_t mask, bool enabled);
269
270 /*! \brief Enable/disable multiple interrupts on the executing core
271 * \ingroup hardware_irq
272 *
273 * \param n the index of the mask to update. n == 0 means 0->31, n == 1 mean 32->63 etc.
274 * \param mask 32-bit mask with one bits set for the interrupts to enable/disable \ref interrupt_nums
275 * \param enabled true to enable the interrupts, false to disable them.
276 */
277 void irq_set_mask_n_enabled(uint n, uint32_t mask, bool enabled);
278
279 /*! \brief Set an exclusive interrupt handler for an interrupt on the executing core.
280 * \ingroup hardware_irq
281 *
282 * Use this method to set a handler for single IRQ source interrupts, or when
283 * your code, use case or performance requirements dictate that there should
284 * no other handlers for the interrupt.
285 *
286 * This method will assert if there is already any sort of interrupt handler installed
287 * for the specified irq number.
288 *
289 * \param num Interrupt number \ref interrupt_nums
290 * \param handler The handler to set. See \ref irq_handler_t
291 * \see irq_add_shared_handler()
292 */
293 void irq_set_exclusive_handler(uint num, irq_handler_t handler);
294
295 /*! \brief Get the exclusive interrupt handler for an interrupt on the executing core.
296 * \ingroup hardware_irq
297 *
298 * This method will return an exclusive IRQ handler set on this core
299 * by irq_set_exclusive_handler if there is one.
300 *
301 * \param num Interrupt number \ref interrupt_nums
302 * \see irq_set_exclusive_handler()
303 * \return handler The handler if an exclusive handler is set for the IRQ,
304 * NULL if no handler is set or shared/shareable handlers are installed
305 */
306 irq_handler_t irq_get_exclusive_handler(uint num);
307
308 /*! \brief Add a shared interrupt handler for an interrupt on the executing core
309 * \ingroup hardware_irq
310 *
311 * Use this method to add a handler on an irq number shared between multiple distinct hardware sources (e.g. GPIO, DMA or PIO IRQs).
312 * Handlers added by this method will all be called in sequence from highest order_priority to lowest. The
313 * irq_set_exclusive_handler() method should be used instead if you know there will or should only ever be one handler for the interrupt.
314 *
315 * This method will assert if there is an exclusive interrupt handler set for this irq number on this core, or if
316 * the (total across all IRQs on both cores) maximum (configurable via PICO_MAX_SHARED_IRQ_HANDLERS) number of shared handlers
317 * would be exceeded.
318 *
319 * \param num Interrupt number \ref interrupt_nums
320 * \param handler The handler to set. See \ref irq_handler_t
321 * \param order_priority The order priority controls the order that handlers for the same IRQ number on the core are called.
322 * The shared irq handlers for an interrupt are all called when an IRQ fires, however the order of the calls is based
323 * on the order_priority (higher priorities are called first, identical priorities are called in undefined order). A good
324 * rule of thumb is to use PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY if you don't much care, as it is in the middle of
325 * the priority range by default.
326 *
327 * \note The order_priority uses \em higher values for higher priorities which is the \em opposite of the CPU interrupt priorities passed
328 * to irq_set_priority() which use lower values for higher priorities.
329 *
330 * \see irq_set_exclusive_handler()
331 */
332 void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_priority);
333
334 /*! \brief Remove a specific interrupt handler for the given irq number on the executing core
335 * \ingroup hardware_irq
336 *
337 * This method may be used to remove an irq set via either irq_set_exclusive_handler() or
338 * irq_add_shared_handler(), and will assert if the handler is not currently installed for the given
339 * IRQ number
340 *
341 * \note This method may *only* be called from user (non IRQ code) or from within the handler
342 * itself (i.e. an IRQ handler may remove itself as part of handling the IRQ). Attempts to call
343 * from another IRQ will cause an assertion.
344 *
345 * \param num Interrupt number \ref interrupt_nums
346 * \param handler The handler to removed.
347 * \see irq_set_exclusive_handler()
348 * \see irq_add_shared_handler()
349 */
350 void irq_remove_handler(uint num, irq_handler_t handler);
351
352 /*! \brief Determine if the current handler for the given number is shared
353 * \ingroup hardware_irq
354 *
355 * \param num Interrupt number \ref interrupt_nums
356 * \return true if the specified IRQ has a shared handler
357 */
358 bool irq_has_shared_handler(uint num);
359
360 /*! \brief Get the current IRQ handler for the specified IRQ from the currently installed hardware vector table (VTOR)
361 * of the execution core
362 * \ingroup hardware_irq
363 *
364 * \param num Interrupt number \ref interrupt_nums
365 * \return the address stored in the VTABLE for the given irq number
366 */
367 irq_handler_t irq_get_vtable_handler(uint num);
368
369 /*! \brief Clear a specific interrupt on the executing core
370 * \ingroup hardware_irq
371 *
372 * This method is only useful for "software" IRQs that are not connected to hardware (e.g. IRQs 26-31 on RP2040)
373 * as the the NVIC always reflects the current state of the IRQ state of the hardware for hardware IRQs, and clearing
374 * of the IRQ state of the hardware is performed via the hardware's registers instead.
375 *
376 * \param int_num Interrupt number \ref interrupt_nums
377 */
irq_clear(uint int_num)378 static inline void irq_clear(uint int_num) {
379 #if PICO_RP2040
380 *((volatile uint32_t *) (PPB_BASE + M0PLUS_NVIC_ICPR_OFFSET)) = (1u << ((uint32_t) (int_num & 0x1F)));
381 #elif defined(__riscv)
382 // External IRQs are not latched, but we should clear the IRQ force bit here
383 hazard3_irqarray_clear(RVCSR_MEIFA_OFFSET, int_num / 16, 1u << (int_num % 16));
384 #else
385 nvic_hw->icpr[int_num/32] = 1 << (int_num % 32);
386 #endif
387 }
388
389 /*! \brief Force an interrupt to be pending on the executing core
390 * \ingroup hardware_irq
391 *
392 * This should generally not be used for IRQs connected to hardware.
393 *
394 * \param num Interrupt number \ref interrupt_nums
395 */
396 void irq_set_pending(uint num);
397
398
399 /*! \brief Perform IRQ priority initialization for the current core
400 *
401 * \note This is an internal method and user should generally not call it.
402 */
403 void runtime_init_per_core_irq_priorities(void);
404
irq_init_priorities(void)405 static __force_inline void irq_init_priorities(void) {
406 runtime_init_per_core_irq_priorities();
407 }
408
409 /*! \brief Claim ownership of a user IRQ on the calling core
410 * \ingroup hardware_irq
411 *
412 * User IRQs starting from FIRST_USER_IRQ are not connected to any hardware, but can be triggered by \ref irq_set_pending.
413 *
414 * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therefore all functions
415 * dealing with Uer IRQs affect only the calling core
416 *
417 * This method explicitly claims ownership of a user IRQ, so other code can know it is being used.
418 *
419 * \param irq_num the user IRQ to claim
420 */
421 void user_irq_claim(uint irq_num);
422
423 /*! \brief Mark a user IRQ as no longer used on the calling core
424 * \ingroup hardware_irq
425 *
426 * User IRQs starting from FIRST_USER_IRQ are not connected to any hardware, but can be triggered by \ref irq_set_pending.
427 *
428 * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therefore all functions
429 * dealing with Uer IRQs affect only the calling core
430 *
431 * This method explicitly releases ownership of a user IRQ, so other code can know it is free to use.
432 *
433 * \note it is customary to have disabled the irq and removed the handler prior to calling this method.
434 *
435 * \param irq_num the irq irq_num to unclaim
436 */
437 void user_irq_unclaim(uint irq_num);
438
439 /*! \brief Claim ownership of a free user IRQ on the calling core
440 * \ingroup hardware_irq
441 *
442 * User IRQs starting from FIRST_USER_IRQ are not connected to any hardware, but can be triggered by \ref irq_set_pending.
443 *
444 * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therefore all functions
445 * dealing with Uer IRQs affect only the calling core
446 *
447 * This method explicitly claims ownership of an unused user IRQ if there is one, so other code can know it is being used.
448 *
449 * \param required if true the function will panic if none are available
450 * \return the user IRQ number or -1 if required was false, and none were free
451 */
452 int user_irq_claim_unused(bool required);
453
454 /*
455 *! \brief Check if a user IRQ is in use on the calling core
456 * \ingroup hardware_irq
457 *
458 * User IRQs starting from FIRST_USER_IRQ are not connected to any hardware, but can be triggered by \ref irq_set_pending.
459 *
460 * \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therefore all functions
461 * dealing with Uer IRQs affect only the calling core
462 *
463 * \param irq_num the irq irq_num
464 * \return true if the irq_num is claimed, false otherwise
465 * \sa user_irq_claim
466 * \sa user_irq_unclaim
467 * \sa user_irq_claim_unused
468 */
469 bool user_irq_is_claimed(uint irq_num);
470
471 void __unhandled_user_irq(void);
472
473 #ifdef __riscv
474 enum riscv_vector_num {
475 RISCV_VEC_MACHINE_EXCEPTION = 0,
476 RISCV_VEC_MACHINE_SOFTWARE_IRQ = 3,
477 RISCV_VEC_MACHINE_TIMER_IRQ = 7,
478 RISCV_VEC_MACHINE_EXTERNAL_IRQ = 11,
479 };
480
481 irq_handler_t irq_set_riscv_vector_handler(enum riscv_vector_num index, irq_handler_t handler);
482 #endif
483
484 #if PICO_SECURE
irq_assign_to_ns(uint irq_num,bool ns)485 static inline void irq_assign_to_ns(uint irq_num, bool ns) {
486 check_irq_param(irq_num);
487 if (ns) nvic_hw->itns[irq_num >> 5] |= 1u << (irq_num & 0x1fu);
488 else nvic_hw->itns[irq_num >> 5] &= ~(1u << (irq_num & 0x1fu));
489 }
490 #endif
491 #ifdef __cplusplus
492 }
493 #endif
494
495 #endif
496 #endif
497