NVIC_SetPriority
I was using your CTL library which provided the following function to set an IRQ priority:
void ctl_set_priority(int irq, int priority)
{
NVIC_SetPriority(irq, (1 << (__NVIC_PRIO_BITS - 1)) + priority);
}
In researching the actual function NVIC_SetPriority on the web I found many sources that states your implementation is incorrect.
Here is one such link: http://embeddedgurus.com/state-space/2014/02/cutting-through-the-confusion-with-arm-cortex-m-interrupt-priorities/
The following is the most important information as it states the bits SHOULD NOT be shifted as you do in your function ctl_set_priority.
Is your implementation correct or is it in error as stated by the information below.
Thanks
Joe
Interrupt Priority Numbering in the CMSIS
The Cortex Microcontroller Software Interface Standard (CMSIS) provided by ARM Ltd. is the recommended way of way of programming Cortex-M microcontrollers the in a portable way. The CMSIS standard provides the function NVIC_SetPriority(IRQn, priority) for setting the interrupts priorities.
However, it is very important to note that the ‘priority‘ argument of this function must not be shifted by the number of unimplemented bits, because the function performs the shifting by (8 – __NVIC_PRIO_BITS) internally, before writing the value to the appropriate priority configuration register in the NVIC. The number of implemented priority bits __NVIC_PRIO_BITS is defined in CMSIS for each ARM Cortex-M device.
For example, calling NVIC_SetPriority(7, 6) will set the priority configuration register corresponding to IRQ#7 to 1100,0000 binary on ARM Cortex-M with 3-bits of interrupt priority and it will set the same register to 0110,0000 binary on ARM Cortex-M with 4-bits of priority.
NOTE: The confusion about the priority numbering scheme used in the NVIC_SetPriority() is further promulgated by various code examples on the Internet and even in reputable books. For example the book “The Definitive Guide to ARM Cortex-M3, Second Edition”, ISBN 979-0-12-382091-4, Section 8.3 on page 138 includes a call NVIC_SetPriority(7, 0xC0) with the intent to set priority of IR#7 to 6. This call is incorrect and at least in CMSIS version 3.x will set the priority of IR#7 to zero.
-
I believe Crosswork's CTL implementation of ctl_set_priority(..) is wrong.
As a test example ... Use a Cortex M4 that has (__NVIC_PRIO_BITS equal to 4.
The call to set irq 24 to priority 6 using the CTL would be ctl_set_priority(24, 6).
Expanding into the CTL function as shown above ...
void ctl_set_priority(int irq, int priority)
{
NVIC_SetPriority(irq, (1 << (__NVIC_PRIO_BITS - 1)) + priority);
}1 << (__NVIC_PRIO_BITS - 1) equals 0x08 so the parameters being passed to the function NVIC_SetPriority would be the irq value of 24 and the priority value of 0x08 + 0x06 which equals 14 or 0x0e.
The following is from the Crosswork's V3 packages ....
/** \brief Set Interrupt Priority The function sets the priority of an interrupt. \note The priority cannot be set for every core interrupt. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. */ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { if((int32_t)IRQn < 0) { SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } }
So the inline function being called is ...NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
(priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL is expanded ...
0x0e << (8 - 4) === 0x0e << 4 === 0xe0
In this example, the CTL code is setting the priority to a value of 14 when the request was to set it to a value of 6.
Again -- the Crosswork's implementation of void ctl_set_priority(int irq, int priority) appears to be in error.
If my analysis is correct -- the proper implementation should be
void ctl_set_priority(int irq, int priority)
{
NVIC_SetPriority(irq, priority);
}
Thanks.
Joe -
For cortex-m3/4/7 ctl priority interrupts have to be in the lowest half of the priority range. On a device with 4 priority bits priorities 8-15 are ctl interrupts, with PendSV set to the lowest 15. The highest priority interrupts 0-7 can be used for interrupts that don't require ctl. The ctl functions are trying to help with this.
-
I do not remember any documentation that states the CTL set_priority function was taking the requested priority number and moving it into the priority range for the CTL.
I say that because if I'm using the CTL but want to set an irq priority to 6 (actual 6 - not the CTL version of 6) ... I need to use the NVIC priority function NOT the CTL version .... again --- I don't remember seeing documentation stating that as a requirement.
If it is stated somewhere -- sorry for bring up the question.
Joe
Please sign in to leave a comment.
Comments
4 comments