[arch][arm-m] add additional comments and asserts to exception/context switch code
This commit is contained in:
@@ -116,51 +116,51 @@ void _nmi(void) {
|
||||
*/
|
||||
#if (__CORTEX_M >= 0X03) || (__CORTEX_SC >= 300)
|
||||
#define PUSH_REGS \
|
||||
"push {r4-r11, lr};"
|
||||
"push {r4-r11, lr};" /* 9 words on the stack */
|
||||
#else
|
||||
#define PUSH_REGS \
|
||||
"push {r4-r7, lr};" \
|
||||
"mov r4, r8;" \
|
||||
"mov r5, r9;" \
|
||||
"mov r6, r10;" \
|
||||
"mov r7, r11;" \
|
||||
"push {r4-r7};"
|
||||
"push {r4-r7, lr};" /* 5 words */ \
|
||||
"mov r4, r8;" \
|
||||
"mov r5, r9;" \
|
||||
"mov r6, r10;" \
|
||||
"mov r7, r11;" \
|
||||
"push {r4-r7};" /* 4 more words */
|
||||
#endif
|
||||
|
||||
__NAKED void _hardfault(void) {
|
||||
__asm__ volatile(
|
||||
PUSH_REGS
|
||||
"mov r0, sp;"
|
||||
"b hardfault;"
|
||||
"mov r0, sp;"
|
||||
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
|
||||
"b hardfault;"
|
||||
);
|
||||
__UNREACHABLE;
|
||||
}
|
||||
|
||||
__NAKED void _memmanage(void) {
|
||||
__asm__ volatile(
|
||||
PUSH_REGS
|
||||
"mov r0, sp;"
|
||||
"b memmanage;"
|
||||
"mov r0, sp;"
|
||||
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
|
||||
"b memmanage;"
|
||||
);
|
||||
__UNREACHABLE;
|
||||
}
|
||||
|
||||
__NAKED void _busfault(void) {
|
||||
__asm__ volatile(
|
||||
PUSH_REGS
|
||||
"mov r0, sp;"
|
||||
"b busfault;"
|
||||
"mov r0, sp;"
|
||||
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
|
||||
"b busfault;"
|
||||
);
|
||||
__UNREACHABLE;
|
||||
}
|
||||
|
||||
__NAKED void _usagefault(void) {
|
||||
__asm__ volatile(
|
||||
PUSH_REGS
|
||||
"mov r0, sp;"
|
||||
"b usagefault;"
|
||||
"mov r0, sp;"
|
||||
"sub sp, #4;" /* adjust the stack to be 8 byte aligned */
|
||||
"b usagefault;"
|
||||
);
|
||||
__UNREACHABLE;
|
||||
}
|
||||
|
||||
#undef PUSH_REGS
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
/* support header for all cortex-m class cpus */
|
||||
|
||||
#include <assert.h>
|
||||
#include <lk/compiler.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@@ -59,6 +60,8 @@ struct arm_cm_exception_frame {
|
||||
uint32_t r7;
|
||||
#endif
|
||||
uint32_t exc_return;
|
||||
|
||||
/* hardware pushes this */
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
@@ -69,6 +72,8 @@ struct arm_cm_exception_frame {
|
||||
uint32_t psr;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct arm_cm_exception_frame) == 17 * 4, "");
|
||||
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
|
||||
/* exception frame when fpu context save is enabled */
|
||||
@@ -85,6 +90,7 @@ struct arm_cm_exception_frame_fpu {
|
||||
|
||||
float s16_31[16];
|
||||
|
||||
/* hardware pushes this */
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
@@ -94,9 +100,14 @@ struct arm_cm_exception_frame_fpu {
|
||||
uint32_t pc;
|
||||
uint32_t psr;
|
||||
|
||||
/* additional state the cpu pushes when using an extended frame */
|
||||
float s0_15[16];
|
||||
uint32_t fpscr;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct arm_cm_exception_frame_fpu) == (9 + 16 + 8 + 16 + 2) * 4, "");
|
||||
|
||||
#endif
|
||||
|
||||
#if ARM_CM_DYNAMIC_PRIORITY_SIZE
|
||||
@@ -158,12 +169,13 @@ static inline void arm_cm_trigger_interrupt(int vector) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static inline void arm_cm_trigger_preempt(void) {
|
||||
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
|
||||
|
||||
static inline bool arm_cm_is_preempt_triggered(void) {
|
||||
return SCB->ICSR & SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
|
||||
/* systick */
|
||||
void arm_cm_systick_init(uint32_t mhz);
|
||||
|
||||
@@ -106,7 +106,7 @@ static vaddr_t pendsv_swap_sp(vaddr_t old_frame) {
|
||||
DEBUG_ASSERT(((uintptr_t)__GET_FRAME() & 0x7) == 0);
|
||||
|
||||
DEBUG_ASSERT_MSG(!spin_lock_held(&thread_lock),
|
||||
"PENDSV: thread lock was held when preempted! pc %#x\n", ((struct arm_cm_exception_frame *)old_frame)->pc);
|
||||
"PENDSV: thread lock was held when preempted! pc %#x\n", ((struct arm_cm_exception_frame *)old_frame)->pc);
|
||||
|
||||
DEBUG_ASSERT(_prev_running_thread != NULL);
|
||||
DEBUG_ASSERT(_current_thread != NULL);
|
||||
@@ -181,6 +181,12 @@ void arch_context_switch(struct thread *oldthread, struct thread *newthread) {
|
||||
arm_cm_trigger_preempt();
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure either pendsv is queued up either via the previous if statement
|
||||
* or via a nested preemption.
|
||||
*/
|
||||
DEBUG_ASSERT(arm_cm_is_preempt_triggered());
|
||||
|
||||
if (!in_interrupt_context) {
|
||||
/* we're in thread context, so jump to PendSV immediately */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user