Add irq_has_handler() and use it to fix GPIO IRQ assert (#2277)

This commit is contained in:
Graham Sanderson 2025-02-17 16:07:27 -06:00 committed by GitHub
parent 59c9211589
commit 0ed224cf59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 7 deletions

View file

@ -184,12 +184,9 @@ static void _gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled, io_b
} }
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) { void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) {
// either this call disables the interrupt // either this call disables the interrupt or callback should already be set.
// or callback should already be set (raw or using gpio_set_irq_callback)
// this protects against enabling the interrupt without callback set // this protects against enabling the interrupt without callback set
assert(!enabled assert(!enabled || irq_has_handler(IO_IRQ_BANK0));
|| (raw_irq_mask[get_core_num()] & (1ull<<gpio))
|| callbacks[get_core_num()]);
// Separate mask/force/status per-core, so check which core called, and // Separate mask/force/status per-core, so check which core called, and
// set the relevant IRQ controls. // set the relevant IRQ controls.

View file

@ -403,9 +403,23 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
*/ */
void irq_remove_handler(uint num, irq_handler_t handler); void irq_remove_handler(uint num, irq_handler_t handler);
/*! \brief Determine if the current handler for the given number is shared /*! \brief Determine if there is an installed IRQ handler for the given interrupt number
* \ingroup hardware_irq * \ingroup hardware_irq
* *
* See \ref irq_set_exclusive_handler() for discussion on the scope of handlers
* when using both cores.
*
* \param num Interrupt number \ref interrupt_nums
* \return true if the specified IRQ has a handler
*/
bool irq_has_handler(uint num);
/*! \brief Determine if the current IRQ andler for the given interrupt number is shared
* \ingroup hardware_irq
*
* See \ref irq_set_exclusive_handler() for discussion on the scope of handlers
* when using both cores.
*
* \param num Interrupt number \ref interrupt_nums * \param num Interrupt number \ref interrupt_nums
* \return true if the specified IRQ has a shared handler * \return true if the specified IRQ has a shared handler
*/ */

View file

@ -197,10 +197,16 @@ static inline bool is_shared_irq_raw_handler(irq_handler_t raw_handler) {
return (uintptr_t)raw_handler - (uintptr_t)irq_handler_chain_slots < sizeof(irq_handler_chain_slots); return (uintptr_t)raw_handler - (uintptr_t)irq_handler_chain_slots < sizeof(irq_handler_chain_slots);
} }
bool irq_has_handler(uint irq_num) {
check_irq_param(irq_num);
irq_handler_t handler = irq_get_vtable_handler(irq_num);
return handler && handler != __unhandled_user_irq;
}
bool irq_has_shared_handler(uint irq_num) { bool irq_has_shared_handler(uint irq_num) {
check_irq_param(irq_num); check_irq_param(irq_num);
irq_handler_t handler = irq_get_vtable_handler(irq_num); irq_handler_t handler = irq_get_vtable_handler(irq_num);
return handler && is_shared_irq_raw_handler(handler); return is_shared_irq_raw_handler(handler);
} }
#else // PICO_DISABLE_SHARED_IRQ_HANDLERS #else // PICO_DISABLE_SHARED_IRQ_HANDLERS