]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/IAR/RISC-V/port.c
Add IAR RISC-V port to SVN - a work in progress.
[freertos] / FreeRTOS / Source / portable / IAR / RISC-V / port.c
diff --git a/FreeRTOS/Source/portable/IAR/RISC-V/port.c b/FreeRTOS/Source/portable/IAR/RISC-V/port.c
new file mode 100644 (file)
index 0000000..025cb2f
--- /dev/null
@@ -0,0 +1,193 @@
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 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
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/*-----------------------------------------------------------\r
+ * Implementation of functions defined in portable.h for the RISC-V RV32 port.\r
+ *----------------------------------------------------------*/\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\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
+       StackType_t xISRStackTop = ( StackType_t ) 0;\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 ) __attribute__(( weak ));\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Used to program the machine timer compare register. */\r
+uint64_t ullNextTime = 0ULL;\r
+const uint64_t *pullNextTime = &ullNextTime;\r
+const size_t uxTimerIncrementsForOneTick = ( size_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */\r
+volatile uint64_t * const pullMachineTimerCompareRegister = ( uint64_t * ) ( 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
+#if( configCLINT_BASE_ADDRESS != 0 )\r
+\r
+       void vPortSetupTimerInterrupt( void )\r
+       {\r
+       uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;\r
+       volatile uint32_t * const pulTimeHigh = ( uint32_t * ) ( configCLINT_BASE_ADDRESS + 0xBFFC );\r
+       volatile uint32_t * const pulTimeLow = ( uint32_t * ) ( 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 ) uxTimerIncrementsForOneTick;\r
+               *pullMachineTimerCompareRegister = ullNextTime;\r
+\r
+               /* Prepare the time to use after the next tick interrupt. */\r
+               ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;\r
+       }\r
+\r
+#endif /* ( configCLINT_BASE_ADDRESS != 0 ) */\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xPortStartScheduler( void )\r
+{\r
+extern void xPortStartFirstTask( void );\r
+#warning Replicate this change in the GCC version.\r
+       #ifdef configISR_STACK_SIZE_WORDS\r
+               xISRStackTop = ( ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS - 1 ] ) & ~portBYTE_ALIGNMENT_MASK );\r
+       #endif\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, 0x305" : "=r"( mtvec ) ); /* 0x305 is 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 0x304, %0" :: "r"(0x880) ); /* 0x304 is mie. */\r
+       }\r
+       #else\r
+       {\r
+               /* Enable external interrupts. */\r
+               __asm volatile( "csrs 0x304, %0" :: "r"(0x800) ); /* 304 is mie. */\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