Skip to content

Commit aaa7e72

Browse files
committed
arch: arm: cortex-m: Reduce ZLI latency by not disabling them in wrapper
The difference between __irq_disable() and irq_lock() is that the former essentially translates to `cpsid i`, whereas `irq_lock()` translates to setting BASEPRI (on cores with BASEPRI). This means that using irq_lock() does not disable zero-latency interrupts (ZLIs), which reduces the potential execution latency of ZLIs. In both isr_wrapper and _arch_isr_direct_pm() (which is just really an implementation of ISR_DIRECT_PM()), we were using __irq_disable() to disable all interrups, including ZLIs. But the code executed with interrupts disabled handles waking up from idle, and so must only be protected against regular interrupts being executed, not ZLIs, which should have no effect on the correct execution of the code. Signed-off-by: Carles Cufi <[email protected]>
1 parent 34f5f8d commit aaa7e72

File tree

2 files changed

+11
-27
lines changed

2 files changed

+11
-27
lines changed

arch/arm/core/cortex_m/irq_manage.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -132,33 +132,17 @@ void z_irq_spurious(const void *unused)
132132
#ifdef CONFIG_PM
133133
void _arch_isr_direct_pm(void)
134134
{
135-
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
136135
unsigned int key;
137136

138-
/* irq_lock() does what we want for this CPU */
137+
/* Disable all interrupts except ZLIs. */
139138
key = irq_lock();
140-
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
141-
/* Lock all interrupts. irq_lock() will on this CPU only disable those
142-
* lower than BASEPRI, which is not what we want. See comments in
143-
* arch/arm/core/cortex_m/isr_wrapper.c
144-
*/
145-
__asm__ volatile("cpsid i" : : : "memory");
146-
#else
147-
#error Unknown ARM architecture
148-
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
149139

150140
if (_kernel.idle) {
151141
_kernel.idle = 0;
152142
pm_system_resume();
153143
}
154144

155-
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
156145
irq_unlock(key);
157-
#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)
158-
__asm__ volatile("cpsie i" : : : "memory");
159-
#else
160-
#error Unknown ARM architecture
161-
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
162146
}
163147
#endif
164148

arch/arm/core/cortex_m/isr_wrapper.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,21 @@ void _isr_wrapper(void)
3838

3939
#ifdef CONFIG_PM
4040
/*
41-
* All interrupts are disabled when handling idle wakeup. For tickless
42-
* idle, this ensures that the calculation and programming of the
43-
* device for the next timer deadline is not interrupted. For
41+
* All non-ZLI interrupts are disabled when handling idle wakeup. For
42+
* tickless idle, this ensures that the calculation and programming of
43+
* the device for the next timer deadline is not interrupted. For
4444
* non-tickless idle, this ensures that the clearing of the kernel idle
45-
* state is not interrupted. In each case, pm_system_resume
46-
* is called with interrupts disabled.
45+
* state is not interrupted. In each case, pm_system_resume is called
46+
* with non-ZLI interrupts disabled.
4747
*/
4848

4949
/*
50-
* Disable interrupts to prevent nesting while exiting idle state. This
51-
* is only necessary for the Cortex-M because it is the only ARM
52-
* architecture variant that automatically enables interrupts when
50+
* Disable non-ZLI interrupts to prevent nesting while exiting idle
51+
* state. This is only necessary for the Cortex-M because it is the only
52+
* ARM architecture variant that automatically enables interrupts when
5353
* entering an ISR.
5454
*/
55-
__disable_irq();
55+
unsigned int key = irq_lock();
5656

5757
/* is this a wakeup from idle ? */
5858
/* requested idle duration, in ticks */
@@ -62,7 +62,7 @@ void _isr_wrapper(void)
6262
pm_system_resume();
6363
}
6464
/* re-enable interrupts */
65-
__enable_irq();
65+
irq_unlock(key);
6666
#endif /* CONFIG_PM */
6767

6868
#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER)

0 commit comments

Comments
 (0)