]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
First task running in RISC-V-Qemu-sifive_e-FreedomStudio demo.
[freertos] / FreeRTOS / Source / portable / GCC / RISC-V-RV32 / port.c
index 24611a9bef5d34802ec83323f953fa2c7e05a8c6..2754cb40e300c97fc3c600238aa0bff5dbf3e530 100644 (file)
@@ -50,7 +50,8 @@ static void prvTaskExitError( void );
 \r
 /* Used to program the machine timer compare register. */\r
 static uint64_t ullNextTime = 0ULL;\r
-static volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCTRL_BASE + 0x4000 );\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
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -75,6 +76,8 @@ volatile uint32_t ulx = 0;
  */\r
 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
 {\r
+uint32_t mstatus;\r
+const uint32_t ulMPIE_Bit = 0x80, ulMPP_Bits = 0x1800;\r
        /*\r
           X1 to X31 integer registers for the 'I' profile, X1 to X15 for the 'E' profile.\r
 \r
@@ -93,6 +96,13 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
                x28-31          t3-6                    Temporaries                                     Caller\r
        */\r
 \r
+       /* Start task with interrupt enabled. */\r
+       __asm volatile ("csrr %0, mstatus" : "=r"(mstatus));\r
+       mstatus |= ulMPIE_Bit | ulMPP_Bits;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = mstatus;\r
+\r
+       /* Numbers correspond to the x register number. */\r
        pxTopOfStack--;\r
        *pxTopOfStack = ( StackType_t ) 31;\r
        pxTopOfStack--;\r
@@ -165,8 +175,8 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
 void vPortSetupTimerInterrupt( void )\r
 {\r
 uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;\r
-volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCTRL_BASE + 0xBFF8 );\r
-volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCTRL_BASE + 0xBFFc );\r
+volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFFC );\r
+volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFF8 );\r
 \r
        do\r
        {\r
@@ -177,23 +187,73 @@ volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCTR
        ullNextTime = ( uint64_t ) ulCurrentTimeHigh;\r
        ullNextTime <<= 32ULL;\r
        ullNextTime |= ( uint64_t ) ulCurrentTimeLow;\r
-       ullNextTime += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );\r
+       ullNextTime += ullTimerIncrementsForOneTick;\r
        *pullMachineTimerCompareRegister = ullNextTime;\r
 \r
+       /* Prepare the time to use after the next tick interrupt. */\r
+       ullNextTime += ullTimerIncrementsForOneTick;\r
+\r
        /* Enable timer interrupt */\r
-       __asm volatile( "csrs mie, %0" :: "r"(0x80) );\r
+       __asm volatile( "csrs mie, %0" :: "r"(0x80) ); /* 1<<7 for timer interrupt. */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void Software_IRQHandler( void )\r
 {\r
-volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCTRL_BASE;\r
+volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDRESS;\r
 \r
        vTaskSwitchContext();\r
 \r
        /* Clear software interrupt. */\r
-       *ulSoftInterrupt = 0UL;\r
+       *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) &= 0x08UL;\r
+}\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
+\r
+       #if( configASSERT_DEFINED == 1 )\r
+       {\r
+               volatile uint32_t mtvec = 0;\r
+\r
+               /* Check the least significant two bits of mtvec are 00 - indicating single\r
+               vector mode. */\r
+               __asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );\r
+               configASSERT( ( mtvec & 0x03UL ) == 0 );\r
+       }\r
+       #endif\r
+\r
+       vPortSetupTimerInterrupt();\r
+       xPortStartFirstTask();\r
+\r
+       /* Should not get here as after calling xPortStartFirstTask() only tasks\r
+       should be executing. */\r
+       return pdFAIL;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+void vPortEndScheduler( void )\r
+{\r
+       /* Not implemented. */\r
+       for( ;; );\r
+}\r
+\r
+\r
+\r
 \r