Skip to content

Commit

Permalink
[arch][arm-m] add additional comments and asserts to exception/contex…
Browse files Browse the repository at this point in the history
…t switch code
  • Loading branch information
travisg committed Feb 26, 2024
1 parent be19e2a commit 770d475
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 22 deletions.
38 changes: 19 additions & 19 deletions arch/arm/arm-m/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 14 additions & 2 deletions arch/arm/arm-m/include/arch/arm/cm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 7 additions & 1 deletion arch/arm/arm-m/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 */

Expand Down

0 comments on commit 770d475

Please sign in to comment.