Skip to content

Commit 420e5c0

Browse files
carlescufigalak
authored andcommitted
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 <[email protected]> Signed-off-by: Carles Cufi <[email protected]> Signed-off-by: Kumar Gala <[email protected]>
1 parent 4ef1d4e commit 420e5c0

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

include/arch/arm/cortex_m/nvic.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,13 @@ static inline void _NvicIrqUnpend(unsigned int irq)
184184

185185
static inline void _NvicIrqPrioSet(unsigned int irq, uint8_t prio)
186186
{
187+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
188+
volatile uint32_t * const ipr = &__scs.nvic.ipr[_PRIO_IP_IDX(irq)];
189+
*ipr = ((*ipr & ~((uint32_t)0xff << _PRIO_BIT_SHIFT(irq))) |
190+
((uint32_t)prio << _PRIO_BIT_SHIFT(irq)));
191+
#else
187192
__scs.nvic.ipr[irq] = prio;
193+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
188194
}
189195

190196
/**
@@ -200,7 +206,11 @@ static inline void _NvicIrqPrioSet(unsigned int irq, uint8_t prio)
200206

201207
static inline uint8_t _NvicIrqPrioGet(unsigned int irq)
202208
{
209+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
210+
return (__scs.nvic.ipr[_PRIO_IP_IDX(irq)] >> _PRIO_BIT_SHIFT(irq));
211+
#else
203212
return __scs.nvic.ipr[irq];
213+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
204214
}
205215

206216
#if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS)

include/arch/arm/cortex_m/scb.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -557,44 +557,60 @@ static inline void ScbCcrSet(uint32_t val)
557557
*
558558
* @brief Obtain priority of an exception
559559
*
560-
* Only works with exceptions 4 to 15; i.e. do not use this for interrupts, which
560+
* Only works with exceptions; i.e. do not use this for interrupts, which
561561
* are exceptions 16+.
562562
*
563-
* Exceptions 1 to 3 priorities are fixed (-3, -2, -1).
563+
* ARMv6-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1) and 4 to 9 are
564+
* reserved exceptions.
565+
* ARMv7-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1).
564566
*
565567
* @param exc exception number, 4 to 15
566568
* @return priority of exception @a exc
567569
*/
568570

569571
static inline uint8_t _ScbExcPrioGet(uint8_t exc)
570572
{
573+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
574+
__ASSERT((exc > 10) && (exc < 16), "");
575+
return (__scs.scb.shpr[_PRIO_SHP_IDX(exc)] >> _PRIO_BIT_SHIFT(exc));
576+
#else
571577
/* For priority exception handler 4-15 */
572578
__ASSERT((exc > 3) && (exc < 16), "");
573579
return __scs.scb.shpr[exc - 4];
580+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
574581
}
575582

576583
/**
577584
*
578585
* @brief Set priority of an exception
579586
*
580-
* Only works with exceptions 4 to 15; i.e. do not use this for interrupts, which
587+
* Only works with exceptions; i.e. do not use this for interrupts, which
581588
* are exceptions 16+.
582589
*
583590
* Note that the processor might not implement all 8 bits, in which case the
584591
* lower N bits are ignored.
585592
*
586-
* Exceptions 1 to 3 priorities are fixed (-3, -2, -1).
593+
* ARMv6-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1) and 4 to 9 are
594+
* reserved exceptions.
595+
* ARMv7-M: Exceptions 1 to 3 priorities are fixed (-3, -2, -1).
587596
*
588-
* @param exc exception number, 4 to 15
597+
* @param exc exception number, 10 to 15 on ARMv6-M and 4 to 15 on ARMv7-M
589598
* @param pri priority, 0 to 255
590599
* @return N/A
591600
*/
592601

593602
static inline void _ScbExcPrioSet(uint8_t exc, uint8_t pri)
594603
{
604+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
605+
volatile uint32_t * const shpr = &__scs.scb.shpr[_PRIO_SHP_IDX(exc)];
606+
__ASSERT((exc > 10) && (exc < 16), "");
607+
*shpr = ((*shpr & ~((uint32_t)0xff << _PRIO_BIT_SHIFT(exc))) |
608+
((uint32_t)pri << _PRIO_BIT_SHIFT(exc)));
609+
#else
595610
/* For priority exception handler 4-15 */
596611
__ASSERT((exc > 3) && (exc < 16), "");
597612
__scs.scb.shpr[exc - 4] = pri;
613+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
598614
}
599615

600616
#if !defined(CONFIG_CPU_CORTEX_M0_M0PLUS)

include/arch/arm/cortex_m/scs.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,9 +454,13 @@ struct __scs {
454454
uint32_t rsvd__320_37f[24];
455455

456456
uint32_t rsvd__380_3ff[32];
457-
457+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
458+
uint32_t ipr[8];
459+
uint32_t rsvd__420_4ff[56];
460+
#else
458461
uint8_t ipr[240]; /* 0x400 Interrupt Priority Registers */
459462
uint32_t rsvd__4f0_4ff[4];
463+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
460464
} nvic; /* offset: 0x100, size 0x400 */
461465

462466
uint32_t rsvd__500_cff[(0xd00 - 0x500) / 4];
@@ -470,10 +474,15 @@ struct __scs {
470474
aircr; /* 0xd0c App IRQ and Reset Control Register */
471475
union __scr scr; /* 0xd10 System Control Register */
472476
union __ccr ccr; /* 0xd14 Configuration and Control Register */
477+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
478+
uint32_t rsvd_24_27;
479+
uint32_t shpr[2];
480+
#else
473481
uint8_t shpr[12]; /* 0xd18 System Handler Priority Registers
474482
* Use ('exception number' - 4) to
475483
* get index into array
476484
*/
485+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
477486
union __shcsr
478487
shcsr; /* 0xd24 Sys Handler Control and State Reg */
479488
union __cfsr cfsr; /* 0xd28 Configurable Fault Status Register
@@ -530,6 +539,14 @@ struct __scs {
530539
/* the linker always puts this object at 0xe000e000 */
531540
extern volatile struct __scs __scs;
532541

542+
#if defined(CONFIG_CPU_CORTEX_M0_M0PLUS)
543+
/* Interrupt Priorities are WORD accessible only under ARMv6M */
544+
/* The following MACROS handle generation of the register offset and masks */
545+
#define _PRIO_BIT_SHIFT(IRQn) (((((uint32_t)(IRQn))) & 0x03UL) * 8UL)
546+
#define _PRIO_SHP_IDX(IRQn) ((((((uint32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL))
547+
#define _PRIO_IP_IDX(IRQn) ((((uint32_t)(IRQn)) >> 2UL))
548+
#endif /* CONFIG_CPU_CORTEX_M0_M0PLUS */
549+
533550
/* API */
534551

535552
/**

0 commit comments

Comments
 (0)