*/\r
\r
#if __riscv_xlen == 64\r
- #error Not implemented yet - change lw to ld, and sw to sd.\r
- #define WORD_SIZE 8\r
+ #error Not implemented yet - change lw to ld, and sw to sd.\r
+ #define WORD_SIZE 8\r
#elif __riscv_xlen == 32\r
- #define WORD_SIZE 4\r
+ #define WORD_SIZE 4\r
#else\r
- #error Assembler has not defined __riscv_xlen\r
+ #error Assembler has not defined __riscv_xlen\r
#endif\r
\r
#define CONTEXT_SIZE ( 30 * WORD_SIZE )\r
.global vPortTrapHandler\r
.extern pxCurrentTCB\r
.extern ulPortTrapHandler\r
+.extern vTaskSwitchContext\r
+.extern Timer_IRQHandler\r
+\r
+\r
+.extern pullMachineTimerCompareRegister\r
+.extern pullNextTime\r
+.extern ulTimerIncrementsForOneTick\r
+\r
\r
/*-----------------------------------------------------------*/\r
\r
la t0, vPortTrapHandler\r
csrw mtvec, t0\r
\r
- lw sp, pxCurrentTCB /* Load pxCurrentTCB. */\r
- lw sp, 0( sp ) /* Read sp from first TCB member. */\r
+ lw sp, pxCurrentTCB /* Load pxCurrentTCB. */\r
+ lw sp, 0( sp ) /* Read sp from first TCB member. */\r
\r
lw x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */\r
- lw x5, 2 * WORD_SIZE( sp ) /* t0 */\r
- lw x6, 3 * WORD_SIZE( sp ) /* t1 */\r
- lw x7, 4 * WORD_SIZE( sp ) /* t2 */\r
- lw x8, 5 * WORD_SIZE( sp ) /* s0/fp */\r
- lw x9, 6 * WORD_SIZE( sp ) /* s1 */\r
- lw x10, 7 * WORD_SIZE( sp ) /* a0 */\r
- lw x11, 8 * WORD_SIZE( sp ) /* a1 */\r
- lw x12, 9 * WORD_SIZE( sp ) /* a2 */\r
+ lw x5, 2 * WORD_SIZE( sp ) /* t0 */\r
+ lw x6, 3 * WORD_SIZE( sp ) /* t1 */\r
+ lw x7, 4 * WORD_SIZE( sp ) /* t2 */\r
+ lw x8, 5 * WORD_SIZE( sp ) /* s0/fp */\r
+ lw x9, 6 * WORD_SIZE( sp ) /* s1 */\r
+ lw x10, 7 * WORD_SIZE( sp ) /* a0 */\r
+ lw x11, 8 * WORD_SIZE( sp ) /* a1 */\r
+ lw x12, 9 * WORD_SIZE( sp ) /* a2 */\r
lw x13, 10 * WORD_SIZE( sp ) /* a3 */\r
lw x14, 11 * WORD_SIZE( sp ) /* a4 */\r
lw x15, 12 * WORD_SIZE( sp ) /* a5 */\r
lw x29, 26 * WORD_SIZE( sp ) /* t4 */\r
lw x30, 27 * WORD_SIZE( sp ) /* t5 */\r
lw x31, 28 * WORD_SIZE( sp ) /* t6 */\r
- addi sp, sp, CONTEXT_SIZE\r
- csrs mstatus, 8 /* Enable machine interrupts. */\r
+ addi sp, sp, CONTEXT_SIZE\r
+ csrs mstatus, 8 /* Enable machine interrupts. */\r
ret\r
\r
/*-----------------------------------------------------------*/\r
sw x30, 27 * WORD_SIZE( sp )\r
sw x31, 28 * WORD_SIZE( sp )\r
\r
- csrr t0, mstatus /* Required for MPIE bit. */\r
+ csrr t0, mstatus /* Required for MPIE bit. */\r
sw t0, 29 * WORD_SIZE( sp )\r
\r
- lw t0, pxCurrentTCB /* Load pxCurrentTCB. */\r
- sw sp, 0( t0 ) /* Write sp to first TCB member. */\r
+ lw t0, pxCurrentTCB /* Load pxCurrentTCB. */\r
+ sw sp, 0( t0 ) /* Write sp to first TCB member. */\r
\r
csrr a0, mcause\r
csrr a1, mepc\r
mv a2, sp\r
-/*_RB_ Does stack need aligning here? */\r
- jal ulPortTrapHandler\r
- csrw mepc, a0\r
- /* Save exception return address. */\r
- sw a0, 0( sp )\r
\r
-\r
- lw sp, pxCurrentTCB /* Load pxCurrentTCB. */\r
- lw sp, 0( sp ) /* Read sp from first TCB member. */\r
+test_if_environment_call:\r
+ li t0, 11 /* 11 == environment call when using qemu. */\r
+ bne a0, t0, test_if_timer\r
+ addi a1, a1, 4 /* Synchronous so return to the instruction after the environment call. */\r
+ sw a1, 0( sp ) /* Save updated exception return address. */\r
+/*_RB_ Does stack need aligning here? */\r
+ jal vTaskSwitchContext\r
+ j processed_source\r
+\r
+\r
+test_if_timer:\r
+ sw a1, 0( sp ) /* Asynch so save unmodified exception return address. */\r
+\r
+ lui t0, 0x80000\r
+ addi t1,t0, 7 /* 0x80000007 == machine timer interrupt. */\r
+ bne a0, t1, as_yet_unhandled\r
+\r
+ lw t0, pullMachineTimerCompareRegister /* Load address of compare register into t0. */\r
+ lw t1, pullNextTime /* Load the address of ullNextTime into t1. */\r
+ lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */\r
+ lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */\r
+ sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */\r
+ sw t3, 4(t0) /* Store high word of ullNextTime into compare register. */\r
+ lw t0, ulTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */\r
+ add t4, t0, t2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits. */\r
+ sltu t5, t4, t2 /* See if the sum of low words overflowed (what about the zero case?). */\r
+ add t6, t3, t5 /* Add overflow to high word of ullNextTime. */\r
+ sw t4, 0(t1) /* Store new low word of ullNextTime. */\r
+ sw t6, 4(t1) /* Store new high word of ullNextTime. */\r
+ jal xTaskIncrementTick\r
+ beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */\r
+ jal vTaskSwitchContext\r
+ j processed_source\r
+\r
+as_yet_unhandled:\r
+ j as_yet_unhandled /* External interrupt? */\r
+\r
+processed_source:\r
+ lw sp, pxCurrentTCB /* Load pxCurrentTCB. */\r
+ lw sp, 0( sp ) /* Read sp from first TCB member. */\r
\r
/* Load mret with the address of the next task. */\r
lw t0, 0( sp )\r
\r
/* Load mstatus with the interrupt enable bits used by the task. */\r
lw t0, 29 * WORD_SIZE( sp )\r
- csrw mstatus, t0 /* Required for MPIE bit. */\r
+ csrw mstatus, t0 /* Required for MPIE bit. */\r
\r
lw x1, 1 * WORD_SIZE( sp )\r
- lw x5, 2 * WORD_SIZE( sp ) /* t0 */\r
- lw x6, 3 * WORD_SIZE( sp ) /* t1 */\r
- lw x7, 4 * WORD_SIZE( sp ) /* t2 */\r
- lw x8, 5 * WORD_SIZE( sp ) /* s0/fp */\r
- lw x9, 6 * WORD_SIZE( sp ) /* s1 */\r
- lw x10, 7 * WORD_SIZE( sp ) /* a0 */\r
- lw x11, 8 * WORD_SIZE( sp ) /* a1 */\r
- lw x12, 9 * WORD_SIZE( sp ) /* a2 */\r
- lw x13, 10 * WORD_SIZE( sp ) /* a3 */\r
- lw x14, 11 * WORD_SIZE( sp ) /* a4 */\r
- lw x15, 12 * WORD_SIZE( sp ) /* a5 */\r
- lw x16, 13 * WORD_SIZE( sp ) /* a6 */\r
- lw x17, 14 * WORD_SIZE( sp ) /* a7 */\r
- lw x18, 15 * WORD_SIZE( sp ) /* s2 */\r
- lw x19, 16 * WORD_SIZE( sp ) /* s3 */\r
- lw x20, 17 * WORD_SIZE( sp ) /* s4 */\r
- lw x21, 18 * WORD_SIZE( sp ) /* s5 */\r
- lw x22, 19 * WORD_SIZE( sp ) /* s6 */\r
- lw x23, 20 * WORD_SIZE( sp ) /* s7 */\r
- lw x24, 21 * WORD_SIZE( sp ) /* s8 */\r
- lw x25, 22 * WORD_SIZE( sp ) /* s9 */\r
- lw x26, 23 * WORD_SIZE( sp ) /* s10 */\r
- lw x27, 24 * WORD_SIZE( sp ) /* s11 */\r
- lw x28, 25 * WORD_SIZE( sp ) /* t3 */\r
- lw x29, 26 * WORD_SIZE( sp ) /* t4 */\r
- lw x30, 27 * WORD_SIZE( sp ) /* t5 */\r
- lw x31, 28 * WORD_SIZE( sp ) /* t6 */\r
- addi sp, sp, CONTEXT_SIZE\r
+ lw x5, 2 * WORD_SIZE( sp ) /* t0 */\r
+ lw x6, 3 * WORD_SIZE( sp ) /* t1 */\r
+ lw x7, 4 * WORD_SIZE( sp ) /* t2 */\r
+ lw x8, 5 * WORD_SIZE( sp ) /* s0/fp */\r
+ lw x9, 6 * WORD_SIZE( sp ) /* s1 */\r
+ lw x10, 7 * WORD_SIZE( sp ) /* a0 */\r
+ lw x11, 8 * WORD_SIZE( sp ) /* a1 */\r
+ lw x12, 9 * WORD_SIZE( sp ) /* a2 */\r
+ lw x13, 10 * WORD_SIZE( sp ) /* a3 */\r
+ lw x14, 11 * WORD_SIZE( sp ) /* a4 */\r
+ lw x15, 12 * WORD_SIZE( sp ) /* a5 */\r
+ lw x16, 13 * WORD_SIZE( sp ) /* a6 */\r
+ lw x17, 14 * WORD_SIZE( sp ) /* a7 */\r
+ lw x18, 15 * WORD_SIZE( sp ) /* s2 */\r
+ lw x19, 16 * WORD_SIZE( sp ) /* s3 */\r
+ lw x20, 17 * WORD_SIZE( sp ) /* s4 */\r
+ lw x21, 18 * WORD_SIZE( sp ) /* s5 */\r
+ lw x22, 19 * WORD_SIZE( sp ) /* s6 */\r
+ lw x23, 20 * WORD_SIZE( sp ) /* s7 */\r
+ lw x24, 21 * WORD_SIZE( sp ) /* s8 */\r
+ lw x25, 22 * WORD_SIZE( sp ) /* s9 */\r
+ lw x26, 23 * WORD_SIZE( sp ) /* s10 */\r
+ lw x27, 24 * WORD_SIZE( sp ) /* s11 */\r
+ lw x28, 25 * WORD_SIZE( sp ) /* t3 */\r
+ lw x29, 26 * WORD_SIZE( sp ) /* t4 */\r
+ lw x30, 27 * WORD_SIZE( sp ) /* t5 */\r
+ lw x31, 28 * WORD_SIZE( sp ) /* t6 */\r
+ addi sp, sp, CONTEXT_SIZE\r
\r
mret\r
\r