diff --git a/ChangeLog b/ChangeLog index 958d8a8..286eaa5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2021-02-08 NIIBE Yutaka + + * entry-cortex-m.c (vector_table): No use of PENDV exception. + Use chx_handle_intr for SysTick. + * example-fsm-55/reset.c (vector): Likewise. + + * chopstx-cortex-m.c (preempting): Remove. + (CPU_EXCEPTION_PRIORITY_PENDSV): Remove. + (chx_interrupt_controller_init): No setup for PENDV. + (chx_request_preemption_possibly): Remove. + (involuntary_context_switch): New. + (chx_timer_handler): Remove. + (chx_handle_intr): Use involuntary_context_switch directly. + (preempt): Remove. + 2021-02-05 NIIBE Yutaka * chopstx-cortex-m.c (preempting): New value to hold the pointer diff --git a/chopstx-cortex-m.c b/chopstx-cortex-m.c index 524e1db..a525722 100644 --- a/chopstx-cortex-m.c +++ b/chopstx-cortex-m.c @@ -29,7 +29,6 @@ */ static struct chx_thread *running; -static struct chx_thread *preempting; static struct chx_thread * chx_running (void) @@ -77,14 +76,14 @@ struct chx_stack_regs { * --------------------- * Prio 0x40: thread temporarily inhibiting schedule for critical region * ... - * Prio 0xb0: systick, external interrupt, pendsv + * Prio 0xb0: systick, external interrupt * ===================================== * * Cortex-M0 * ===================================== * Prio 0x00: thread temporarily inhibiting schedule for critical region * ... - * Prio 0x40: systick, external interrupt, pendsv + * Prio 0x40: systick, external interrupt * Prio 0x80: svc (not used) * ===================================== */ @@ -96,7 +95,6 @@ struct chx_stack_regs { /* ... */ #define CPU_EXCEPTION_PRIORITY_SYSTICK 0x40 #define CPU_EXCEPTION_PRIORITY_INTERRUPT CPU_EXCEPTION_PRIORITY_SYSTICK -#define CPU_EXCEPTION_PRIORITY_PENDSV CPU_EXCEPTION_PRIORITY_SYSTICK #define CPU_EXCEPTION_PRIORITY_SVC 0x80 /* No use in this arch */ #elif defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) #define CPU_EXCEPTION_PRIORITY_SVC 0x30 @@ -105,7 +103,6 @@ struct chx_stack_regs { /* ... */ #define CPU_EXCEPTION_PRIORITY_SYSTICK 0xb0 #define CPU_EXCEPTION_PRIORITY_INTERRUPT CPU_EXCEPTION_PRIORITY_SYSTICK -#define CPU_EXCEPTION_PRIORITY_PENDSV CPU_EXCEPTION_PRIORITY_SYSTICK #else #error "no support for this arch" #endif @@ -229,8 +226,7 @@ chx_interrupt_controller_init (void) { *AIRCR = 0x05FA0000 | ( 5 << 8); /* PRIGROUP = 5, 2-bit:2-bit. */ *SHPR2 = (CPU_EXCEPTION_PRIORITY_SVC << 24); - *SHPR3 = ((CPU_EXCEPTION_PRIORITY_SYSTICK << 24) - | (CPU_EXCEPTION_PRIORITY_PENDSV << 16)); + *SHPR3 = (CPU_EXCEPTION_PRIORITY_SYSTICK << 24); } @@ -257,42 +253,106 @@ chx_cpu_sched_unlock (void) } -static void -chx_request_preemption_possibly (struct chx_thread *tp_next) +static void __attribute__ ((naked, used)) +involuntary_context_switch (struct chx_thread *tp_next) { - if (!tp_next) - return; + register struct chx_thread *tp_current asm ("r1"); - if (preempting) - chx_ready_push (tp_next); + asm ( + "ldr r2, =running\n\t" + "ldr r1, [r2]" + : "=r" (tp_current) + : /* no input */ + : "r2"); + + if (!tp_current) + /* It's idle thread. No need to save registers. */ + ; else { - preempting = tp_next; - *ICSR = (1 << 28); - asm volatile ("" : : : "memory"); + /* Save registers onto CHX_THREAD struct. */ + asm volatile ( + "add %0, #20\n\t" + "stm %0!, {r4, r5, r6, r7}\n\t" + "mov r2, r8\n\t" + "mov r3, r9\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "mrs r6, PSP\n\t" /* r13(=SP) in user space. */ + "stm %0!, {r2, r3, r4, r5, r6}" + : "=r" (tp_current) + : "0" (tp_current) + /* + * Memory clobber constraint here is not accurate, but this + * works. R7 keeps its value, but having "r7" here prevents + * use of R7 before this asm statement. + */ + : "r2", "r3", "r4", "r5", "r6", "r7", "memory"); + + tp_next = chx_running_preempted (tp_next); } + + /* Registers on stack (PSP): r0, r1, r2, r3, r12, lr, pc, xpsr */ + + asm volatile ( + /* Now, r0 points to the thread to be switched. */ + /* Put it to *running. */ + "ldr r1, =running\n\t" + /* Update running. */ + "str r0, [r1]\n\t" + /**/ + "add r0, #20\n\t" + "ldm r0!, {r4, r5, r6, r7}\n\t" +#if defined(__ARM_ARCH_6M__) + "ldm r0!, {r1, r2, r3}\n\t" + "mov r8, r1\n\t" + "mov r9, r2\n\t" + "mov r10, r3\n\t" + "ldm r0!, {r1, r2}\n\t" + "mov r11, r1\n\t" + "msr PSP, r2\n\t" +#else + "ldr r8, [r0], #4\n\t" + "ldr r9, [r0], #4\n\t" + "ldr r10, [r0], #4\n\t" + "ldr r11, [r0], #4\n\t" + "ldr r1, [r0], #4\n\t" + "msr PSP, r1\n\t" +#endif + "mov r0, #0\n\t" + "sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */ + "bx r0" + : /* no output */ : "r" (tp_next) : "memory"); } -void -chx_timer_handler (void) -{ - struct chx_thread *tp_next; - tp_next = chx_timer_expired (); - chx_request_preemption_possibly (tp_next); -} +static struct chx_thread *chx_timer_expired (void) __attribute__ ((noinline,used)); +static struct chx_thread *chx_recv_irq (uint32_t irq_num) __attribute__ ((noinline,used)); -void +void __attribute__ ((naked)) chx_handle_intr (void) { - register uint32_t irq_num; - struct chx_thread *tp_next; + register struct chx_thread *tp_next asm ("r0");; asm volatile ("mrs %0, IPSR\n\t" - "sub %0, #16" /* Exception # - 16 = interrupt number. */ - : "=r" (irq_num) : /* no input */ : "memory"); + "sub %0, #16\n\t" /* Exception # - 16 = interrupt number. */ + "bpl 0f\n\t" + "bl chx_timer_expired\n\t" + "b 1f\n" + "0:\n\t" + "bl chx_recv_irq\n" + "1:" + : "=r" (tp_next) : /* no input */ : "memory"); - tp_next = chx_recv_irq (irq_num); - chx_request_preemption_possibly (tp_next); + if (tp_next) + asm volatile ( + "b involuntary_context_switch" + : /*no input */ : /* no input */ : "memory"); + else + asm volatile ( + "mov r0, #0\n\t" + "sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */ + "bx r0" + : /*no input */ : /* no input */ : "memory"); } static void @@ -476,87 +536,6 @@ chopstx_create_arch (uintptr_t stack_addr, size_t stack_size, return tp; } -/* - * Lower layer architecture specific exception handling entries. - * - */ - -void __attribute__ ((naked)) -preempt (void) -{ - register struct chx_thread *tp_next asm ("r0"); - register struct chx_thread *tp_current asm ("r1"); - - asm ( - "mov r1, #0\n\t" - "ldr r2, =preempting\n\t" - "ldr r0, [r2]\n\t" - "str r1, [r2]\n\t" - "ldr r2, =running\n\t" - "ldr r1, [r2]" - : "=r" (tp_next), "=r" (tp_current) - : /* no input */ - : "r2"); - - if (!tp_current) - /* It's idle thread. No need to save registers. */ - ; - else - { - /* Save registers onto CHX_THREAD struct. */ - asm volatile ( - "add %0, #20\n\t" - "stm %0!, {r4, r5, r6, r7}\n\t" - "mov r2, r8\n\t" - "mov r3, r9\n\t" - "mov r4, r10\n\t" - "mov r5, r11\n\t" - "mrs r6, PSP\n\t" /* r13(=SP) in user space. */ - "stm %0!, {r2, r3, r4, r5, r6}" - : "=r" (tp_current) - : "0" (tp_current) - /* - * Memory clobber constraint here is not accurate, but this - * works. R7 keeps its value, but having "r7" here prevents - * use of R7 before this asm statement. - */ - : "r2", "r3", "r4", "r5", "r6", "r7", "memory"); - - tp_next = chx_running_preempted (tp_next); - } - - /* Registers on stack (PSP): r0, r1, r2, r3, r12, lr, pc, xpsr */ - - asm volatile ( - /* Now, r0 points to the thread to be switched. */ - /* Put it to *running. */ - "ldr r1, =running\n\t" - /* Update running. */ - "str r0, [r1]\n\t" - /**/ - "add r0, #20\n\t" - "ldm r0!, {r4, r5, r6, r7}\n\t" -#if defined(__ARM_ARCH_6M__) - "ldm r0!, {r1, r2, r3}\n\t" - "mov r8, r1\n\t" - "mov r9, r2\n\t" - "mov r10, r3\n\t" - "ldm r0!, {r1, r2}\n\t" - "mov r11, r1\n\t" - "msr PSP, r2\n\t" -#else - "ldr r8, [r0], #4\n\t" - "ldr r9, [r0], #4\n\t" - "ldr r10, [r0], #4\n\t" - "ldr r11, [r0], #4\n\t" - "ldr r1, [r0], #4\n\t" - "msr PSP, r1\n\t" -#endif - "mov r0, #0\n\t" - "sub r0, #3\n\t" /* EXC_RETURN to a thread with PSP */ - "bx r0" - : /* no output */ : "r" (tp_next) : "memory"); -} #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) /* diff --git a/entry-cortex-m.c b/entry-cortex-m.c index 35aec4f..702046e 100644 --- a/entry-cortex-m.c +++ b/entry-cortex-m.c @@ -65,9 +65,6 @@ extern uint8_t __main_stack_end__; extern void svc (void); #endif -extern void preempt (void); - -extern void chx_timer_handler (void); extern void chx_handle_intr (void); static void nmi (void) @@ -194,8 +191,8 @@ handler vector_table[] __attribute__ ((section(".startup.vectors"))) = { #endif none, /* Debug */ none, /* reserved */ - preempt, /* PendSV */ - chx_timer_handler, /* SysTick */ + none, /* PendSV */ + chx_handle_intr, /* SysTick */ /* 0x40 */ chx_handle_intr /* WWDG */, chx_handle_intr /* PVD */, chx_handle_intr /* TAMPER */, chx_handle_intr /* RTC */, diff --git a/example-fsm-55/reset.c b/example-fsm-55/reset.c index 1ce6226..a21e199 100644 --- a/example-fsm-55/reset.c +++ b/example-fsm-55/reset.c @@ -31,8 +31,6 @@ reset (void) } extern uint8_t __main_stack_end__; -extern void preempt (void); -extern void chx_timer_handler (void); extern void chx_handle_intr (void); static void nmi (void) @@ -84,8 +82,8 @@ handler vector[] __attribute__ ((section(".vectors"))) = { none, /* SVCall */ none, /* Debug */ none, /* reserved */ - preempt, /* PendSV */ - chx_timer_handler, /* SysTick */ + none, /* PendSV */ + chx_handle_intr, /* SysTick */ /* 0x40 */ chx_handle_intr /* WWDG */, chx_handle_intr /* PVD */, chx_handle_intr /* TAMPER */, chx_handle_intr /* RTC */,