]> git.sur5r.net Git - freertos/commitdiff
Some efficiency improvements in Risc-V port.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Wed, 28 Nov 2018 19:35:40 +0000 (19:35 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Wed, 28 Nov 2018 19:35:40 +0000 (19:35 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2597 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S

index 2754cb40e300c97fc3c600238aa0bff5dbf3e530..28b4b0477de4da0c98a703ec83ff7f8be8e21b0c 100644 (file)
@@ -49,9 +49,10 @@ static void prvTaskExitError( void );
 /*-----------------------------------------------------------*/\r
 \r
 /* Used to program the machine timer compare register. */\r
-static uint64_t ullNextTime = 0ULL;\r
-static const uint64_t ullTimerIncrementsForOneTick = ( uint64_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );\r
-static volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );\r
+uint64_t ullNextTime = 0ULL;\r
+const uint64_t *pullNextTime = &ullNextTime;\r
+const uint32_t ulTimerIncrementsForOneTick = ( uint32_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */\r
+volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -187,11 +188,11 @@ volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLI
        ullNextTime = ( uint64_t ) ulCurrentTimeHigh;\r
        ullNextTime <<= 32ULL;\r
        ullNextTime |= ( uint64_t ) ulCurrentTimeLow;\r
-       ullNextTime += ullTimerIncrementsForOneTick;\r
+       ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;\r
        *pullMachineTimerCompareRegister = ullNextTime;\r
 \r
        /* Prepare the time to use after the next tick interrupt. */\r
-       ullNextTime += ullTimerIncrementsForOneTick;\r
+       ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;\r
 \r
        /* Enable timer interrupt */\r
        __asm volatile( "csrs mie, %0" :: "r"(0x80) ); /* 1<<7 for timer interrupt. */\r
@@ -209,21 +210,6 @@ volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDR
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void Timer_IRQHandler( void )\r
-{\r
-extern void vTaskSwitchContext( void );\r
-\r
-       /* Reload for the next timer interrupt. */\r
-       *pullMachineTimerCompareRegister = ullNextTime;\r
-       ullNextTime += ullTimerIncrementsForOneTick;\r
-\r
-       if( xTaskIncrementTick() != pdFALSE )\r
-       {\r
-               vTaskSwitchContext();\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
 BaseType_t xPortStartScheduler( void )\r
 {\r
 extern void xPortStartFirstTask( void );\r
index 8ffd3a434da2ae462651cfba78023cffa3738557..5f6c3a10ed8db94f5040a120426351f931e42e55 100644 (file)
  */\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
@@ -51,18 +59,18 @@ xPortStartFirstTask:
        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
@@ -82,8 +90,8 @@ xPortStartFirstTask:
        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
@@ -120,24 +128,56 @@ vPortTrapHandler:
        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
@@ -145,37 +185,37 @@ vPortTrapHandler:
 \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