Update RISC-V port to use a separate interrupt stack.
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
index 28b4b04..139d1c8 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
@@ -34,6 +34,16 @@
 #include "task.h"

 #include "portmacro.h"

 

+#ifdef configISR_STACK_SIZE

+	/* The stack used by interrupt service routines. */

+	static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 };

+	const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & ~portBYTE_ALIGNMENT_MASK ) - 1 ] );

+#else

+#warning What should _sp be named?

+	extern const uint32_t _sp[];

+	const uint32_t xISRStackTop = ( uint32_t ) _sp;

+#endif

+

 /*

  * Setup the timer to generate the tick interrupts.  The implementation in this

  * file is weak to allow application writers to change the timer used to

@@ -54,6 +64,30 @@
 const uint32_t ulTimerIncrementsForOneTick = ( uint32_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */

 volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );

 

+/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task

+stack checking.  A problem in the ISR stack will trigger an assert, not call the

+stack overflow hook function (because the stack overflow hook is specific to a

+task stack, not the ISR stack). */

+#if( configCHECK_FOR_STACK_OVERFLOW > 2 )

+	#warning This path not tested, or even compiled yet.

+	/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for

+	the task stacks, and so will legitimately appear in many positions within

+	the ISR stack. */

+	#define portISR_STACK_FILL_BYTE	0xee

+

+	static const uint8_t ucExpectedStackBytes[] = {

+									portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,		\

+									portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,		\

+									portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,		\

+									portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE,		\

+									portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE };	\

+

+	#define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )

+#else

+	/* Define the function away. */

+	#define portCHECK_ISR_STACK()

+#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */

+

 /*-----------------------------------------------------------*/

 

 void prvTaskExitError( void )

@@ -194,22 +228,11 @@
 	/* Prepare the time to use after the next tick interrupt. */

 	ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;

 

-	/* Enable timer interrupt */

+	/* Enable timer interrupt. */

 	__asm volatile( "csrs mie, %0" :: "r"(0x80) ); /* 1<<7 for timer interrupt. */

 }

 /*-----------------------------------------------------------*/

 

-void Software_IRQHandler( void )

-{

-volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDRESS;

-

-	vTaskSwitchContext();

-

-	/* Clear software interrupt. */

-	*( ( uint32_t * ) configCLINT_BASE_ADDRESS ) &= 0x08UL;

-}

-/*-----------------------------------------------------------*/

-

 BaseType_t xPortStartScheduler( void )

 {

 extern void xPortStartFirstTask( void );

@@ -218,10 +241,15 @@
 	{

 		volatile uint32_t mtvec = 0;

 

-		/* Check the least significant two bits of mtvec are 00 - indicating single

-		vector mode. */

+		/* Check the least significant two bits of mtvec are 00 - indicating

+		single vector mode. */

 		__asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );

 		configASSERT( ( mtvec & 0x03UL ) == 0 );

+

+		/* Check alignment of the interrupt stack - which is the same as the

+		stack that was being used by main() prior to the scheduler being

+		started. */

+		configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );

 	}

 	#endif

 

diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
index 5f6c3a1..e9ba838 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
@@ -49,7 +49,7 @@
 .extern pullMachineTimerCompareRegister

 .extern pullNextTime

 .extern ulTimerIncrementsForOneTick

-

+.extern xISRStackTop

 

 /*-----------------------------------------------------------*/

 

@@ -136,14 +136,13 @@
 

 	csrr a0, mcause

 	csrr a1, mepc

-	mv a2, sp

 

 test_if_environment_call:

 	li t0, 11 								/* 11 == environment call when using qemu. */

 	bne a0, t0, test_if_timer

 	addi a1, a1, 4 							/* Synchronous so return to the instruction after the environment call. */

 	sw a1, 0( sp ) 							/* Save updated exception return address. */

-/*_RB_ Does stack need aligning here? */

+	lw sp, xISRStackTop						/* Switch to ISR stack before function call. */

 	jal vTaskSwitchContext

 	j processed_source

 

@@ -167,13 +166,15 @@
 	add t6, t3, t5							/* Add overflow to high word of ullNextTime. */

 	sw t4, 0(t1)							/* Store new low word of ullNextTime. */

 	sw t6, 4(t1)							/* Store new high word of ullNextTime. */

+	lw sp, xISRStackTop						/* Switch to ISR stack before function call. */

 	jal xTaskIncrementTick

 	beqz a0, processed_source				/* Don't switch context if incrementing tick didn't unblock a task. */

 	jal vTaskSwitchContext

 	j processed_source

 

 as_yet_unhandled:

-	j as_yet_unhandled 						/* External interrupt? */

+//	ebreak 						/* External interrupt? */

+	j as_yet_unhandled

 

 processed_source:

 	lw  sp, pxCurrentTCB					/* Load pxCurrentTCB. */

diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h
index 72b8b83..c0c1b6b 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h
@@ -70,8 +70,9 @@
 

 

 /* Scheduler utilities. */

-#define portYIELD() __asm volatile( "ecall" ); // software interrupt alternative *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) |= 0x08UL

-#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield()

+extern void vTaskSwitchContext( void );

+#define portYIELD() __asm volatile( "ecall" );

+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()

 #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )

 /*-----------------------------------------------------------*/

 

@@ -84,14 +85,39 @@
 extern void vTaskExitCritical( void );

 

 #define portSET_INTERRUPT_MASK_FROM_ISR() 0

-#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue )

-#define portDISABLE_INTERRUPTS()	__asm volatile( "csrc mstatus, 8" )

-#define portENABLE_INTERRUPTS()		__asm volatile( "csrs mstatus, 8" )

+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue

+#define portDISABLE_INTERRUPTS()	__asm volatile( "csrc mstatus, 8" ); __asm volatile( "fence" )

+#define portENABLE_INTERRUPTS()		__asm volatile( "csrs mstatus, 8" ); __asm volatile( "fence" )

 #define portENTER_CRITICAL()	vTaskEnterCritical()

 #define portEXIT_CRITICAL()		vTaskExitCritical()

 

 /*-----------------------------------------------------------*/

 

+/* Architecture specific optimisations. */

+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION

+	#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1

+#endif

+

+#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )

+

+	/* Check the configuration. */

+	#if( configMAX_PRIORITIES > 32 )

+		#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.

+	#endif

+

+	/* Store/clear the ready priorities in a bit map. */

+	#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )

+	#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )

+

+	/*-----------------------------------------------------------*/

+

+	#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - __builtin_clz( uxReadyPriorities ) )

+

+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */

+

+

+/*-----------------------------------------------------------*/

+

 /* Task function macros as described on the FreeRTOS.org WEB site.  These are

 not necessary for to use this port.  They are defined so the common demo files

 (which build with all the ports) will build. */

@@ -107,7 +133,6 @@
 #ifndef portFORCE_INLINE

 	#define portFORCE_INLINE inline __attribute__(( always_inline))

 #endif

-portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) {}

 

 #ifdef __cplusplus

 }