From 9f1c37318bbbc3f6b672db44115c0d34e29d09e7 Mon Sep 17 00:00:00 2001 From: Graham Sanderson Date: Tue, 12 Oct 2021 09:04:04 -0500 Subject: [PATCH] add irq_get_priority method - improve efficiency of irq_init_priorities (#609) --- .../hardware_irq/include/hardware/irq.h | 19 +++++++++++++++++++ src/rp2_common/hardware_irq/irq.c | 19 +++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/rp2_common/hardware_irq/include/hardware/irq.h b/src/rp2_common/hardware_irq/include/hardware/irq.h index 5ddf915..424a497 100644 --- a/src/rp2_common/hardware_irq/include/hardware/irq.h +++ b/src/rp2_common/hardware_irq/include/hardware/irq.h @@ -119,6 +119,10 @@ extern "C" { */ typedef void (*irq_handler_t)(void); +static inline void check_irq_param(__unused uint num) { + invalid_params_if(IRQ, num >= NUM_IRQS); +} + /*! \brief Set specified interrupt's priority * \ingroup hardware_irq * @@ -133,6 +137,21 @@ typedef void (*irq_handler_t)(void); */ void irq_set_priority(uint num, uint8_t hardware_priority); +/*! \brief Get specified interrupt's priority + * \ingroup hardware_irq + * + * Numerically-lower values indicate a higher priority. Hardware priorities + * range from 0 (highest priority) to 255 (lowest priority) though only the + * top 2 bits are significant on ARM Cortex-M0+. To make it easier to specify + * higher or lower priorities than the default, all IRQ priorities are + * initialized to PICO_DEFAULT_IRQ_PRIORITY by the SDK runtime at startup. + * PICO_DEFAULT_IRQ_PRIORITY defaults to 0x80 + * + * \param num Interrupt number + * \return the IRQ priority + */ +uint irq_get_priority(uint num); + /*! \brief Enable or disable a specific interrupt on the executing core * \ingroup hardware_irq * diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c index dc11668..2705e03 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -33,10 +33,6 @@ static void set_raw_irq_handler_and_unlock(uint num, irq_handler_t handler, uint spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_IRQ), save); } -static inline void check_irq_param(__unused uint num) { - invalid_params_if(IRQ, num >= NUM_IRQS); -} - void irq_set_enabled(uint num, bool enabled) { check_irq_param(num); irq_set_mask_enabled(1u << num, enabled); @@ -364,6 +360,14 @@ void irq_set_priority(uint num, uint8_t hardware_priority) { *p = (*p & ~(0xffu << (8 * (num & 3u)))) | (((uint32_t) hardware_priority) << (8 * (num & 3u))); } +uint irq_get_priority(uint num) { + check_irq_param(num); + + // note that only 32 bit reads are supported + io_rw_32 *p = (io_rw_32 *)((PPB_BASE + M0PLUS_NVIC_IPR0_OFFSET) + (num & ~3u)); + return (uint8_t)(*p >> (8 * (num & 3u))); +} + #if !PICO_DISABLE_SHARED_IRQ_HANDLERS // used by irq_handler_chain.S to remove the last link in a handler chain after it executes // note this must be called only with the last slot in a chain (and during the exception) @@ -400,8 +404,11 @@ void irq_add_tail_to_free_list(struct irq_handler_chain_slot *slot) { void irq_init_priorities() { #if PICO_DEFAULT_IRQ_PRIORITY != 0 - for (uint irq = 0; irq < NUM_IRQS; irq++) { - irq_set_priority(irq, PICO_DEFAULT_IRQ_PRIORITY); + static_assert(!(NUM_IRQS & 3), ""); + uint32_t prio4 = (PICO_DEFAULT_IRQ_PRIORITY & 0xff) * 0x1010101u; + io_rw_32 * p = (io_rw_32 *)(PPB_BASE + M0PLUS_NVIC_IPR0_OFFSET); + for (uint i = 0; i < NUM_IRQS / 4; i++) { + *p++ = prio4; } #endif }