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
|
||||
*
|
||||
* Valid values are from 1 to 255. Interrupts of priority 1 are not masked when
|
||||
* interrupts are locked system-wide, so care must be taken when using them. ISR
|
||||
* installed with priority 1 interrupts cannot make kernel calls.
|
||||
*
|
||||
* Priority 0 is reserved for kernel usage and cannot be used.
|
||||
*
|
||||
* The priority is verified if ASSERT_ON is enabled.
|
||||
* The priority is verified if ASSERT_ON is enabled. The maximum number
|
||||
* of priority levels is a little complex, as there are some hardware
|
||||
* priority levels which are reserved: three for various types of exceptions,
|
||||
* and possibly one additional to support zero latency interrupts.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void _irq_priority_set(unsigned int irq,
|
||||
unsigned int prio)
|
||||
void _irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
|
||||
{
|
||||
__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));
|
||||
}
|
||||
|
||||
|
@ -146,7 +168,7 @@ int irq_connect_dynamic(unsigned int irq,
|
|||
{
|
||||
ARG_UNUSED(flags);
|
||||
_irq_handler_set(irq, isr, arg);
|
||||
_irq_priority_set(irq, prio);
|
||||
_irq_priority_set(irq, prio, flags);
|
||||
return irq;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,19 @@ extern void _IntExit(void);
|
|||
#define CONCAT(x, y) DO_CONCAT(x, y)
|
||||
|
||||
/* 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 isr_p Interrupt service routine
|
||||
* @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
|
||||
*/
|
||||
|
@ -96,7 +108,7 @@ extern void _irq_priority_set(unsigned int irq, unsigned int prio);
|
|||
__attribute__ ((used)) \
|
||||
__attribute__ ((section(STRINGIFY(_CONCAT(.gnu.linkonce.isr_irq, irq_p))))) = \
|
||||
{isr_param_p, isr_p}; \
|
||||
_irq_priority_set(irq_p, priority_p); \
|
||||
_irq_priority_set(irq_p, priority_p, flags_p); \
|
||||
irq_p; \
|
||||
})
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ void main(void)
|
|||
|
||||
for (int ii = 0; ii < 3; ii++) {
|
||||
irq_enable(ii);
|
||||
_irq_priority_set(ii, _EXC_IRQ_DEFAULT_PRIO);
|
||||
_irq_priority_set(ii, 0, 0);
|
||||
nano_sem_init(&sem[ii]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue