# About the "configKERNEL INTERRUPT PRIORITY" value

**URL:** <https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937>\
**Category:** Kernel\
**Created:** [November 23, 2021, 10:09am UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937 "2021-11-23T10:09:05Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomstorey](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/tomstorey/32/1277_2.png) [@tomstorey](https://forums.freertos.org/u/tomstorey)\
**Post date:** [November 23, 2021, 10:09am UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/1 "2021-11-23T10:09:05Z")

</div>

(For some reason, configKERNEL\_INTERRUPT\_PRIORITY is considered too long a word to be in the title)

Hi all,

Sorry for the noise, but I am feeling really thick at the moment and struggling to get a grasp of something which seems to be documented everywhere and explained multiple times, but somehow is not getting through to me. Things have a habit of clicking with me when I try to explain my thoughts, so bear with me. 🙂

I have also read through this thread but still I dont seem to be getting it 🙄: [What is config KERNEL INTERRUPT PRIORITY?](https://forums.freertos.org/t/what-is-config-kernel-interrupt-priority/11501)

In my m68k port I have defined both configKERNEL\_INTERRUPT\_PRIORITY and configMAX\_API\_CALL\_INTERRUPT\_PRIORITY.

On the m68k, IPL 0 means “all interrupts are enabled”, but is not an IRQ level itself. The minimum IRQ is 1, so in my current project my tick interrupt is configured for IRQ 1 as it is recommended to be the lowest available IRQ level. ([c1600\_freertos\_tcp/FreeRTOSConfig.h at master · tomstorey/c1600\_freertos\_tcp · GitHub](https://github.com/tomstorey/c1600_freertos_tcp/blob/master/FreeRTOSConfig.h))

The problem is arising when I look at my implementation of portENABLE\_INTERRUPTS ([FreeRTOS-Kernel/portmacro.h at new\_task\_switch · tomstorey/FreeRTOS-Kernel · GitHub](https://github.com/tomstorey/FreeRTOS-Kernel/blob/new_task_switch/portable/GCC/m68k/portmacro.h#L71-L81)). My fuzzy understanding was that this should fully re-enable all interrupts, i.e. configure the IPL to 0. However, if I do this, I get a lot of crashes due to null pointers. Configuring IPL 1 is generally leaps and bounds more stable (although I still seem to be getting crashes due to null pointers for some reason right now… this has been very temperamental)

But it doesnt seem right to “re-enable” interrupts at a priority above 0? Surely if portDISABLE\_INTERRUPTS is setting the IPL to configMAX\_API\_CALL\_INTERRUPT\_PRIORITY to prevent API-calling ISRs from interrupting the kernel, then portENABLE\_INTERRUPTS should restore the IPL to 0 to re-enable all interrupts as the name suggests?

What am I missing?

Thanks!

---

<div class="post-metadata">

**Author:** ![RAc](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rac/32/1389_2.png) [@RAc](https://forums.freertos.org/u/RAc)\
**Post date:** [November 23, 2021, 11:49am UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/2 "2021-11-23T11:49:45Z")

</div>

> [@tomstorey](#):
>
> The minimum IRQ is 1, so in my current project my tick interrupt is configured for IRQ 1 as it is recommended to be the lowest available IRQ level. ([c1600\_freertos\_tcp/FreeRTOSConfig.h at master · tomstorey/c1600\_freertos\_tcp · GitHub](https://github.com/tomstorey/c1600_freertos_tcp/blob/master/FreeRTOSConfig.h))

Actually, in my understanding, the kernel interrupt priority must be lowest. This is because a context switch happens at kernel interrupt time, and in order to save a valid task context to which to switch back to orderly, the kernel interrupt must never interrupt ISRs, only tasks.

And yes, enabling interrupts will (must) also enable the kernel interrupt.

---

<div class="post-metadata">

**Author:** ![tomstorey](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/tomstorey/32/1277_2.png) [@tomstorey](https://forums.freertos.org/u/tomstorey)\
**Post date:** [November 23, 2021, 12:55pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/3 "2021-11-23T12:55:00Z")

</div>

Not quire sure I follow what you said there… To clarify, on the 68k, interrupt priority level 0 would permit IRQ1 plus all higher priority interrupts. My tick interrupt is at IRQ1 and the only peripherals I am using at present (Ethernet controller) are at IRQ2.

Raising the priority level to 1 would mask IRQ1, but still allow IRQ2 and above. And so forth until level 7 which cannot be masked and is effectively the NMI.

So in my ISRs (such as the tick interrupt, yield, and my peripherals) I raise the priority level to the value of configMAX\_API\_CALL\_INTERRUPT\_PRIORITY (4 in my project).

Is this what you were saying?

The problem is if I set the priority back to level 0 in portENABLE\_INTERRUPTS, which would seem like the logical thing to do, I very quickly get bus errors as some code within FreeRTOS tries to dereference a null pointer.

For example (I have no memory mapped at address 0, hence bus error):

```auto
Bus Error (08)

D0 0x00000002 D4 0x00000001 A0 0x00000000 A4 0x00000000 SR 0x2400 (EH 0x2700)
D1 0x00000000 D5 0xA5A5A5A5 A1 0x0220C21C A5 0x02230CA8 PC 0x02002F7A
D2 0x00000008 D6 0xA5A5A5A5 A2 0x02230CC8 FP 0x02230BFC USP 0x00000000
D3 0x02230CCC D7 0xA5A5A5A5 A3 0x00000015 SSP 0x02230B60

```

the code at the PC:

```auto
                    listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
 2002f5e: 206a 0014 moveal %a2@(20),%a0
 2002f62: 226a 0008 moveal %a2@(8),%a1
 2002f66: 236a 000c 0008 movel %a2@(12),%a1@(8)
 2002f6c: 226a 000c moveal %a2@(12),%a1
 2002f70: 236a 0008 0004 movel %a2@(8),%a1@(4)
 2002f76: 260a movel %a2,%d3
 2002f78: 5883 addql #4,%d3
 2002f7a: b6a8 0004 cmpl %a0@(4),%d3 <<<<<<<<<<<<<<

```

which is this line [FreeRTOS-Kernel/tasks.c at new\_task\_switch · tomstorey/FreeRTOS-Kernel · GitHub](https://github.com/tomstorey/FreeRTOS-Kernel/blob/new_task_switch/tasks.c#L5084)

The A2 register would appear to correspond with the `TaskHandle_t xTaskToNotify parameter` of xTaskGenericNotifyFromISR which becomes the pxTCB variable.

If, instead of changing the IPL to 0 I change it to 1 instead, I am far less likely to crash, and it would be up to a context restore to set IPL to 0 at the end of a task switch.

Its really confusing behaviour, and the bus errors arent even consistent. Last night I ran for 10+ minutes without a crash (1.1 million pings responded to with only 2 drops, I only stopped it to see how many packets had been sent), today I’d be lucky to get a couple of seconds worth of pings through before a crash. 😕

---

<div class="post-metadata">

**Author:** ![RAc](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rac/32/1389_2.png) [@RAc](https://forums.freertos.org/u/RAc)\
**Post date:** [November 23, 2021, 1:04pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/4 "2021-11-23T13:04:53Z")

</div>

Don’t try to look too close at the immediate fault cause. In an RTOS, typically the code that caused that problem took place long before something else crashes.

I’m not familiar with the 68k port (though I coded for the 68332 and a ColdFire POD many many years).

What I’m interested in is the context switching mechanism. Normally this goes through a software interrupt. Which one is that and what priority is that one assigned to?

Coincidentally, the only issue I ever created in this forum actually dealt with an 68k derivate (ColdFire). Maybe some of the info in there is useful to you (the fault cause actually was exactly that - a problem in the context switch interrupt priority):

> [@Problem with array bounds for pxReadyTasksLists (FreeRTOS 8.2.x)](https://forums.freertos.org/t/problem-with-array-bounds-for-pxreadytaskslists-freertos-8-2-x/12009):
>
> Hi there, pxReadyTasksLists is an array bound by configMAX\_PRIORITIES. There are cases in which uxTopReadyPriority (which is used as an index into pxReadyTasksLists) exceeds configMAX\_PRIORITIES, causing taskSELECT\_HIGHEST\_PRIORITY\_TASK to accessing undefined memory. The control path is this (configUSE\_PORT\_OPTIMISED\_TASK\_SELECTION set)\*: #define taskSELECT\_HIGHEST\_PRIORITY\_TASK() \ { \ UBaseType\_t uxTopPriority; \ /\* Find the highest priority queue that contains ready…

---

<div class="post-metadata">

**Author:** ![tomstorey](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/tomstorey/32/1277_2.png) [@tomstorey](https://forums.freertos.org/u/tomstorey)\
**Post date:** [November 23, 2021, 1:38pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/5 "2021-11-23T13:38:42Z")

</div>

ColdFire and 68k are somewhat similar as I understand it. I am using a 68k port that I created myself, with some inspiration from the supplied ColdFire port and others.

There is no software interrupt mechanism on the CPU I am using I believe (68EN360, a bigger brother of the 68332 I believe - it uses a CPU32 core but that is also quite similar, moreso to a 68020 as I recall), so I am using trap #15 to do a yield.

Task switch code is here for a yield: [FreeRTOS-Kernel/portasm.S at new\_task\_switch · tomstorey/FreeRTOS-Kernel · GitHub](https://github.com/tomstorey/FreeRTOS-Kernel/blob/new_task_switch/portable/GCC/m68k/portasm.S#L31-L52)

That is callable via: [FreeRTOS-Kernel/portmacro.h at new\_task\_switch · tomstorey/FreeRTOS-Kernel · GitHub](https://github.com/tomstorey/FreeRTOS-Kernel/blob/new_task_switch/portable/GCC/m68k/portmacro.h#L90-L93)

And here is my projects tick interrupt which is using a timer that is configured to generate interrupts at IRQ1: [c1600\_freertos\_tcp/PITInterruptHandler.S at master · tomstorey/c1600\_freertos\_tcp · GitHub](https://github.com/tomstorey/c1600_freertos_tcp/blob/master/PITInterruptHandler.S)

Timer setup code: [c1600\_freertos\_tcp/main.c at master · tomstorey/c1600\_freertos\_tcp · GitHub](https://github.com/tomstorey/c1600_freertos_tcp/blob/master/main.c#L17-L26)

I guess the problem with doing a yield is that it happens at what ever IPL the code that calls it is running in, since it isnt possible to perform a trap at a specified IPL (that I know of). So I raise it myself in the trap handler, and the RTE instruction at the end will restore the previous IPL.

I almost had a thought that maybe IRQs were only masked below the IPL, but the datasheet confirms it is _at and below_ the IPL. So e.g. IPL4 means IRQ1-4 are masked, 5-7 can still happen.

Thanks for lending an ear. 🙂

---

<div class="post-metadata">

**Author:** ![RAc](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rac/32/1389_2.png) [@RAc](https://forums.freertos.org/u/RAc)\
**Post date:** [November 23, 2021, 1:47pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/6 "2021-11-23T13:47:09Z")

</div>

well, a TRAP IS a software interrupt handler. There must also be an entry in your IVT for trap 15, and it is subject to masking.

I don’t remember what the priority and masking rules for your POD is, but if the priority of your TRAP handler is not the lowest interrupt priority, it may well explain your problems.

EDIT: I just checked with the 68332 Reference Manual, which of course may differ in details from your POD, but the basic operation should be compatible. The TRAP vectors are in locations 32-47 of your IVT, and it seems as if all traps have a higher priority than all interrupts, which in my understanding is not FreeRTOS architecture compliant. You should try rewriting your context switch architecture.

Editedit: Maybe this here link provides more useful info:, even if it already quite old: [trap instruction for taskYIELD](https://forums.freertos.org/t/trap-instruction-for-taskyield/4819)

---

<div class="post-metadata">

**Author:** ![tomstorey](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/tomstorey/32/1277_2.png) [@tomstorey](https://forums.freertos.org/u/tomstorey)\
**Post date:** [November 23, 2021, 2:07pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/7 "2021-11-23T14:07:45Z")

</div>

The traps dont have any assignable priority and cant be masked - they just execute “in-line” with the current executing code.

That is to say, if I want to cause an interrupt that will be deferred and run after the current code completes and drops back to a lower IPL, that isnt possible with a trap. You call the trap and it runs immediately.

There is indeed an entry in the IVT for my trap #15 handler, and it does work like this - I have 5 tasks that run and blink some LEDs, and they are definitely running.

The issue is under load I suppose, when I ping flood the device, this consumes quite a substantial amount of CPU as can be evidenced when the blinking LEDs slow to a crawl. And maybe something is out of whack between interrupts at that time.

Im having an idea that perhaps a task switch needs to be a bit more tightly coupled with enabling/disabling interrupts…

Say I call trap #15 and the IPL == the API priority, I set a flag somewhere to say a task switch is required, and then exit the trap handler without effecting a task switch.

Then in something like portENABLE\_INTERRUPTS I check this flag, and if it is set - after lowering the IPL - then I execute a task switch.

That then kind of emulates the deferred interrupt behaviour. Does that sound reasonable?

I dont know if FreeRTOS requires that a task switch doesnt happen in the middle of a critical section, but this sounds like it would prevent that from happening.

---

<div class="post-metadata">

**Author:** ![RAc](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rac/32/1389_2.png) [@RAc](https://forums.freertos.org/u/RAc)\
**Post date:** [November 23, 2021, 2:12pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/8 "2021-11-23T14:12:54Z")

</div>

ok, just make sure to observe Richard’s advice in his last post in the thread I added in my most recent response - if nested critical sections are required, make sure to record the most recent mask when reentering masking so your crit section management is fully “unwinding at the right levels.”

---

<div class="post-metadata">

**Author:** ![tomstorey](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/tomstorey/32/1277_2.png) [@tomstorey](https://forums.freertos.org/u/tomstorey)\
**Post date:** [November 23, 2021, 2:21pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/9 "2021-11-23T14:21:31Z")

</div>

A trap instruction will push the status register (which holds the IPL) onto the stack along with the return address, and an RTE (return from exception) then pops that status register value back (thus restoring any previous IPL and flags), so it kind of nicely keeps track of CPU state.

As for nesting critical sections, the existing port functions (`vPortEnterCritical` and `vPortExitCritical`) do not seem to record the current IPL, instead just enable or disable according to the API and kernel IPL values in your config file while keeping track of what to do with a counter (i.e. only re-enable once the counter hits 0).

There are two macros (`portSET_INTERRUPT_MASK_FROM_ISR` and `portCLEAR_INTERRUPT_MASK_FROM_ISR`) that call `ulPortSetIPL` which allows the current IPL to be exchanged, so I suppose in a situation where it needs to be maintained, that is used instead.

Soooo, if I understand everything correctly, then the IPL should be maintained appropriately as long as the correct combinations of macros were used.

Only one way to find out though I guess. 🙂

---

<div class="post-metadata">

**Author:** ![tomstorey](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/tomstorey/32/1277_2.png) [@tomstorey](https://forums.freertos.org/u/tomstorey)\
**Post date:** [November 23, 2021, 3:15pm UTC](https://forums.freertos.org/t/about-the-configkernel-interrupt-priority-value/13937/10 "2021-11-23T15:15:16Z")

</div>

Holy balls what a difference that made! 🤩

The LED blinking tasks are actually managing to run at a half reasonable rate as well.

I guess that was it, or at least a significant part of it.

No bus errors so far either, so fingers crossed…

Changes for reference: [Major improvement to task switching · tomstorey/FreeRTOS-Kernel@c04a7db · GitHub](https://github.com/tomstorey/FreeRTOS-Kernel/commit/c04a7db8b500dc6501877b14d3542c4eabb75957?diff=split)

Many thanks for your input and guidance @RAc !
