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:
parent
f649db2405
commit
09ccd43d61
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user