arch/arm/include/armv7-m, arch/arm/include/armv7-m, arch/arm/include/stm32f7: Add a configuration to enable workaround for r0p1 Errata 837070: Increasing priority usingwrite to BASEPRI does not take effect immediately.

This update is required to be serialized to the instruction stream meaning that after this update completes, it takes effect immediately and no exceptions of lower priority than the new boosted priority can pre-empt execution.  Because of this erratum, the priority boosting does not take place immediately, allowing the instruction after the MSR to be interrupted by an exception of lower priority than the new boosted priority. This effect is only limited to the next instruction. Subsequent instructions are guaranteed to see the new boosted priority.

This was raised in Bitbucket issue 113 from Vadzim Dambrouski.
This commit is contained in:
Gregory Nutt 2018-08-02 16:51:58 -06:00
parent f649db2405
commit 09ccd43d61
4 changed files with 102 additions and 52 deletions

View File

@ -604,56 +604,6 @@ config ARCH_CHIP
default "tms570" if ARCH_CHIP_TMS570
default "xmc4" if ARCH_CHIP_XMC4
config ARMV7M_USEBASEPRI
bool "Use BASEPRI Register"
default n
depends on ARCH_CORTEXM3 || ARCH_CORTEXM4 || ARCH_CORTEXM7
---help---
Use the BASEPRI register to enable and disable interrupts. By
default, the PRIMASK register is used for this purpose. This
usually results in hardfaults when supervisor calls are made.
Though, these hardfaults are properly handled by the RTOS, the
hardfaults can confuse some debuggers. With the BASEPRI
register, these hardfaults, will be avoided. For more details see
http://www.nuttx.org/doku.php?id=wiki:nxinternal:svcall
config ARCH_HAVE_LAZYFPU
bool
config ARMV7M_LAZYFPU
bool "Lazy FPU storage"
default n
depends on ARCH_HAVE_LAZYFPU
---help---
There are two forms of the common vector logic. There are pros and
cons to each option:
1) The standard common vector logic exploits features of the ARMv7-M
architecture to save the all of floating registers on entry into
each interrupt and then to restore the floating registers when
the interrupt returns. The primary advantage to this approach is
that floating point operations are available in interrupt
handling logic. Since the volatile registers are preserved,
operations on the floating point registers by interrupt handling
logic has no ill effect. The downside is, of course, that more
stack operations are required on each interrupt to save and store
the floating point registers. Because of the some special
features of the ARMv-M, this is not as much overhead as you might
expect, but overhead nonetheless.
2) The lazy FPU common vector logic does not save or restore
floating point registers on entry and exit from the interrupt
handler. Rather, the floating point registers are not restored
until it is absolutely necessary to do so when a context switch
occurs and the interrupt handler will be returning to a different
floating point context. Since floating point registers are not
protected, floating point operations must not be performed in
interrupt handling logic. Better interrupt performance is be
expected, however.
By default, the "standard" common vector logic is build. This
option selects the alternate lazy FPU common vector logic.
config ARCH_HAVE_FPU
bool
default n
@ -662,6 +612,9 @@ config ARCH_HAVE_DPFPU
bool
default n
config ARCH_HAVE_LAZYFPU
bool
config ARCH_FPU
bool "FPU support"
default y

View File

