cpu/fe310: Use ecall instruction for thread yield

This commit is contained in:
Koen Zandberg 2021-01-10 16:04:38 +01:00
parent f1367818ca
commit 1b2adb4821
No known key found for this signature in database
GPG Key ID: 0895A893E6D2985B
2 changed files with 34 additions and 11 deletions

View File

@ -108,6 +108,19 @@ void handle_trap(uint32_t mcause)
} }
} }
else { else {
switch (mcause) {
case CAUSE_USER_ECALL: /* ECALL from user mode */
case CAUSE_MACHINE_ECALL: /* ECALL from machine mode */
{
/* TODO: get the ecall arguments */
sched_context_switch_request = 1;
/* Increment the return program counter past the ecall
* instruction */
uint32_t return_pc = read_csr(mepc);
write_csr(mepc, return_pc + 4);
break;
}
default:
#ifdef DEVELHELP #ifdef DEVELHELP
printf("Unhandled trap:\n"); printf("Unhandled trap:\n");
printf(" mcause: 0x%"PRIx32"\n", mcause); printf(" mcause: 0x%"PRIx32"\n", mcause);
@ -117,6 +130,7 @@ void handle_trap(uint32_t mcause)
/* Unknown trap */ /* Unknown trap */
core_panic(PANIC_GENERAL_ERROR, "Unhandled trap"); core_panic(PANIC_GENERAL_ERROR, "Unhandled trap");
} }
}
/* ISR done - no more changes to thread states */ /* ISR done - no more changes to thread states */
fe310_in_isr = 0; fe310_in_isr = 0;
} }

View File

@ -178,13 +178,22 @@ void cpu_switch_context_exit(void)
UNREACHABLE(); UNREACHABLE();
} }
static inline void _ecall_dispatch(uint32_t num, void *ctx)
{
/* function arguments are in a0 and a1 as per ABI */
__asm__ volatile (
"mv a0, %[num] \n"
"mv a1, %[ctx] \n"
"ECALL\n"
: /* No outputs */
: [num] "r" (num), [ctx] "r" (ctx)
: "memory"
);
}
void thread_yield_higher(void) void thread_yield_higher(void)
{ {
/* Use SW intr to schedule context switch */ _ecall_dispatch(0, NULL);
CLINT_REG(CLINT_MSIP) = 1;
/* Latency of SW intr can be 4-7 cycles; wait for the SW intr */
__asm__ volatile ("wfi");
} }
/** /**