]> git.sur5r.net Git - freertos/commitdiff
Update RISC-V port to use a separate interrupt stack.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 4 Dec 2018 01:23:41 +0000 (01:23 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 4 Dec 2018 01:23:41 +0000 (01:23 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2598 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h

index 28b4b0477de4da0c98a703ec83ff7f8be8e21b0c..139d1c8336716b78f57a4b6b2c27e809f5dcb505 100644 (file)
 #include "task.h"\r
 #include "portmacro.h"\r
 \r
+#ifdef configISR_STACK_SIZE\r
+       /* The stack used by interrupt service routines. */\r
+       static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 };\r
+       const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & ~portBYTE_ALIGNMENT_MASK ) - 1 ] );\r
+#else\r
+#warning What should _sp be named?\r
+       extern const uint32_t _sp[];\r
+       const uint32_t xISRStackTop = ( uint32_t ) _sp;\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
@@ -54,6 +64,30 @@ const uint64_t *pullNextTime = &ullNextTime;
 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
@@ -194,22 +228,11 @@ volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLI
        /* Prepare the time to use after the next tick interrupt. */\r
        ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;\r
 \r
-       /* Enable timer interrupt */\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
 BaseType_t xPortStartScheduler( void )\r
 {\r
 extern void xPortStartFirstTask( void );\r
@@ -218,10 +241,15 @@ extern void xPortStartFirstTask( void );
        {\r
                volatile uint32_t mtvec = 0;\r
 \r
-               /* Check the least significant two bits of mtvec are 00 - indicating single\r
-               vector mode. */\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\r
 \r
index 5f6c3a10ed8db94f5040a120426351f931e42e55..e9ba83856fc8d67993de853e9b54006c54891e9a 100644 (file)
@@ -49,7 +49,7 @@
 .extern pullMachineTimerCompareRegister\r
 .extern pullNextTime\r
 .extern ulTimerIncrementsForOneTick\r
-\r
+.extern xISRStackTop\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -136,14 +136,13 @@ vPortTrapHandler:
 \r
        csrr a0, mcause\r
        csrr a1, mepc\r
-       mv a2, sp\r
 \r
 test_if_environment_call:\r
        li t0, 11                                                               /* 11 == environment call when using qemu. */\r
        bne a0, t0, test_if_timer\r
        addi a1, a1, 4                                                  /* Synchronous so return to the instruction after the environment call. */\r
        sw a1, 0( sp )                                                  /* Save updated exception return address. */\r
-/*_RB_ Does stack need aligning here? */\r
+       lw sp, xISRStackTop                                             /* Switch to ISR stack before function call. */\r
        jal vTaskSwitchContext\r
        j processed_source\r
 \r
@@ -167,13 +166,15 @@ test_if_timer:
        add t6, t3, t5                                                  /* Add overflow to high word of ullNextTime. */\r
        sw t4, 0(t1)                                                    /* Store new low word of ullNextTime. */\r
        sw t6, 4(t1)                                                    /* Store new high word of ullNextTime. */\r
+       lw sp, xISRStackTop                                             /* Switch to ISR stack before function call. */\r
        jal xTaskIncrementTick\r
        beqz a0, processed_source                               /* Don't switch context if incrementing tick didn't unblock a task. */\r
        jal vTaskSwitchContext\r
        j processed_source\r
 \r
 as_yet_unhandled:\r
-       j as_yet_unhandled                                              /* External interrupt? */\r
+//     ebreak                                          /* External interrupt? */\r
+       j as_yet_unhandled\r
 \r
 processed_source:\r
        lw  sp, pxCurrentTCB                                    /* Load pxCurrentTCB. */\r
index 72b8b8392e76978fd5fb5a04d3a4a817beed2ba9..c0c1b6b095bb9a07e3d7b6e7113f95bbdff762e1 100644 (file)
@@ -70,8 +70,9 @@ not need to be guarded with a critical section. */
 \r
 \r
 /* Scheduler utilities. */\r
-#define portYIELD() __asm volatile( "ecall" ); // software interrupt alternative *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) |= 0x08UL\r
-#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield()\r
+extern void vTaskSwitchContext( void );\r
+#define portYIELD() __asm volatile( "ecall" );\r
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()\r
 #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -84,12 +85,37 @@ extern void vTaskEnterCritical( void );
 extern void vTaskExitCritical( void );\r
 \r
 #define portSET_INTERRUPT_MASK_FROM_ISR() 0\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue )\r
-#define portDISABLE_INTERRUPTS()       __asm volatile( "csrc mstatus, 8" )\r
-#define portENABLE_INTERRUPTS()                __asm volatile( "csrs mstatus, 8" )\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue\r
+#define portDISABLE_INTERRUPTS()       __asm volatile( "csrc mstatus, 8" ); __asm volatile( "fence" )\r
+#define portENABLE_INTERRUPTS()                __asm volatile( "csrs mstatus, 8" ); __asm volatile( "fence" )\r
 #define portENTER_CRITICAL()   vTaskEnterCritical()\r
 #define portEXIT_CRITICAL()            vTaskExitCritical()\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
+/* Architecture specific optimisations. */\r
+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION\r
+       #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1\r
+#endif\r
+\r
+#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )\r
+\r
+       /* Check the configuration. */\r
+       #if( configMAX_PRIORITIES > 32 )\r
+               #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.\r
+       #endif\r
+\r
+       /* Store/clear the ready priorities in a bit map. */\r
+       #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )\r
+       #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )\r
+\r
+       /*-----------------------------------------------------------*/\r
+\r
+       #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - __builtin_clz( uxReadyPriorities ) )\r
+\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
@@ -107,7 +133,6 @@ not necessary for to use this port.  They are defined so the common demo files
 #ifndef portFORCE_INLINE\r
        #define portFORCE_INLINE inline __attribute__(( always_inline))\r
 #endif\r
-portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) {}\r
 \r
 #ifdef __cplusplus\r
 }\r