Add new user_irq claim APIs to make it easier for independent code using them to interoperate (#854)

This commit is contained in:
Graham Sanderson
2022-06-07 14:27:38 -05:00
committed by GitHub
parent f3c446ae14
commit d3dcbb8292
5 changed files with 112 additions and 6 deletions

View File

@ -289,6 +289,69 @@ void irq_set_pending(uint num);
* \note This is an internal method and user should generally not call it.
*/
void irq_init_priorities(void);
/*! \brief Claim ownership of a user IRQ on the calling core
* \ingroup hardware_irq
*
* User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
*
* \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
* dealing with Uer IRQs affect only the calling core
*
* This method explicitly claims ownership of a user IRQ, so other code can know it is being used.
*
* \param irq_num the user IRQ to claim
*/
void user_irq_claim(uint irq_num);
/*! \brief Mark a user IRQ as no longer used on the calling core
* \ingroup hardware_irq
*
* User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
*
* \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
* dealing with Uer IRQs affect only the calling core
*
* This method explicitly releases ownership of a user IRQ, so other code can know it is free to use.
*
* \note it is customary to have disabled the irq and removed the handler prior to calling this method.
*
* \param irq_num the irq irq_num to unclaim
*/
void user_irq_unclaim(uint irq_num);
/*! \brief Claim ownership of a free user IRQ on the calling core
* \ingroup hardware_irq
*
* User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
*
* \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
* dealing with Uer IRQs affect only the calling core
*
* This method explicitly claims ownership of an unused user IRQ if there is one, so other code can know it is being used.
*
* \param required if true the function will panic if none are available
* \return the user IRQ number or -1 if required was false, and none were free
*/
int user_irq_claim_unused(bool required);
/*
*! \brief Check if a user IRQ is in use on the calling core
* \ingroup hardware_irq
*
* User IRQs are numbered 26-31 and are not connected to any hardware, but can be triggered by \ref irq_set_pending.
*
* \note User IRQs are a core local feature; they cannot be used to communicate between cores. Therfore all functions
* dealing with Uer IRQs affect only the calling core
*
* \param irq_num the irq irq_num
* \return true if the irq_num is claimed, false otherwise
* \sa user_irq_claim
* \sa user_irq_unclaim
* \sa user_irq_claim_unused
*/
bool user_irq_is_claimed(uint irq_num);
#ifdef __cplusplus
}
#endif

View File

@ -8,12 +8,15 @@
#include "hardware/regs/m0plus.h"
#include "hardware/platform_defs.h"
#include "hardware/structs/scb.h"
#include "hardware/claim.h"
#include "pico/mutex.h"
#include "pico/assert.h"
extern void __unhandled_user_irq(void);
static uint8_t user_irq_claimed[NUM_CORES];
static inline irq_handler_t *get_vtable(void) {
return (irq_handler_t *) scb_hw->vtor;
}
@ -410,3 +413,31 @@ void irq_init_priorities() {
}
#endif
}
#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
static uint get_user_irq_claim_index(uint irq_num) {
invalid_params_if(IRQ, irq_num < FIRST_USER_IRQ || irq_num >= NUM_IRQS);
// we count backwards from the last, to match the existing hard coded uses of user IRQs in the SDK which were previously using 31
static_assert(NUM_IRQS - FIRST_USER_IRQ <= 8, ""); // we only use a single byte's worth of claim bits today.
return NUM_IRQS - irq_num - 1u;
}
void user_irq_claim(uint irq_num) {
hw_claim_or_assert(&user_irq_claimed[get_core_num()], get_user_irq_claim_index(irq_num), "User IRQ is already claimed");
}
void user_irq_unclaim(uint irq_num) {
hw_claim_clear(&user_irq_claimed[get_core_num()], get_user_irq_claim_index(irq_num));
}
int user_irq_claim_unused(bool required) {
int bit = hw_claim_unused_from_range(&user_irq_claimed[get_core_num()], required, 0, NUM_USER_IRQS - 1, "No user IRQs are available");
if (bit >= 0) bit = (int)NUM_IRQS - bit - 1;
return bit;
}
bool user_irq_is_claimed(uint irq_num) {
return hw_is_claimed(&user_irq_claimed[get_core_num()], get_user_irq_claim_index(irq_num));
}