Skip to content

Commit

Permalink
cpu/fe310: Use ecall instruction for thread yield
Browse files Browse the repository at this point in the history
  • Loading branch information
bergzand committed Jan 13, 2021
1 parent f136781 commit 1b2adb4
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
26 changes: 20 additions & 6 deletions cpu/fe310/irq_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,28 @@ void handle_trap(uint32_t mcause)
}
}
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
printf("Unhandled trap:\n");
printf(" mcause: 0x%"PRIx32"\n", mcause);
printf(" mepc: 0x%"PRIx32"\n", read_csr(mepc));
printf(" mtval: 0x%"PRIx32"\n", read_csr(mtval));
printf("Unhandled trap:\n");
printf(" mcause: 0x%"PRIx32"\n", mcause);
printf(" mepc: 0x%"PRIx32"\n", read_csr(mepc));
printf(" mtval: 0x%"PRIx32"\n", read_csr(mtval));
#endif
/* Unknown trap */
core_panic(PANIC_GENERAL_ERROR, "Unhandled trap");
/* Unknown trap */
core_panic(PANIC_GENERAL_ERROR, "Unhandled trap");
}
}
/* ISR done - no more changes to thread states */
fe310_in_isr = 0;
Expand Down
19 changes: 14 additions & 5 deletions cpu/fe310/thread_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,22 @@ void cpu_switch_context_exit(void)
UNREACHABLE();
}

void thread_yield_higher(void)
static inline void _ecall_dispatch(uint32_t num, void *ctx)
{
/* Use SW intr to schedule context switch */
CLINT_REG(CLINT_MSIP) = 1;
/* 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"
);
}

/* Latency of SW intr can be 4-7 cycles; wait for the SW intr */
__asm__ volatile ("wfi");
void thread_yield_higher(void)
{
_ecall_dispatch(0, NULL);
}

/**
Expand Down

0 comments on commit 1b2adb4

Please sign in to comment.