]> 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 f14c58ce3d162a79b0b984b63d7be27ee75b3698..8e32f81be7efe4282616d3ed93400eb037d3a239 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
- * FreeRTOS Kernel V10.0.1\r
- * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\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
  * this software and associated documentation files (the "Software"), to deal in\r
 #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
  * 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,34 +76,135 @@ static void prvTaskExitError( void );
 \r
 /*-----------------------------------------------------------*/\r
 \r
-void prvTaskExitError( void )\r
+/* Used to program the machine timer compare register. */\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
+static void prvTaskExitError( void )\r
 {\r
+volatile uint32_t ulx = 0;\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
 \r
        Artificially force an assert() to be triggered if configASSERT() is\r
        defined, then stop here so application writers can catch the error. */\r
-       configASSERT( uxCriticalNesting == ~0UL );\r
+       configASSERT( ulx == ~0UL );\r
        portDISABLE_INTERRUPTS();\r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/*\r
- * See header file for description.\r
- */\r
-StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\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
 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\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
+               /* 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 vPortEndScheduler( void )\r
+{\r
+       /* Not implemented. */\r
+       for( ;; );\r
+}\r
+\r
+\r
+\r
+\r
 \r