ARM: rebase available priority levels to 0
We have a new policy: users should not be able to configure an interrupt with "forbidden" priority levels, and any priority levels with special semantics will be activated by flags. Change-Id: I757c19cfedcb1d0938eaf4da348ddafb71b3e001 Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
2b8673b571
commit
4455ee6d87
3 changed files with 49 additions and 15 deletions
|
@ -70,20 +70,42 @@ void irq_disable(unsigned int irq)
|
||||||
*
|
*
|
||||||
* @brief Set an interrupt's priority
|
* @brief Set an interrupt's priority
|
||||||
*
|
*
|
||||||
* Valid values are from 1 to 255. Interrupts of priority 1 are not masked when
|
* The priority is verified if ASSERT_ON is enabled. The maximum number
|
||||||
* interrupts are locked system-wide, so care must be taken when using them. ISR
|
* of priority levels is a little complex, as there are some hardware
|
||||||
* installed with priority 1 interrupts cannot make kernel calls.
|
* priority levels which are reserved: three for various types of exceptions,
|
||||||
*
|
* and possibly one additional to support zero latency interrupts.
|
||||||
* Priority 0 is reserved for kernel usage and cannot be used.
|
|
||||||
*
|
|
||||||
* The priority is verified if ASSERT_ON is enabled.
|
|
||||||
*
|
*
|
||||||
* @return N/A
|
* @return N/A
|
||||||
*/
|
*/
|
||||||
void _irq_priority_set(unsigned int irq,
|
void _irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
|
||||||
unsigned int prio)
|
|
||||||
{
|
{
|
||||||
__ASSERT(prio > 0 && prio < 256, "invalid priority!");
|
/* Hardware priority levels 0 and 1 reserved for Kernel use.
|
||||||
|
* So we add 2 to the requested priority level. If we support
|
||||||
|
* ZLI, 2 is also reserved so we add 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if CONFIG_ZERO_LATENCY_IRQS
|
||||||
|
#define IRQ_PRIORITY_OFFSET 3
|
||||||
|
/* If we have zero latency interrupts, that makes priority level 2
|
||||||
|
* a case with special semantics; it is not masked by irq_lock().
|
||||||
|
* Our policy is to express priority levels with special properties
|
||||||
|
* via flags
|
||||||
|
*/
|
||||||
|
if (flags | IRQ_ZERO_LATENCY) {
|
||||||
|
prio = 2;
|
||||||
|
} else {
|
||||||
|
prio += IRQ_PRIORITY_OFFSET;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define IRQ_PRIORITY_OFFSET 2
|
||||||
|
ARG_UNUSED(flags);
|
||||||
|
prio += IRQ_PRIORITY_OFFSET;
|
||||||
|
#endif
|
||||||
|
/* Last priority level reserved for PendSV exception */
|
||||||
|
__ASSERT(prio < ((1 << CONFIG_NUM_IRQ_PRIO_BITS) - 1),
|
||||||
|
"invalid priority %d! values must be less than %d\n",
|
||||||
|
prio - IRQ_PRIORITY_OFFSET,
|
||||||
|
(1 << CONFIG_NUM_IRQ_PRIO_BITS) - (IRQ_PRIORITY_OFFSET + 1));
|
||||||
_NvicIrqPrioSet(irq, _EXC_PRIO(prio));
|
_NvicIrqPrioSet(irq, _EXC_PRIO(prio));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +168,7 @@ int irq_connect_dynamic(unsigned int irq,
|
||||||
{
|
{
|
||||||
ARG_UNUSED(flags);
|
ARG_UNUSED(flags);
|
||||||
_irq_handler_set(irq, isr, arg);
|
_irq_handler_set(irq, isr, arg);
|
||||||
_irq_priority_set(irq, prio);
|
_irq_priority_set(irq, prio, flags);
|
||||||
return irq;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,19 @@ extern void _IntExit(void);
|
||||||
#define CONCAT(x, y) DO_CONCAT(x, y)
|
#define CONCAT(x, y) DO_CONCAT(x, y)
|
||||||
|
|
||||||
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
|
/* internal routine documented in C file, needed by IRQ_CONNECT() macro */
|
||||||
extern void _irq_priority_set(unsigned int irq, unsigned int prio);
|
extern void _irq_priority_set(unsigned int irq, unsigned int prio,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
|
|
||||||
|
/* Flags for use with IRQ_CONNECT() or irq_connect_dynamic() */
|
||||||
|
#if CONFIG_ZERO_LATENCY_IRQS
|
||||||
|
/**
|
||||||
|
* Set this interrupt up as a zero-latency IRQ. It has a fixed hardware
|
||||||
|
* priority level (discarding what was supplied in the interrupt's priority
|
||||||
|
* argument), and will run even if irq_lock() is active. Be careful!
|
||||||
|
*/
|
||||||
|
#define IRQ_ZERO_LATENCY (1 << 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,7 +97,7 @@ extern void _irq_priority_set(unsigned int irq, unsigned int prio);
|
||||||
* @param priority_p Interrupt priority
|
* @param priority_p Interrupt priority
|
||||||
* @param isr_p Interrupt service routine
|
* @param isr_p Interrupt service routine
|
||||||
* @param isr_param_p ISR parameter
|
* @param isr_param_p ISR parameter
|
||||||
* @param flags_p IRQ triggering options (currently unused)
|
* @param flags_p IRQ options
|
||||||
*
|
*
|
||||||
* @return The vector assigned to this interrupt
|
* @return The vector assigned to this interrupt
|
||||||
*/
|
*/
|
||||||
|
@ -96,7 +108,7 @@ extern void _irq_priority_set(unsigned int irq, unsigned int prio);
|
||||||
__attribute__ ((used)) \
|
__attribute__ ((used)) \
|
||||||
__attribute__ ((section(STRINGIFY(_CONCAT(.gnu.linkonce.isr_irq, irq_p))))) = \
|
__attribute__ ((section(STRINGIFY(_CONCAT(.gnu.linkonce.isr_irq, irq_p))))) = \
|
||||||
{isr_param_p, isr_p}; \
|
{isr_param_p, isr_p}; \
|
||||||
_irq_priority_set(irq_p, priority_p); \
|
_irq_priority_set(irq_p, priority_p, flags_p); \
|
||||||
irq_p; \
|
irq_p; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ void main(void)
|
||||||
|
|
||||||
for (int ii = 0; ii < 3; ii++) {
|
for (int ii = 0; ii < 3; ii++) {
|
||||||
irq_enable(ii);
|
irq_enable(ii);
|
||||||
_irq_priority_set(ii, _EXC_IRQ_DEFAULT_PRIO);
|
_irq_priority_set(ii, 0, 0);
|
||||||
nano_sem_init(&sem[ii]);
|
nano_sem_init(&sem[ii]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue