summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarles Cufi <carles.cufi@nordicsemi.no>2016-12-27 15:49:39 +0100
committerKumar Gala <kumar.gala@linaro.org>2017-01-04 08:19:00 -0600
commit420e5c057f5b2dde9508ad17d657cb4e19d0437d (patch)
treeab87c7525fe07582c11d520013ffeba82689ba95
parent4ef1d4e122a932536a67436fe1df45bd36751040 (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.h10
-rw-r--r--include/arch/arm/cortex_m/scb.h26
-rw-r--r--include/arch/arm/cortex_m/scs.h19
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 */
/**