@ -245,13 +245,36 @@ static inline void setbasepri(uint32_t basepri)
: "memory");
}
static inline void raisebasepri(uint32_t basepri) inline_function;
static inline void raisebasepri(uint32_t basepri)
{
/* This may be retaining or raising priority. Cortex-M7 r0p1 Errata
* 837070 Workaround may be required if we are raising the priority.
*/
#ifdef CONFIG_ARMV7M_BASEPRI_WAR /* Cortex-M7 r0p1 Errata 837070 Workaround */
__asm__ __volatile__ ("\tcpsid i\n");
#endif
__asm__ __volatile__
(
"\tmsr basepri, %0\n"
:
: "r" (basepri)
: "memory");
#ifdef CONFIG_ARMV7M_BASEPRI_WAR /* Cortex-M7 r0p1 Errata 837070 Workaround */
__asm__ __volatile__ ("\tcpsie i\n");
#endif
}
/* Disable IRQs */
static inline void up_irq_disable(void) inline_function;
static inline void up_irq_disable(void)
{
#ifdef CONFIG_ARMV7M_USEBASEPRI
setbasepri(NVIC_SYSH_DISABLE_PRIORITY);
/* Probably raising priority */
raisebasepri(NVIC_SYSH_DISABLE_PRIORITY);
#else
__asm__ __volatile__ ("\tcpsid i\n");
#endif
@ -263,9 +286,10 @@ static inline irqstate_t up_irq_save(void) inline_function;
static inline irqstate_t up_irq_save(void)
{
#ifdef CONFIG_ARMV7M_USEBASEPRI
/* Probably raising priority */
uint8_t basepri = getbasepri();
setbasepri(NVIC_SYSH_DISABLE_PRIORITY);
raisebasepri(NVIC_SYSH_DISABLE_PRIORITY);
return (irqstate_t)basepri;
#else
@ -293,6 +317,8 @@ static inline irqstate_t up_irq_save(void)
static inline void up_irq_enable(void) inline_function;
static inline void up_irq_enable(void)
{
/* In this case, we are always retaining or lowering the priority value */
setbasepri(NVIC_SYSH_PRIORITY_MIN);
__asm__ __volatile__ ("\tcpsie i\n");
}
@ -303,7 +329,10 @@ static inline void up_irq_restore(irqstate_t flags) inline_function;
static inline void up_irq_restore(irqstate_t flags)
{
#ifdef CONFIG_ARMV7M_USEBASEPRI
/* In this case, we are always retaining or lowering the priority value */
setbasepri((uint32_t)flags);
#else
/* If bit 0 of the primask is 0, then we need to restore
* interrupts.
@ -318,6 +347,7 @@ static inline void up_irq_restore(irqstate_t flags)
:
: "r" (flags)
: "memory");
#endif
}

View File

@ -13,6 +13,71 @@ config ARMV7M_HAVE_DCACHE
bool
default n
config ARMV7M_LAZYFPU
bool "Lazy FPU storage"
default n
depends on ARCH_HAVE_LAZYFPU
---help---
There are two forms of the common vector logic. There are pros and
cons to each option:
1) The standard common vector logic exploits features of the ARMv7-M
architecture to save the all of floating registers on entry into
each interrupt and then to restore the floating registers when
the interrupt returns. The primary advantage to this approach is
that floating point operations are available in interrupt
handling logic. Since the volatile registers are preserved,
operations on the floating point registers by interrupt handling
logic has no ill effect. The downside is, of course, that more
stack operations are required on each interrupt to save and store
the floating point registers. Because of the some special
features of the ARMv-M, this is not as much overhead as you might
expect, but overhead nonetheless.
2) The lazy FPU common vector logic does not save or restore
floating point registers on entry and exit from the interrupt
handler. Rather, the floating point registers are not restored
until it is absolutely necessary to do so when a context switch
occurs and the interrupt handler will be returning to a different
floating point context. Since floating point registers are not
protected, floating point operations must not be performed in
interrupt handling logic. Better interrupt performance is be
expected, however.
By default, the "standard" common vector logic is build. This
option selects the alternate lazy FPU common vector logic.
config ARMV7M_USEBASEPRI
bool "Use BASEPRI Register"
default n
depends on ARCH_CORTEXM3 || ARCH_CORTEXM4 || ARCH_CORTEXM7
---help---
Use the BASEPRI register to enable and disable interrupts. By
default, the PRIMASK register is used for this purpose. This
usually results in hardfaults when supervisor calls are made.
Though, these hardfaults are properly handled by the RTOS, the
hardfaults can confuse some debuggers. With the BASEPRI
register, these hardfaults, will be avoided. For more details see
http://www.nuttx.org/doku.php?id=wiki:nxinternal:svcall
config ARMV7M_BASEPRI_WAR
bool "Cortex-M7 r0p1 Errata 837070 Workaround"
default n
depends on ARMV7M_USEBASEPRI && ARCH_CORTEXM7
---help---
Enable workaround for r0p1 Errata 837070: Increasing priority using
write to BASEPRI does not take effect immediately.
This update is required to be serialized to the instruction stream
meaning that after this update completes, it takes effect
immediately and no exceptions of lower priority than the new boosted
priority can pre-empt execution. Because of this erratum, the
priority boosting does not take place immediately, allowing the
instruction after the MSR to be interrupted by an exception of
lower priority than the new boosted priority. This effect is only
limited to the next instruction. Subsequent instructions are
guaranteed to see the new boosted priority.
config ARMV7M_ICACHE
bool "Use I-Cache"
default n

View File

@ -461,6 +461,8 @@ struct max3421e_lowerhalf_s
* acknowledge - Acknowledge/clear any pending GPIO interrupt
* power - Enable or disable 5V VBUS power. REVISIT: Often a
* GPIO from the MAX3421E is used to control VBUS power.
*
* REVISIT: A method may be necessary to sense the state of the GPX input.
*/
CODE int (*attach)(FAR const struct max3421e_lowerhalf_s *lower,