diff options
author | Carles Cufi <carles.cufi@nordicsemi.no> | 2016-12-27 15:49:39 +0100 |
---|---|---|
committer | Kumar Gala <kumar.gala@linaro.org> | 2017-01-04 08:19:00 -0600 |
commit | 420e5c057f5b2dde9508ad17d657cb4e19d0437d (patch) | |
tree | ab87c7525fe07582c11d520013ffeba82689ba95 | |
parent | 4ef1d4e122a932536a67436fe1df45bd36751040 (diff) |
arm: nvic: Fix exception priority access on Cortex-M0(+)
The Cortex-M0(+) and in general processors that support only the ARMv6-M
instruction set can only access the NVIC_IPRn registers with word
accesses, and not with byte ones like the Cortex-M3 and onwards. This
patch addresses the issue by modifying the way that _NvicIrqPrioSet()
writes to the IPRn register, using a word access for Cortex-M0(+).
A similar issue is addressed for internal exceptions, this time for the
SHPR registers that are accessed differently on ARMv6-M.
Reference code taken from CMSIS.
Jira: ZEP-1497
Change-id: I08e1bf60b3b70579b42f4ab926ee835c18bb65bb
Signed-off-by: Vinayak Chettimada <vinayak.kariappa.chettimada@nordicsemi.no>
Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
-rw-r--r-- | include/arch/arm/cortex_m/nvic.h | 10 | ||||
-rw-r--r-- | include/arch/arm/cortex_m/scb.h | 26 | ||||
-rw-r--r-- | include/arch/arm/cortex_m/scs.h | 19 |
3 files changed, 49 insertions, 6 deletions
diff --git a/include/arch/arm/cortex_m/nvic.h b/include/arch/arm/cortex_m/nvic.h index 7b516b542..26207062b 100644 --- a/include/arch/arm/cortex_m/nvic.h +++ b/include/arch/arm/cortex_m/nvic.h @@ -184,7 +184,13 @@ static inline void _NvicIrqUnpend(unsigned int irq) static inline void _NvicIrqPrioSet(unsigned int irq, uint8_t prio) { +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) + volatile uint32_t * const ipr = &__scs.nvic.ipr[_PRIO_IP_IDX(irq)]; + *ipr = ((*ipr & ~((uint32_t)0xff << _PRIO_BIT_SHIFT(irq))) | + ((uint32_t)prio << _PRIO_BIT_SHIFT(irq))); +#else __scs.nvic.ipr[irq] = prio; +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ } /** @@ -200,7 +206,11 @@ static inline void _NvicIrqPrioSet(unsigned int irq, uint8_t prio) static inline uint8_t _NvicIrqPrioGet(unsigned int irq) { +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) + return (__scs.nvic.ipr[_PRIO_IP_IDX(irq)] >> _PRIO_BIT_SHIFT(irq)); +#else return __scs.nvic.ipr[irq]; +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ } #if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS) diff --git a/include/arch/arm/cortex_m/scb.h b/include/arch/arm/cortex_m/scb.h index 6c5284cc7..73a1f5e62 100644 --- a/include/arch/arm/cortex_m/scb.h +++ b/include/arch/arm/cortex_m/scb.h @@ -557,10 +557,12 @@ static inline void ScbCcrSet(uint32_t val) * * @brief Obtain priority of an exception * - * Only works with exceptions 4 to 15; i.e. do not use this for interrupts, which + * Only works with exceptions; i.e. do not use this for interrupts, which * are exceptions 16+. * - * Exceptions 1 to 3 priorities are fixed (-3, -2, -1). + * ARMv6-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1) and 4 to 9 are + * reserved exceptions. + * ARMv7-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1). * * @param exc exception number, 4 to 15 * @return priority of exception @a exc @@ -568,33 +570,47 @@ static inline void ScbCcrSet(uint32_t val) static inline uint8_t _ScbExcPrioGet(uint8_t exc) { +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) + __ASSERT((exc > 10) && (exc < 16), ""); + return (__scs.scb.shpr[_PRIO_SHP_IDX(exc)] >> _PRIO_BIT_SHIFT(exc)); +#else /* For priority exception handler 4-15 */ __ASSERT((exc > 3) && (exc < 16), ""); return __scs.scb.shpr[exc - 4]; +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ } /** * * @brief Set priority of an exception * - * Only works with exceptions 4 to 15; i.e. do not use this for interrupts, which + * Only works with exceptions; i.e. do not use this for interrupts, which * are exceptions 16+. * * Note that the processor might not implement all 8 bits, in which case the * lower N bits are ignored. * - * Exceptions 1 to 3 priorities are fixed (-3, -2, -1). + * ARMv6-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1) and 4 to 9 are + * reserved exceptions. + * ARMv7-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1). * - * @param exc exception number, 4 to 15 + * @param exc exception number, 10 to 15 on ARMv6-M and 4 to 15 on ARMv7-M * @param pri priority, 0 to 255 * @return N/A */ static inline void _ScbExcPrioSet(uint8_t exc, uint8_t pri) { +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) + volatile uint32_t * const shpr = &__scs.scb.shpr[_PRIO_SHP_IDX(exc)]; + __ASSERT((exc > 10) && (exc < 16), ""); + *shpr = ((*shpr & ~((uint32_t)0xff << _PRIO_BIT_SHIFT(exc))) | + ((uint32_t)pri << _PRIO_BIT_SHIFT(exc))); +#else /* For priority exception handler 4-15 */ __ASSERT((exc > 3) && (exc < 16), ""); __scs.scb.shpr[exc - 4] = pri; +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ } #if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS) diff --git a/include/arch/arm/cortex_m/scs.h b/include/arch/arm/cortex_m/scs.h index 4095999b9..cfc3406de 100644 --- a/include/arch/arm/cortex_m/scs.h +++ b/include/arch/arm/cortex_m/scs.h @@ -454,9 +454,13 @@ struct __scs { uint32_t rsvd__320_37f[24]; uint32_t rsvd__380_3ff[32]; - +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) + uint32_t ipr[8]; + uint32_t rsvd__420_4ff[56]; +#else uint8_t ipr[240]; /* 0x400 Interrupt Priority Registers */ uint32_t rsvd__4f0_4ff[4]; +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ } nvic; /* offset: 0x100, size 0x400 */ uint32_t rsvd__500_cff[(0xd00 - 0x500) / 4]; @@ -470,10 +474,15 @@ struct __scs { aircr; /* 0xd0c App IRQ and Reset Control Register */ union __scr scr; /* 0xd10 System Control Register */ union __ccr ccr; /* 0xd14 Configuration and Control Register */ +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) + uint32_t rsvd_24_27; + uint32_t shpr[2]; +#else uint8_t shpr[12]; /* 0xd18 System Handler Priority Registers * Use ('exception number' - 4) to * get index into array */ +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ union __shcsr shcsr; /* 0xd24 Sys Handler Control and State Reg */ union __cfsr cfsr; /* 0xd28 Configurable Fault Status Register @@ -530,6 +539,14 @@ struct __scs { /* the linker always puts this object at 0xe000e000 */ extern volatile struct __scs __scs; +#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS) +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and masks */ +#define _PRIO_BIT_SHIFT(IRQn) (((((uint32_t)(IRQn))) & 0x03UL) * 8UL) +#define _PRIO_SHP_IDX(IRQn) ((((((uint32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL)) +#define _PRIO_IP_IDX(IRQn) ((((uint32_t)(IRQn)) >> 2UL)) +#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */ + /* API */ /** |