]> 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 3e65c4f9b3603acf896fa0fe897db9073fb60cdf..2754cb40e300c97fc3c600238aa0bff5dbf3e530 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- * FreeRTOS Kernel V10.1.0\r
+ * FreeRTOS Kernel V10.1.1\r
  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
  *\r
  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
@@ -39,7 +39,7 @@
  * file is weak to allow application writers to change the timer used to\r
  * generate the tick interrupt.\r
  */\r
-void vPortSetupTimerInterrupt( void );\r
+void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));\r
 \r
 /*\r
  * Used to catch tasks that attempt to return from their implementing function.\r
@@ -48,6 +48,13 @@ static void prvTaskExitError( void );
 \r
 /*-----------------------------------------------------------*/\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
+\r
+/*-----------------------------------------------------------*/\r
+\r
 void prvTaskExitError( void )\r
 {\r
 volatile uint32_t ulx = 0;\r
@@ -69,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
@@ -87,21 +96,164 @@ 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
+       *pxTopOfStack = ( StackType_t ) 30;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 29;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 28;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 27;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 26;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 25;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 24;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 23;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 22;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 21;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 20;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 19;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 18;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 17;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 16;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 15;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 14;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 13;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 12;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 11;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) pvParameters;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 9;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 8;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 7;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) 6;\r
        pxTopOfStack--;\r
-       *pxTopOfStack = ( StackType_t ) pxCode; /* X1 */\r
+       *pxTopOfStack = ( StackType_t ) 5;\r
        pxTopOfStack--;\r
-       *pxTopOfStack =\r
+//     *pxTopOfStack = ( StackType_t ) 4;  /* Thread pointer. */\r
+//     pxTopOfStack--;\r
+//     *pxTopOfStack = ( StackType_t ) 3;  /* Global pointer. */\r
+//     pxTopOfStack--;\r
+//     *pxTopOfStack = ( StackType_t ) 2;  /* Stack pointer. */\r
+//     pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) prvTaskExitError;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( StackType_t ) pxCode;\r
+\r
+       return pxTopOfStack;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortSetupTimerInterrupt( void )\r
+{\r
+uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;\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
+               ulCurrentTimeHigh = *pulTimeHigh;\r
+               ulCurrentTimeLow = *pulTimeLow;\r
+       } while( ulCurrentTimeHigh != *pulTimeHigh );\r
+\r
+       ullNextTime = ( uint64_t ) ulCurrentTimeHigh;\r
+       ullNextTime <<= 32ULL;\r
+       ullNextTime |= ( uint64_t ) ulCurrentTimeLow;\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) ); /* 1<<7 for timer interrupt. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void Software_IRQHandler( void )\r
+{\r
+volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDRESS;\r
+\r
+       vTaskSwitchContext();\r
 \r
+       /* Clear software interrupt. */\r
+       *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) &= 0x08UL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void Timer_IRQHandler( void )\r
+{\r
+extern void vTaskSwitchContext( void );\r
 \r
-               return pxTopOfStack;\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
-       /*Should not get here*/\r
-       return pdFALSE;\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