mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-20 05:21:59 -04:00
Update RISC-V port to use a separate interrupt stack.
This commit is contained in:
parent
e85ea96f78
commit
65f7a2dc19
|
@ -34,6 +34,16 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "portmacro.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
|
* 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
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
@ -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. */
|
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 );
|
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 )
|
void prvTaskExitError( void )
|
||||||
|
@ -194,22 +228,11 @@ volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLI
|
||||||
/* Prepare the time to use after the next tick interrupt. */
|
/* Prepare the time to use after the next tick interrupt. */
|
||||||
ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;
|
ullNextTime += ( uint64_t ) ulTimerIncrementsForOneTick;
|
||||||
|
|
||||||
/* Enable timer interrupt */
|
/* Enable timer interrupt. */
|
||||||
__asm volatile( "csrs mie, %0" :: "r"(0x80) ); /* 1<<7 for 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 )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
extern void xPortStartFirstTask( void );
|
extern void xPortStartFirstTask( void );
|
||||||
|
@ -218,10 +241,15 @@ extern void xPortStartFirstTask( void );
|
||||||
{
|
{
|
||||||
volatile uint32_t mtvec = 0;
|
volatile uint32_t mtvec = 0;
|
||||||
|
|
||||||
/* Check the least significant two bits of mtvec are 00 - indicating single
|
/* Check the least significant two bits of mtvec are 00 - indicating
|
||||||
vector mode. */
|
single vector mode. */
|
||||||
__asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );
|
__asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );
|
||||||
configASSERT( ( mtvec & 0x03UL ) == 0 );
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
.extern pullMachineTimerCompareRegister
|
.extern pullMachineTimerCompareRegister
|
||||||
.extern pullNextTime
|
.extern pullNextTime
|
||||||
.extern ulTimerIncrementsForOneTick
|
.extern ulTimerIncrementsForOneTick
|
||||||
|
.extern xISRStackTop
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -136,14 +136,13 @@ vPortTrapHandler:
|
||||||
|
|
||||||
csrr a0, mcause
|
csrr a0, mcause
|
||||||
csrr a1, mepc
|
csrr a1, mepc
|
||||||
mv a2, sp
|
|
||||||
|
|
||||||
test_if_environment_call:
|
test_if_environment_call:
|
||||||
li t0, 11 /* 11 == environment call when using qemu. */
|
li t0, 11 /* 11 == environment call when using qemu. */
|
||||||
bne a0, t0, test_if_timer
|
bne a0, t0, test_if_timer
|
||||||
addi a1, a1, 4 /* Synchronous so return to the instruction after the environment call. */
|
addi a1, a1, 4 /* Synchronous so return to the instruction after the environment call. */
|
||||||
sw a1, 0( sp ) /* Save updated exception return address. */
|
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
|
jal vTaskSwitchContext
|
||||||
j processed_source
|
j processed_source
|
||||||
|
|
||||||
|
@ -167,13 +166,15 @@ test_if_timer:
|
||||||
add t6, t3, t5 /* Add overflow to high word of ullNextTime. */
|
add t6, t3, t5 /* Add overflow to high word of ullNextTime. */
|
||||||
sw t4, 0(t1) /* Store new low word of ullNextTime. */
|
sw t4, 0(t1) /* Store new low word of ullNextTime. */
|
||||||
sw t6, 4(t1) /* Store new high 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
|
jal xTaskIncrementTick
|
||||||
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
|
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
|
||||||
jal vTaskSwitchContext
|
jal vTaskSwitchContext
|
||||||
j processed_source
|
j processed_source
|
||||||
|
|
||||||
as_yet_unhandled:
|
as_yet_unhandled:
|
||||||
j as_yet_unhandled /* External interrupt? */
|
// ebreak /* External interrupt? */
|
||||||
|
j as_yet_unhandled
|
||||||
|
|
||||||
processed_source:
|
processed_source:
|
||||||
lw sp, pxCurrentTCB /* Load pxCurrentTCB. */
|
lw sp, pxCurrentTCB /* Load pxCurrentTCB. */
|
||||||
|
|
|
@ -70,8 +70,9 @@ not need to be guarded with a critical section. */
|
||||||
|
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
#define portYIELD() __asm volatile( "ecall" ); // software interrupt alternative *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) |= 0x08UL
|
extern void vTaskSwitchContext( void );
|
||||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield()
|
#define portYIELD() __asm volatile( "ecall" );
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
|
||||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -84,12 +85,37 @@ extern void vTaskEnterCritical( void );
|
||||||
extern void vTaskExitCritical( void );
|
extern void vTaskExitCritical( void );
|
||||||
|
|
||||||
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
|
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
|
||||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue )
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
|
||||||
#define portDISABLE_INTERRUPTS() __asm volatile( "csrc mstatus, 8" )
|
#define portDISABLE_INTERRUPTS() __asm volatile( "csrc mstatus, 8" ); __asm volatile( "fence" )
|
||||||
#define portENABLE_INTERRUPTS() __asm volatile( "csrs mstatus, 8" )
|
#define portENABLE_INTERRUPTS() __asm volatile( "csrs mstatus, 8" ); __asm volatile( "fence" )
|
||||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
#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
|
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||||
|
@ -107,7 +133,6 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#ifndef portFORCE_INLINE
|
#ifndef portFORCE_INLINE
|
||||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||||
#endif
|
#endif
|
||||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) {}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue