aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Kay <chris.kay@arm.com>2020-05-29 18:37:15 +0100
committerChris Kay <chris@cjkay.com>2020-06-05 19:16:35 +0100
commit8850f8582c0f6e1ee7027b82a57435f0c93abb8b (patch)
treecbf783a56e2f712c419d2bdca8e382470924855d
parente376c365590db77227bd04a880a3df3ffca289b6 (diff)
arch: Use CMSIS interfaces
Much of the NVIC and exception handling in the architecture layer duplicates functionality already provided by CMSIS. This patch replaces duplicated interfaces with their CMSIS equivalents. Change-Id: I476c046a3153ee1afff1a313bcffdd56ff763cf5 Signed-off-by: Chris Kay <chris.kay@arm.com>
-rw-r--r--arch/src/arm_main.c12
-rw-r--r--arch/src/arm_nvic.c173
-rw-r--r--arch/src/armv7-m/exceptions.c66
3 files changed, 104 insertions, 147 deletions
diff --git a/arch/src/arm_main.c b/arch/src/arm_main.c
index 69cbf4b7..998fcdef 100644
--- a/arch/src/arm_main.c
+++ b/arch/src/arm_main.c
@@ -11,15 +11,11 @@
#include <fwk_assert.h>
#include <fwk_macros.h>
+#include <fmw_cmsis.h>
+
#include <stdbool.h>
#include <stdint.h>
-#define SCB_CCR ((FWK_RW uint32_t *)(0xE000ED14))
-
-#define SCB_CCR_UNALIGN_TRP_MASK (1U << 3)
-#define SCB_CCR_DIV_0_TRP_MASK (1U << 4)
-#define SCB_CCR_STKALIGN_MASK (1U << 9)
-
extern int arch_nvic_init(struct fwk_arch_interrupt_driver **driver);
extern int arch_mm_init(struct fwk_arch_mm_data *data);
@@ -77,8 +73,8 @@ static void arch_init_ccr(void)
* (2) ARMĀ® v7-M Architecture Reference Manual, section B1.5.7.
*/
- *SCB_CCR |= SCB_CCR_DIV_0_TRP_MASK;
- *SCB_CCR |= SCB_CCR_STKALIGN_MASK;
+ SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
+ SCB->CCR |= SCB_CCR_STKALIGN_Msk;
}
int main(void)
diff --git a/arch/src/arm_nvic.c b/arch/src/arm_nvic.c
index 1bd8b14a..0e30fb9d 100644
--- a/arch/src/arm_nvic.c
+++ b/arch/src/arm_nvic.c
@@ -8,8 +8,6 @@
* Interrupt management.
*/
-#include <cmsis_compiler.h>
-
#include <fwk_arch.h>
#include <fwk_interrupt.h>
#include <fwk_macros.h>
@@ -17,76 +15,38 @@
#include <fwk_noreturn.h>
#include <fwk_status.h>
+#include <fmw_cmsis.h>
+
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-
-#ifdef BUILD_HAS_MULTITHREADING
-# include <rtx_os.h>
-#endif
+#include <string.h>
extern noreturn void arch_exception_invalid(void);
-#define SCB_SHCSR ((FWK_RW uint32_t *)(0xE000ED24UL))
-#define SCB_VTOR ((FWK_RW uint32_t *)(0xE000ED08UL))
-#define SCS_ICTR ((FWK_R uint32_t *)(0xE000E004UL))
-#define SCS_STIR ((FWK_W uint32_t *)(0xE000EF00UL))
-#define SCS_NVIC ((struct nvic *)(0xE000E100UL))
-
-#define SCB_SHCSR_MEMFAULTENA_MASK (1 << 16)
-#define SCB_SHCSR_BUSFAULTENA_MASK (1 << 17)
-#define SCB_SHCSR_USGFAULTENA_MASK (1 << 18)
-
-enum exception_num {
- EXCEPTION_NUM_INVALID = 0U,
- EXCEPTION_NUM_RESET = 1U,
- EXCEPTION_NUM_NMI = 2U,
- EXCEPTION_NUM_HARDFAULT = 3U,
- EXCEPTION_NUM_MEMMANAGE = 4U,
- EXCEPTION_NUM_BUSFAULT = 5U,
- EXCEPTION_NUM_USAGEFAULT = 6U,
- EXCEPTION_NUM_SVCALL = 11U,
- EXCEPTION_NUM_DEBUGMONITOR = 12U,
- EXCEPTION_NUM_PENDSV = 14U,
- EXCEPTION_NUM_SYSTICK = 15U,
- EXCEPTION_NUM_COUNT,
-};
-
-struct nvic {
- FWK_RW uint32_t ISER[16]; /* Interrupt Set Enabled Register */
- uint32_t RESERVED0[16];
- FWK_RW uint32_t ICER[16]; /* Interrupt Clear Enabled Register */
- uint32_t RESERVED1[16];
- FWK_RW uint32_t ISPR[16]; /* Interrupt Set Pending Register */
- uint32_t RESERVED2[16];
- FWK_RW uint32_t ICPR[16]; /* Interrupt Clear Pending Register */
- uint32_t RESERVED3[16];
- FWK_R uint32_t IABR[16]; /* Interrupt Active Bit Register */
- uint32_t RESERVED4[48];
- FWK_W uint32_t IPR[16]; /* Interrupt Priority Register */
- uint32_t RESERVED5[48];
-};
-
-static uint32_t isr_count;
-static uint32_t irq_count;
+static unsigned int isr_count;
+static unsigned int irq_count;
/*
* For interrupts with parameters, their entry in the vector table points to a
* global handler that calls a registered function in the callback table with a
* corresponding parameter. Entries in the vector table for interrupts without
* parameters point directly to the handler functions.
+ *
+ * Entry indices are offset by -1 relative to their interrupt numbers, as no
+ * interrupt may have an interrupt number of zero.
*/
struct callback {
void (*func)(uintptr_t param);
uintptr_t param;
};
-static void (**vector)(void);
static struct callback *callback;
static void irq_global(void)
{
- struct callback *entry = &callback[__get_IPSR()];
+ struct callback *entry = &callback[__get_IPSR() - 1];
+
entry->func(entry->param);
}
@@ -109,8 +69,7 @@ static int is_enabled(unsigned int interrupt, bool *enabled)
if (interrupt >= irq_count)
return FWK_E_PARAM;
- *enabled = SCS_NVIC->ISER[interrupt / 32] &
- (UINT32_C(1) << (interrupt & 0x1F));
+ *enabled = NVIC_GetEnableIRQ(interrupt);
return FWK_SUCCESS;
}
@@ -120,7 +79,7 @@ static int enable(unsigned int interrupt)
if (interrupt >= irq_count)
return FWK_E_PARAM;
- SCS_NVIC->ISER[interrupt / 32] = UINT32_C(1) << (interrupt & 0x1F);
+ NVIC_EnableIRQ(interrupt);
return FWK_SUCCESS;
}
@@ -130,7 +89,7 @@ static int disable(unsigned int interrupt)
if (interrupt >= irq_count)
return FWK_E_PARAM;
- SCS_NVIC->ICER[interrupt / 32] = UINT32_C(1) << (interrupt & 0x1F);
+ NVIC_DisableIRQ(interrupt);
return FWK_SUCCESS;
}
@@ -140,8 +99,7 @@ static int is_pending(unsigned int interrupt, bool *pending)
if (interrupt >= irq_count)
return FWK_E_PARAM;
- *pending = SCS_NVIC->ISPR[interrupt / 32] &
- (UINT32_C(1) << (interrupt & 0x1F));
+ *pending = NVIC_GetPendingIRQ(interrupt);
return FWK_SUCCESS;
}
@@ -151,7 +109,7 @@ static int set_pending(unsigned int interrupt)
if (interrupt >= irq_count)
return FWK_E_PARAM;
- *SCS_STIR = interrupt;
+ NVIC_SetPendingIRQ(interrupt);
return FWK_SUCCESS;
}
@@ -161,7 +119,7 @@ static int clear_pending(unsigned int interrupt)
if (interrupt >= irq_count)
return FWK_E_PARAM;
- SCS_NVIC->ICPR[interrupt / 32] = UINT32_C(1) << (interrupt & 0x1F);
+ NVIC_ClearPendingIRQ(interrupt);
return FWK_SUCCESS;
}
@@ -171,31 +129,32 @@ static int set_isr_irq(unsigned int interrupt, void (*isr)(void))
if (interrupt >= irq_count)
return FWK_E_PARAM;
- vector[EXCEPTION_NUM_COUNT + interrupt] = isr;
+ NVIC_SetVector(interrupt, (uint32_t)isr);
return FWK_SUCCESS;
}
-static int set_isr_irq_param(unsigned int interrupt,
- void (*isr)(uintptr_t param),
- uintptr_t parameter)
+static int set_isr_irq_param(
+ unsigned int interrupt,
+ void (*isr)(uintptr_t param),
+ uintptr_t parameter)
{
struct callback *entry;
if (interrupt >= irq_count)
return FWK_E_PARAM;
- vector[EXCEPTION_NUM_COUNT + interrupt] = irq_global;
-
- entry = &callback[EXCEPTION_NUM_COUNT + interrupt];
+ entry = &callback[NVIC_USER_IRQ_OFFSET + interrupt - 1];
entry->func = isr;
entry->param = parameter;
+ NVIC_SetVector(interrupt, (uint32_t)irq_global);
+
return FWK_SUCCESS;
}
static int set_isr_nmi(void (*isr)(void))
{
- vector[EXCEPTION_NUM_NMI] = isr;
+ NVIC_SetVector(NonMaskableInt_IRQn, (uint32_t)isr);
return FWK_SUCCESS;
}
@@ -204,21 +163,21 @@ static int set_isr_nmi_param(void (*isr)(uintptr_t param), uintptr_t parameter)
{
struct callback *entry;
- vector[EXCEPTION_NUM_NMI] = irq_global;
-
- entry = &callback[EXCEPTION_NUM_NMI];
+ entry = &callback[NVIC_USER_IRQ_OFFSET + NonMaskableInt_IRQn - 1];
entry->func = isr;
entry->param = parameter;
+ NVIC_SetVector(NonMaskableInt_IRQn, (uint32_t)irq_global);
+
return FWK_SUCCESS;
}
static int set_isr_fault(void (*isr)(void))
{
- vector[EXCEPTION_NUM_HARDFAULT] = isr;
- vector[EXCEPTION_NUM_MEMMANAGE] = isr;
- vector[EXCEPTION_NUM_BUSFAULT] = isr;
- vector[EXCEPTION_NUM_USAGEFAULT] = isr;
+ NVIC_SetVector(HardFault_IRQn, (uint32_t)isr);
+ NVIC_SetVector(MemoryManagement_IRQn, (uint32_t)isr);
+ NVIC_SetVector(BusFault_IRQn, (uint32_t)isr);
+ NVIC_SetVector(UsageFault_IRQn, (uint32_t)isr);
return FWK_SUCCESS;
}
@@ -231,12 +190,12 @@ static int get_current(unsigned int *interrupt)
if (*interrupt == 0)
return FWK_E_STATE;
- if (*interrupt == EXCEPTION_NUM_NMI)
+ if (*interrupt == (NVIC_USER_IRQ_OFFSET + NonMaskableInt_IRQn))
*interrupt = FWK_INTERRUPT_NMI;
- else if ((*interrupt) < EXCEPTION_NUM_COUNT)
+ else if (*interrupt < NVIC_USER_IRQ_OFFSET)
*interrupt = FWK_INTERRUPT_EXCEPTION;
else
- *interrupt -= EXCEPTION_NUM_COUNT;
+ *interrupt -= NVIC_USER_IRQ_OFFSET;
return FWK_SUCCESS;
}
@@ -268,15 +227,17 @@ int arch_nvic_init(const struct fwk_arch_interrupt_driver **driver)
uint32_t ictr_intlinesnum;
uint32_t align_entries;
uint32_t align_word;
- unsigned int i;
+
+ uint32_t *vector;
+ IRQn_Type irq;
if (driver == NULL)
return FWK_E_PARAM;
/* Find the number of interrupt lines implemented in hardware */
- ictr_intlinesnum = *SCS_ICTR & 0x0000000F;
+ ictr_intlinesnum = SCnSCB->ICTR & SCnSCB_ICTR_INTLINESNUM_Msk;
irq_count = (ictr_intlinesnum + 1) * 32;
- isr_count = irq_count + EXCEPTION_NUM_COUNT;
+ isr_count = NVIC_USER_IRQ_OFFSET + irq_count;
/*
* Allocate and initialize a table for the callback functions and their
@@ -299,45 +260,37 @@ int arch_nvic_init(const struct fwk_arch_interrupt_driver **driver)
/* Calculate alignment on a word boundary */
align_word = align_entries * sizeof(vector[0]);
- vector = fwk_mm_alloc_aligned(isr_count, sizeof(vector[0]), align_word);
+ /* Allocate and wipe the new vector table */
+ vector = fwk_mm_calloc_aligned(isr_count, sizeof(vector[0]), align_word);
- /*
- * Initialize all exception entries to point to the arch_exception_invalid()
- * handler.
- *
- * Note: Initialization starts from entry 1 since entry 0 is not an
- * exception pointer but the default stack pointer.
- */
- for (i = 1; i < EXCEPTION_NUM_COUNT; i++)
- vector[i] = arch_exception_invalid;
+ /* Copy the processor exception table over to the new vector table */
+ memcpy(
+ vector,
+ (const void *)SCB->VTOR,
+ NVIC_USER_IRQ_OFFSET * sizeof(vector[0]));
- /* Initialize IRQs */
- for (i = 0; i < irq_count; i++) {
- /* Initialize all IRQ entries to point to the irq_invalid() handler */
- vector[EXCEPTION_NUM_COUNT + i] = irq_invalid;
+ __DMB();
- /* Ensure IRQs are disabled during boot sequence */
- disable(i);
- clear_pending(i);
- }
+ __disable_irq();
-#ifdef BUILD_HAS_MULTITHREADING
- /* Set exception entries that are implemented and handled by RTX */
- vector[EXCEPTION_NUM_SVCALL] = SVC_Handler;
- vector[EXCEPTION_NUM_PENDSV] = PendSV_Handler;
- vector[EXCEPTION_NUM_SYSTICK] = SysTick_Handler;
-#endif
+ /* Switch to the new vector table */
+ SCB->VTOR = (uint32_t)vector;
- __DMB();
+ /* Initialize IRQs */
+ for (irq = 0; irq < (IRQn_Type)irq_count; irq++) {
+ /* Ensure IRQs are disabled during boot sequence */
+ NVIC_DisableIRQ(irq);
+ NVIC_ClearPendingIRQ(irq);
- /* Switch to the new vector table */
- *SCB_VTOR = (uint32_t)vector;
- __DMB();
+ /* Initialize all IRQ entries to point to the irq_invalid() handler */
+ NVIC_SetVector(irq, (uint32_t)irq_invalid);
+ }
+
+ __enable_irq();
/* Enable the Usage, Bus and Memory faults which are disabled by default */
- *SCB_SHCSR |= SCB_SHCSR_MEMFAULTENA_MASK |
- SCB_SHCSR_BUSFAULTENA_MASK |
- SCB_SHCSR_USGFAULTENA_MASK;
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk |
+ SCB_SHCSR_USGFAULTENA_Msk;
*driver = &arch_nvic_driver;
diff --git a/arch/src/armv7-m/exceptions.c b/arch/src/armv7-m/exceptions.c
index 8994a581..1095d35f 100644
--- a/arch/src/armv7-m/exceptions.c
+++ b/arch/src/armv7-m/exceptions.c
@@ -10,9 +10,15 @@
#include "exceptions.h"
+#include <fmw_cmsis.h>
+
#include <stdint.h>
#include <string.h>
+#ifdef BUILD_HAS_MULTITHREADING
+# include <rtx_os.h>
+#endif
+
#ifdef __NEWLIB__
/*
* This function overloads a weak definition provided by Newlib. It is called
@@ -33,24 +39,6 @@ void software_init_hook(void)
}
#endif
-enum {
- EXCEPTION_RESET,
- EXCEPTION_NMI,
- EXCEPTION_HARDFAULT,
- EXCEPTION_MEMMANAGE,
- EXCEPTION_BUSFAULT,
- EXCEPTION_USAGEFAULT,
- EXCEPTION_RESERVED0,
- EXCEPTION_RESERVED1,
- EXCEPTION_RESERVED2,
- EXCEPTION_RESERVED3,
- EXCEPTION_SVCALL,
- EXCEPTION_DEBUGMONITOR,
- EXCEPTINO_RESERVED4,
- EXCEPTION_PENDSV,
- EXCEPTION_SYSTICK,
-};
-
#ifdef __ARMCC_VERSION
extern char Image$$ARM_LIB_STACKHEAP$$ZI$$Limit;
@@ -69,19 +57,39 @@ extern char __stackheap_end__;
const struct {
uintptr_t stack;
- uintptr_t exceptions[15];
+ uintptr_t exceptions[NVIC_USER_IRQ_OFFSET - 1];
} arch_exceptions __attribute__((section(".exceptions"))) = {
.stack = (uintptr_t)(arch_exception_stack),
.exceptions = {
- [EXCEPTION_RESET] = (uintptr_t)(arch_exception_reset),
- [EXCEPTION_NMI] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_HARDFAULT] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_MEMMANAGE] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_BUSFAULT] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_USAGEFAULT] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_SVCALL] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_DEBUGMONITOR] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_PENDSV] = (uintptr_t)(arch_exception_invalid),
- [EXCEPTION_SYSTICK] = (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + Reset_IRQn - 1] =
+ (uintptr_t)(arch_exception_reset),
+ [NonMaskableInt_IRQn + (NVIC_USER_IRQ_OFFSET - 1)] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + HardFault_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + MemoryManagement_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + BusFault_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + UsageFault_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + DebugMonitor_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+
+#ifdef BUILD_HAS_MULTITHREADING
+ [NVIC_USER_IRQ_OFFSET + SVCall_IRQn - 1] =
+ (uintptr_t)(SVC_Handler),
+ [NVIC_USER_IRQ_OFFSET + PendSV_IRQn - 1] =
+ (uintptr_t)(PendSV_Handler),
+ [NVIC_USER_IRQ_OFFSET + SysTick_IRQn - 1] =
+ (uintptr_t)(SysTick_Handler),
+#else
+ [NVIC_USER_IRQ_OFFSET + SVCall_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + PendSV_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+ [NVIC_USER_IRQ_OFFSET + SysTick_IRQn - 1] =
+ (uintptr_t)(arch_exception_invalid),
+#endif
},
};