CortexM0: IPR and SHPR are only word addressable

For ARMv6M, the IPR and SHPR registers are accessible only when
adddressed with a 32bit word read or write.

Currently in libopencm3 all NVIC interrupt priority register accesses
are made using an 8bit read or write, which results in the hardware
ignoring the write or always returning 0 on read.

Address this by introducing NVIC_IPR32() and SCS_SHPR32() macro and
conditional implementation of nvic_set_priority when building for
cortex-m0.

See ARMv6M developer documentation:
IPR: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Cihgjeed.html
SHPR: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CIAGECDD.html
This commit is contained in:
Matt Anderson 2019-06-19 04:01:37 -04:00 committed by Karl Palsson
parent baa2f13592
commit d8579dde95
3 changed files with 29 additions and 1 deletions

View File

@ -92,10 +92,15 @@
/** IPR: Interrupt Priority Registers
* @note 240 8bit Registers
* @@note 32 8bit Registers on CM0
* @note 32 8bit Registers on CM0, requires word access
*/
#if defined(__ARM_ARCH_6M__)
#define NVIC_IPR32(ipr_id) MMIO32(NVIC_BASE + 0x300 + \
((ipr_id) * 4))
#else
#define NVIC_IPR(ipr_id) MMIO8(NVIC_BASE + 0x300 + \
(ipr_id))
#endif
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
/** STIR: Software Trigger Interrupt Register */

View File

@ -52,8 +52,14 @@
/** System Handler Priority 8 bits Registers, SHPR1/2/3.
* Note: 12 8bit Registers
* Note: 3 32bit Registers on CM0, requires word access
*/
#if defined(__ARM_ARCH_6M__)
#define SCS_SHPR32(ipr_id) MMIO32(SCS_BASE + 0xD18 + ((ipr_id) * 4))
#else
#define SCS_SHPR(ipr_id) MMIO8(SCS_BASE + 0xD18 + (ipr_id))
#endif
/**
* Debug Halting Control and Status Register (DHCSR).

View File

@ -156,10 +156,27 @@ void nvic_set_priority(uint8_t irqn, uint8_t priority)
* handling would mean signed integers. */
if (irqn >= NVIC_IRQ_COUNT) {
/* Cortex-M system interrupts */
#if defined(__ARM_ARCH_6M__)
/* ARM6M supports only 32bit word access to SHPR registers */
irqn = (irqn & 0xF) - 4;
uint8_t shift = (irqn & 0x3) << 3;
uint8_t reg = irqn >> 2;
SCS_SHPR32(reg) = ((SCS_SHPR32(reg) & ~(0xFFUL << shift)) |
((uint32_t) priority) << shift);
#else
SCS_SHPR((irqn & 0xF) - 4) = priority;
#endif
} else {
/* Device specific interrupts */
#if defined(__ARM_ARCH_6M__)
/* ARM6M supports only 32bit word access to IPR registers */
uint8_t shift = (irqn & 0x3) << 3;
uint8_t reg = irqn >> 2;
NVIC_IPR32(reg) = ((NVIC_IPR32(reg) & ~(0xFFUL << shift)) |
((uint32_t) priority) << shift);
#else
NVIC_IPR(irqn) = priority;
#endif
}
}