Intuition What this page is
The parent note gave you the models. Here we exercise every corner of those models — every priority relationship, the zero-cases, the limiting cases, a real-world word problem, and an exam twist. If a scenario can happen on a Cortex-M, it appears below.
Before any numbers, let us list every kind of situation these formulas must survive. Each row is one case class ; the worked examples below are tagged with the row they hit.
#
Case class
The question it answers
Degenerate / edge form
A
Priority split (2 p , 2 N − p )
How many preempt vs sub levels?
p = 0 (no preemption) and p = N (no sub-levels)
B
Preemption decision
Does IRQ-X interrupt running IRQ-Y?
Equal preempt → no preemption
C
Sub-priority tiebreak
Two pending at once, equal preempt — who runs first?
Equal sub too → lower IRQ number wins
D
Latency, normal
Time to first ISR instruction
Event fires while IRQs masked (worst case)
E
Latency, tail-chaining
Back-to-back IRQs, cost saved
Limiting case: many queued IRQs
F
Deadline / real-world
Do we drop a UART byte?
Zero slack (exactly meets)
G
Exam twist
Combine grouping + latency + a trap
"higher number = more urgent" trap
The formulas we lean on, restated so no symbol is unearned:
A1 (normal split). STM32F4 implements N = 4 priority bits. PRIGROUP gives p = 2 preempt bits. How many preempt levels and sub levels?
Forecast: guess both numbers before reading — they must multiply back to 2 4 = 16 .
Preempt levels = 2 p = 2 2 = 4 . Why this step? p bits encode 2 p distinct groups; 2 bits → patterns 00 , 01 , 10 , 11 → 4 groups.
Sub levels = 2 N − p = 2 4 − 2 = 2 2 = 4 . Why? the leftover N − p = 2 bits are the tiebreaker field, encoding 2 2 = 4 slots.
Sanity product: 4 × 4 = 16 = 2 4 . Why? the split must neither create nor destroy total levels.
Verify: 2 2 ⋅ 2 2 = 16 = 2 4 ✔ and both ≥ 1 , so the config is legal.
A2 (degenerate p = 0 : NO preemption possible). Same chip N = 4 , but PRIGROUP set so all 4 bits are sub-priority (p = 0 ).
Forecast: how many things can preempt a running ISR now?
Preempt levels = 2 0 = 1 . Why? zero preempt bits → a single group; everyone shares it.
Sub levels = 2 4 − 0 = 2 4 = 16 . Why? all 16 encodings become tiebreakers.
Consequence: since there is only one preempt group, no interrupt can ever preempt another — once an ISR starts, it runs to completion. Ordering only decides who runs first among simultaneously pending IRQs.
Verify: 1 × 16 = 16 ✔. Edge behaviour confirmed: preempt levels = 1 ⇒ fully non-nested system.
A3 (degenerate p = N : NO sub-priority, all preemption). N = 4 , p = 4 .
Preempt levels = 2 4 = 16 , sub levels = 2 0 = 1 .
Meaning: every priority difference causes preemption; there is no "runs-first-but-can't-preempt" tie mechanism. Ties (identical priority) fall back to the fixed rule: lower IRQ number wins .
Verify: 16 × 1 = 16 ✔.
Remember the golden trap: lower numeric priority = more urgent . We test every ordering.
B1 (strict preemption). Config p = 3 , N = 4 (8 preempt groups, 2 sub). IRQ-A: preempt= 1 . IRQ-B: preempt= 2 , currently running. A fires mid-B. What happens?
Forecast: does A wait, or cut in?
Compare preempt numbers: 1 < 2 . Why compare these? preemption is decided only by the preempt field.
Lower number = more urgent ⇒ A preempts B. B is stacked (its context auto-saved), A runs, then B resumes.
Verify: ordering respected: after A finishes, B continues from its saved P C — no work lost. Correct because 1 < 2 and lower=urgent.
C1 (equal preempt, sub tiebreak — NO preemption). IRQ-C: preempt= 2 , sub= 0 . IRQ-D: preempt= 2 , sub= 1 . Both pending at the same instant , nothing running yet.
Forecast: who runs first, and does either preempt the other?
Preempt fields equal (2 = 2 ) ⇒ neither preempts the other . Why? preemption needs a strictly lower preempt number.
Tie broken by sub-priority: 0 < 1 ⇒ C first , then D. Why? sub-priority only orders simultaneously pending IRQs.
If C were already running and D became pending, D would wait for C to finish (no preemption).
Verify: run order C→D; and crucially D never interrupts C. Consistent with "sub-priority never causes preemption."
C2 (full tie — the very last fallback). IRQ-E and IRQ-F: identical preempt= 2 , identical sub= 1 , both pending. E is exception/IRQ number 30, F is number 12.
Preempt equal, sub equal ⇒ hardware uses the fixed tiebreak: lower IRQ number wins .
12 < 30 ⇒ F runs first .
Verify: deterministic — the NVIC always resolves a full tie by IRQ number, so behaviour is reproducible.
D1 (worst-case latency with a critical section). f clk = 100 MHz . Fixed hardware part = 12 cycles. Your longest __disable_irq() critical section lasts 50 cycles. Event fires just after you masked. Find worst-case latency in ns.
Forecast: it is not just 12 cycles — guess the ns figure.
One cycle = 1/ ( 100 × 1 0 6 ) = 10 ns . Why? we asserted a numeric answer in ns, so convert cycles→time.
t blocked = 50 cycles: the event must wait the whole masked window before stacking even starts. Why add it? while masked, the NVIC holds the request pending — no stacking.
Total cycles = t blocked + hardware = 50 + 12 = 62 .
t lat,worst = 62 × 10 ns = 620 ns .
Verify: units: cycles × (ns/cycle) = ns ✔. Numeric: 620 ns = 0.62 μ s , plausible for a 100 MHz MCU.
D2 (best-case, nothing masked). Same chip, no critical section active, event fires while executing a 1-cycle instruction. t blocked = 0 , t finish-instr ≈ 1 cycle.
Total = 12 + 1 = 13 cycles (the 12 already folds in detect/stack/vector; we add the finish-instruction slack).
= 13 × 10 = 130 ns .
Verify: best-case < worst-case: 130 < 620 ✔.
E1 (two back-to-back IRQs). IRQ-B then IRQ-C both pending, B finishing. Naive cost: unstack B (≈ 12 ) + stack C (≈ 12 ). Tail-chaining replaces this with ≈ 6 cycles. How many cycles saved, and what fraction?
Forecast: guess the saving before computing.
Naive transition cost = 12 + 12 = 24 cycles. Why? popping 8 words then pushing 8 words.
Tail-chained cost = 6 cycles. Why it works: the stacked context is still valid, so hardware skips pop-then-push and jumps B→C directly.
Saved = 24 − 6 = 18 cycles = 18 × 10 = 180 ns .
Fraction saved = 18/24 = 0.75 = 75% .
Verify: 6 + 18 = 24 ✔; 0.75 is between 0 and 1 ✔.
E2 (limiting case — a burst of k IRQs). k = 5 IRQs queued back-to-back. Compare total transition overhead naive vs tail-chained (entry costs only).
Naive: first entry 12 , then between each pair unstack+stack = 24 . For 5 IRQs there are 4 gaps: 12 + 4 × 24 = 12 + 96 = 108 cycles.
Tail-chained: first entry 12 , then each of the 4 chains costs 6 : 12 + 4 × 6 = 12 + 24 = 36 cycles.
Saving = 108 − 36 = 72 cycles = 720 ns .
Verify: with more queued IRQs the saving grows linearly (18 cycles per gap) — the whole point of tail-chaining under load. 72 = 4 × 18 ✔.
F1 (UART at risk). A UART receives bytes at 115200 baud , 8N1 framing (10 bits per byte). Its RX interrupt must be serviced before the next byte overwrites the register. Your worst-case latency (from D1) is 620 ns , and the ISR itself takes 200 ns . Do you drop bytes?
Forecast: guess YES or NO before computing the byte period.
Time per byte = 115200 bits/s 10 bits = 8.68 × 1 0 − 5 s = 86.8 μ s . Why 10 bits? 8N1 = 1 start + 8 data + 1 stop bit.
Time budget to service one byte = one byte period = 86.8 μ s .
Worst service time = t lat,worst + t ISR = 620 + 200 = 820 ns = 0.82 μ s .
Slack = 86.8 − 0.82 = 85.98 μ s > 0 ⇒ no dropped bytes , with huge margin.
Verify: 0.82 ≪ 86.8 ✔; ratio 0.82/86.8 ≈ 0.94% CPU used per byte — comfortably meets the deadline. This is exactly why a short ISR + ring buffer (see Ring Buffers / FIFO Queues ) keeps deadlines safe.
F2 (zero-slack / tightened case). Same UART but baud raised to 1 Mbaud and worst latency ballooned to 80 μ s by a careless long critical section. Now?
Byte period = 10/1 000 000 = 10 μ s .
Service time = 80 + ? — already 80 μ s > 10 μ s before the ISR even runs.
Slack = 10 − 80 = − 70 μ s < 0 ⇒ bytes dropped . This is the race that a fat critical section creates.
Verify: negative slack ⇒ deadline miss. Fix: shrink the critical section (lower t blocked ) — the single most effective latency lever.
G1 (combined trap question). "IRQ-P has priority number 0 , IRQ-Q has priority number 5 . A student says 'Q is more important because 5 > 0.' Config N = 4 , p = 4 (all preempt). Q is running; P becomes pending. (a) Who is really more urgent? (b) Does P preempt Q? (c) If f clk = 100 MHz and P's stacking is the 12-cycle hardware part with no masking, when does P's first instruction run?"
Forecast: spot the trap in the student's claim before step 1.
(a) On Cortex-M, lower number = higher urgency , so P (0) is more urgent than Q (5). The student's "5>0" reasoning is the classic inverted-scale mistake.
(b) p = 4 ⇒ all bits are preempt, sub levels = 2 0 = 1 . Preempt numbers 0 < 5 ⇒ P preempts Q . Q is stacked, resumes after P.
(c) No masking, hardware part = 12 cycles, = 12 × 10 = 120 ns to P's first instruction (Q's current instruction assumed already at an interruptible point).
Verify: P first instr at 120 ns ; 0 < 5 confirms P urgent and preempting. Trap correctly rejected.
Recall Self-test — reveal after answering
With N = 4 , p = 0 , how many things can preempt a running ISR? ::: Preempt levels = 2 0 = 1 , so none — fully non-nested.
Two IRQs equal preempt, equal sub, numbers 12 and 30 — who runs first? ::: IRQ 12 (lower IRQ number is the final tiebreak).
Worst-case latency at 100 MHz with 12 fixed + 50 masked cycles? ::: 62 × 10 ns = 620 ns .
Tail-chaining saving for one B→C transition (24 naive vs 6)? ::: 18 cycles = 180 ns (75% ).
One byte time at 115200 baud, 8N1? ::: 10/115200 ≈ 86.8 μ s .
Mnemonic Two things to never invert
"Low number, high stakes; equal preempt, no cut-in." Lower priority number = more urgent, and equal-preempt IRQs order but never preempt .