]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
Ensure eTaskGetState() is brought in automatically if INCLUDE_xTaskAbortDelay is...
[freertos] / FreeRTOS / Source / portable / GCC / RISC-V-RV32 / port.c
index 24611a9bef5d34802ec83323f953fa2c7e05a8c6..8e32f81be7efe4282616d3ed93400eb037d3a239 100644 (file)
 #include "task.h"\r
 #include "portmacro.h"\r
 \r
+#ifndef configCLINT_BASE_ADDRESS\r
+       #warning configCLINT_BASE_ADDRESS must be defined in FreeRTOSConfig.h.  If the target chip includes a Core Local Interrupter (CLINT) then set configCLINT_BASE_ADDRESS to the CLINT base address.  Otherwise set configCLINT_BASE_ADDRESS to 0.\r
+#endif\r
+\r
+/* Let the user override the pre-loading of the initial LR with the address of\r
+prvTaskExitError() in case it messes up unwinding of the stack in the\r
+debugger. */\r
+#ifdef configTASK_RETURN_ADDRESS\r
+       #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS\r
+#else\r
+       #define portTASK_RETURN_ADDRESS prvTaskExitError\r
+#endif\r
+\r
+/* The stack used by interrupt service routines.  Set configISR_STACK_SIZE_WORDS\r
+to use a statically allocated array as the interrupt stack.  Alternative leave\r
+configISR_STACK_SIZE_WORDS undefined and update the linker script so that a\r
+linker variable names __freertos_irq_stack_top has the same value as the top\r
+of the stack used by main.  Using the linker script method will repurpose the\r
+stack that was used by main before the scheduler was started for use as the\r
+interrupt stack after the scheduler has started. */\r
+#ifdef configISR_STACK_SIZE_WORDS\r
+       static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };\r
+       const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ ( configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ) - 1 ] );\r
+#else\r
+       extern const uint32_t __freertos_irq_stack_top[];\r
+       const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;\r
+#endif\r
+\r
 /*\r
  * Setup the timer to generate the tick interrupts.  The implementation in this\r
  * file is weak to allow application writers to change the timer used to\r
@@ -49,15 +77,41 @@ static void prvTaskExitError( void );
 /*-----------------------------------------------------------*/\r
 \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
+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
+/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task\r
+stack checking.  A problem in the ISR stack will trigger an assert, not call the\r
+stack overflow hook function (because the stack overflow hook is specific to a\r
+task stack, not the ISR stack). */\r
+#if( configCHECK_FOR_STACK_OVERFLOW > 2 )\r
+       #warning This path not tested, or even compiled yet.\r
+       /* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for\r
+       the task stacks, and so will legitimately appear in many positions within\r
+       the ISR stack. */\r
+       #define portISR_STACK_FILL_BYTE 0xee\r
+\r
+       static const uint8_t ucExpectedStackBytes[] = {\r
+                                                                       portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,             \\r
+                                                                       portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,             \\r
+                                                                       portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,             \\r
+                                                                       portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,             \\r
+                                                                       portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE };   \\r
+\r
+       #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )\r
+#else\r
+       /* Define the function away. */\r
+       #define portCHECK_ISR_STACK()\r
+#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-void prvTaskExitError( void )\r
+static void prvTaskExitError( void )\r
 {\r
 volatile uint32_t ulx = 0;\r
-\r
+#warning Not currently used\r
        /* A function that implements a task must not exit or attempt to return to\r
        its caller as there is nothing to return to.  If a task wants to exit it\r
        should instead call vTaskDelete( NULL ).\r
@@ -70,130 +124,87 @@ volatile uint32_t ulx = 0;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/*\r
- * See header file for description.\r
- */\r
-StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
-{\r
-       /*\r
-          X1 to X31 integer registers for the 'I' profile, X1 to X15 for the 'E' profile.\r
-\r
-               Register        ABI Name                Description                                     Saver\r
-               x0                      zero                    Hard-wired zero                                 -\r
-               x1                      ra                              Return address                                  Caller\r
-               x2                      sp                              Stack pointer                                   Callee\r
-               x3                      gp                              Global pointer                                  -\r
-               x4                      tp                              Thread pointer                                  -\r
-               x5-7            t0-2                    Temporaries                                     Caller\r
-               x8                      s0/fp                   Saved register/Frame pointer    Callee\r
-               x9                      s1                              Saved register                                  Callee\r
-               x10-11          a0-1                    Function Arguments/return values Caller\r
-               x12-17          a2-7                    Function arguments                              Caller\r
-               x18-27          s2-11                   Saved registers                                 Callee\r
-               x28-31          t3-6                    Temporaries                                     Caller\r
-       */\r
-\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 ) 5;\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
+#if( configCLINT_BASE_ADDRESS != 0 )\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 += ( uint64_t ) ulTimerIncrementsForOneTick;\r
+               *pullMachineTimerCompareRegister = ullNextTime;\r
+\r
+               /* Prepare the time to use after the next tick interrupt. */\r
+               ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;\r
+       }\r
+\r
+#endif /* ( configCLINT_BASE_ADDRESS != 0 ) */\r
 /*-----------------------------------------------------------*/\r
 \r
-void vPortSetupTimerInterrupt( void )\r
+BaseType_t xPortStartScheduler( 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
+extern void xPortStartFirstTask( void );\r
 \r
-       do\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\r
+               single vector mode. */\r
+               __asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );\r
+               configASSERT( ( mtvec & 0x03UL ) == 0 );\r
+\r
+               /* Check alignment of the interrupt stack - which is the same as the\r
+               stack that was being used by main() prior to the scheduler being\r
+               started. */\r
+               configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );\r
+       }\r
+       #endif /* configASSERT_DEFINED */\r
+\r
+       /* If there is a CLINT then it is ok to use the default implementation\r
+       in this file, otherwise vPortSetupTimerInterrupt() must be implemented to\r
+       configure whichever clock is to be used to generate the tick interrupt. */\r
+       vPortSetupTimerInterrupt();\r
+\r
+       #if( configCLINT_BASE_ADDRESS != 0 )\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 += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );\r
-       *pullMachineTimerCompareRegister = ullNextTime;\r
-\r
-       /* Enable timer interrupt */\r
-       __asm volatile( "csrs mie, %0" :: "r"(0x80) );\r
+               /* Enable mtime and external interrupts.  1<<7 for timer interrupt, 1<<11\r
+               for external interrupt.  _RB_ What happens here when mtime is not present as\r
+               with pulpino? */\r
+               __asm volatile( "csrs mie, %0" :: "r"(0x880) );\r
+       }\r
+       #else\r
+       {\r
+               /* Enable external interrupts. */\r
+               __asm volatile( "csrs mie, %0" :: "r"(0x800) );\r
+       }\r
+       #endif /* configCLINT_BASE_ADDRESS */\r
+\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 Software_IRQHandler( void )\r
+void vPortEndScheduler( void )\r
 {\r
-volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCTRL_BASE;\r
+       /* Not implemented. */\r
+       for( ;; );\r
+}\r
+\r
 \r
-       vTaskSwitchContext();\r
 \r
-       /* Clear software interrupt. */\r
-       *ulSoftInterrupt = 0UL;\r
-}\r
-/*-----------------------------------------------------------*/\r
 \r
 \r