[rtems commit] arm: Fix ARMv7-M interrupt processing
Sebastian Huber
sebh at rtems.org
Tue Jul 4 13:15:54 UTC 2017
Module: rtems
Branch: master
Commit: 3e7827434d3dd0b59a7d49798facd7bba0a73e23
Changeset: http://git.rtems.org/rtems/commit/?id=3e7827434d3dd0b59a7d49798facd7bba0a73e23
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Tue Jul 4 14:15:03 2017 +0200
arm: Fix ARMv7-M interrupt processing
Right after a "msr basepri_max, %[basepri]" instruction an interrupt
service may still take place (observed at least on Cortex-M7). However,
pendable service calls that are activated during this interrupt service
may be delayed until interrupts are enable again. The
_ARMV7M_Pendable_service_call() did not check that a thread dispatch is
allowed. Move this test from _ARMV7M_Interrupt_service_leave() to
_ARMV7M_Pendable_service_call().
Update #3060.
---
cpukit/score/cpu/arm/armv7m-isr-dispatch.c | 50 +++++++++++++++++----------
cpukit/score/cpu/arm/armv7m-isr-enter-leave.c | 28 +++++++++------
2 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/cpukit/score/cpu/arm/armv7m-isr-dispatch.c b/cpukit/score/cpu/arm/armv7m-isr-dispatch.c
index e460e9c..ffd1589 100644
--- a/cpukit/score/cpu/arm/armv7m-isr-dispatch.c
+++ b/cpukit/score/cpu/arm/armv7m-isr-dispatch.c
@@ -5,10 +5,10 @@
*/
/*
- * Copyright (c) 2011-2014 Sebastian Huber. All rights reserved.
+ * Copyright (c) 2011, 2017 Sebastian Huber. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems at embedded-brains.de>
@@ -48,29 +48,42 @@ static void _ARMV7M_Trigger_lazy_floating_point_context_save( void )
void _ARMV7M_Pendable_service_call( void )
{
- ARMV7M_Exception_frame *ef;
+ Per_CPU_Control *cpu_self = _Per_CPU_Get();
- _ISR_Nest_level = 1;
+ /*
+ * We must check here if a thread dispatch is allowed. Right after a
+ * "msr basepri_max, %[basepri]" instruction an interrupt service may still
+ * take place. However, pendable service calls that are activated during
+ * this interrupt service may be delayed until interrupts are enable again.
+ */
+ if (
+ ( cpu_self->isr_nest_level | cpu_self->thread_dispatch_disable_level ) == 0
+ ) {
+ ARMV7M_Exception_frame *ef;
- _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR;
- _ARMV7M_Trigger_lazy_floating_point_context_save();
+ cpu_self->isr_nest_level = 1;
- ef = (ARMV7M_Exception_frame *) _ARMV7M_Get_PSP();
- --ef;
- _ARMV7M_Set_PSP( (uint32_t) ef );
+ _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR;
+ _ARMV7M_Trigger_lazy_floating_point_context_save();
- /*
- * According to "ARMv7-M Architecture Reference Manual" section B1.5.6
- * "Exception entry behavior" the return address is half-word aligned.
- */
- ef->register_pc = (void *)
- ((uintptr_t) _ARMV7M_Thread_dispatch & ~((uintptr_t) 1));
+ ef = (ARMV7M_Exception_frame *) _ARMV7M_Get_PSP();
+ --ef;
+ _ARMV7M_Set_PSP( (uint32_t) ef );
- ef->register_xpsr = 0x01000000U;
+ /*
+ * According to "ARMv7-M Architecture Reference Manual" section B1.5.6
+ * "Exception entry behavior" the return address is half-word aligned.
+ */
+ ef->register_pc = (void *)
+ ((uintptr_t) _ARMV7M_Thread_dispatch & ~((uintptr_t) 1));
+
+ ef->register_xpsr = 0x01000000U;
+ }
}
void _ARMV7M_Supervisor_call( void )
{
+ Per_CPU_Control *cpu_self = _Per_CPU_Get();
ARMV7M_Exception_frame *ef;
_ARMV7M_Trigger_lazy_floating_point_context_save();
@@ -79,10 +92,9 @@ void _ARMV7M_Supervisor_call( void )
++ef;
_ARMV7M_Set_PSP( (uint32_t) ef );
- _ISR_Nest_level = 0;
- RTEMS_COMPILER_MEMORY_BARRIER();
+ cpu_self->isr_nest_level = 0;
- if ( _Thread_Dispatch_necessary ) {
+ if ( cpu_self->dispatch_necessary ) {
_ARMV7M_Pendable_service_call();
}
}
diff --git a/cpukit/score/cpu/arm/armv7m-isr-enter-leave.c b/cpukit/score/cpu/arm/armv7m-isr-enter-leave.c
index 4ab800b..90e97fb 100644
--- a/cpukit/score/cpu/arm/armv7m-isr-enter-leave.c
+++ b/cpukit/score/cpu/arm/armv7m-isr-enter-leave.c
@@ -5,10 +5,10 @@
*/
/*
- * Copyright (c) 2011 Sebastian Huber. All rights reserved.
+ * Copyright (c) 2011, 2017 Sebastian Huber. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems at embedded-brains.de>
@@ -30,19 +30,25 @@
void _ARMV7M_Interrupt_service_enter( void )
{
- ++_Thread_Dispatch_disable_level;
- ++_ISR_Nest_level;
+ Per_CPU_Control *cpu_self = _Per_CPU_Get();
+
+ ++cpu_self->thread_dispatch_disable_level;
+ ++cpu_self->isr_nest_level;
}
void _ARMV7M_Interrupt_service_leave( void )
{
- --_ISR_Nest_level;
- --_Thread_Dispatch_disable_level;
- if (
- _ISR_Nest_level == 0
- && _Thread_Dispatch_disable_level == 0
- && _Thread_Dispatch_necessary
- ) {
+ Per_CPU_Control *cpu_self = _Per_CPU_Get();
+
+ --cpu_self->thread_dispatch_disable_level;
+ --cpu_self->isr_nest_level;
+
+ /*
+ * Optimistically activate a pendable service call if a thread dispatch is
+ * necessary. The _ARMV7M_Pendable_service_call() will check that a thread
+ * dispatch is allowed.
+ */
+ if ( cpu_self->dispatch_necessary ) {
_ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVSET;
}
}
More information about the vc
mailing list