Revert #768 on the XCC/Xtensa portable files (#948)

pull/914/head^2
Soren Ptak 1 year ago committed by GitHub
parent 94cb87ad30
commit 529de5606e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -37,39 +37,34 @@
/* Defined in portasm.h */ /* Defined in portasm.h */
extern void _frxt_tick_timer_init( void ); extern void _frxt_tick_timer_init(void);
/* Defined in xtensa_context.S */ /* Defined in xtensa_context.S */
extern void _xt_coproc_init( void ); extern void _xt_coproc_init(void);
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
* any details of its type. */ any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
unsigned port_xSchedulerRunning = 0; /* Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting */ unsigned port_xSchedulerRunning = 0; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
unsigned port_interruptNesting = 0; /* Interrupt nesting level */ unsigned port_interruptNesting = 0; // Interrupt nesting level
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* User exception dispatcher when exiting */ // User exception dispatcher when exiting
void _xt_user_exit( void ); void _xt_user_exit(void);
/* /*
* Stack initialization * Stack initialization
*/ */
#if portUSING_MPU_WRAPPERS #if portUSING_MPU_WRAPPERS
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged )
#else #else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
#endif #endif
{ {
StackType_t * sp; StackType_t * sp;
@ -134,18 +129,18 @@ void _xt_user_exit( void );
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the Xtensa port will get stopped. If required simply /* It is unlikely that the Xtensa port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored */ // Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0
/* Initialize co-processor management for tasks. Leave CPENABLE alone. */ /* Initialize co-processor management for tasks. Leave CPENABLE alone. */
_xt_coproc_init(); _xt_coproc_init();
#endif #endif
/* Init the tick divisor value */ /* Init the tick divisor value */
@ -155,14 +150,14 @@ BaseType_t xPortStartScheduler( void )
_frxt_tick_timer_init(); _frxt_tick_timer_init();
#if XT_USE_THREAD_SAFE_CLIB #if XT_USE_THREAD_SAFE_CLIB
/* Init C library */ // Init C library
vPortClibInit(); vPortClibInit();
#endif #endif
port_xSchedulerRunning = 1; port_xSchedulerRunning = 1;
/* Cannot be directly called from C; never returns */ // Cannot be directly called from C; never returns
__asm__ volatile ( "call0 _frxt_dispatch\n" ); __asm__ volatile ("call0 _frxt_dispatch\n");
/* Should not get here. */ /* Should not get here. */
return pdTRUE; return pdTRUE;
@ -195,19 +190,19 @@ BaseType_t xPortSysTickHandler( void )
* Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area. * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
*/ */
#if portUSING_MPU_WRAPPERS #if portUSING_MPU_WRAPPERS
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions, const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack, StackType_t * pxBottomOfStack,
uint32_t ulStackDepth ) uint32_t ulStackDepth )
{ {
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + ulStackDepth - 1 ) ); xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + ulStackDepth - 1 ));
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf ); xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf );
/* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to
* clear the stack area after we return. This is done in pxPortInitialiseStack(). * clear the stack area after we return. This is done in pxPortInitialiseStack().
*/ */
#endif #endif
} }
#endif /* if portUSING_MPU_WRAPPERS */ #endif /* if portUSING_MPU_WRAPPERS */

@ -42,7 +42,7 @@
#endif #endif
#define portbenchmarkINTERRUPT_DISABLE() #define portbenchmarkINTERRUPT_DISABLE()
#define portbenchmarkINTERRUPT_RESTORE( newstate ) #define portbenchmarkINTERRUPT_RESTORE(newstate)
#define portbenchmarkIntLatency() #define portbenchmarkIntLatency()
#define portbenchmarkIntWait() #define portbenchmarkIntWait()
#define portbenchmarkReset() #define portbenchmarkReset()

@ -31,204 +31,200 @@
#if XT_USE_THREAD_SAFE_CLIB #if XT_USE_THREAD_SAFE_CLIB
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB #if XSHAL_CLIB == XTHAL_CLIB_XCLIB
#include <errno.h> #include <errno.h>
#include <sys/reent.h> #include <sys/reent.h>
#include "semphr.h" #include "semphr.h"
typedef SemaphoreHandle_t _Rmtx; typedef SemaphoreHandle_t _Rmtx;
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
/* Override this and set to nonzero to enable locking. */ // Override this and set to nonzero to enable locking.
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
int32_t _xclib_use_mt = 1; int32_t _xclib_use_mt = 1;
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
/* Init lock. */ // Init lock.
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
void _Mtxinit( _Rmtx * mtx ) void
{ _Mtxinit(_Rmtx * mtx)
*mtx = xSemaphoreCreateRecursiveMutex(); {
} *mtx = xSemaphoreCreateRecursiveMutex();
}
/*----------------------------------------------------------------------------- */
/* Destroy lock. */ //-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ // Destroy lock.
void _Mtxdst( _Rmtx * mtx ) //-----------------------------------------------------------------------------
{ void
if( ( mtx != NULL ) && ( *mtx != NULL ) ) _Mtxdst(_Rmtx * mtx)
{ {
vSemaphoreDelete( *mtx ); if ((mtx != NULL) && (*mtx != NULL)) {
} vSemaphoreDelete(*mtx);
} }
}
/*----------------------------------------------------------------------------- */
/* Lock. */ //-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ // Lock.
void _Mtxlock( _Rmtx * mtx ) //-----------------------------------------------------------------------------
{ void
if( ( mtx != NULL ) && ( *mtx != NULL ) ) _Mtxlock(_Rmtx * mtx)
{ {
xSemaphoreTakeRecursive( *mtx, portMAX_DELAY ); if ((mtx != NULL) && (*mtx != NULL)) {
} xSemaphoreTakeRecursive(*mtx, portMAX_DELAY);
} }
}
/*----------------------------------------------------------------------------- */
/* Unlock. */ //-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ // Unlock.
void _Mtxunlock( _Rmtx * mtx ) //-----------------------------------------------------------------------------
{ void
if( ( mtx != NULL ) && ( *mtx != NULL ) ) _Mtxunlock(_Rmtx * mtx)
{ {
xSemaphoreGiveRecursive( *mtx ); if ((mtx != NULL) && (*mtx != NULL)) {
} xSemaphoreGiveRecursive(*mtx);
} }
}
/*----------------------------------------------------------------------------- */
/* Called by malloc() to allocate blocks of memory from the heap. */ //-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ // Called by malloc() to allocate blocks of memory from the heap.
void * _sbrk_r( struct _reent * reent, //-----------------------------------------------------------------------------
int32_t incr ) void *
{ _sbrk_r (struct _reent * reent, int32_t incr)
extern char _end; {
extern char _heap_sentry; extern char _end;
static char * _heap_sentry_ptr = &_heap_sentry; extern char _heap_sentry;
static char * heap_ptr; static char * _heap_sentry_ptr = &_heap_sentry;
char * base; static char * heap_ptr;
char * base;
if( !heap_ptr )
{ if (!heap_ptr)
heap_ptr = ( char * ) &_end; heap_ptr = (char *) &_end;
}
base = heap_ptr;
base = heap_ptr; if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
if( heap_ptr + incr >= _heap_sentry_ptr ) return (char *) -1;
{ }
reent->_errno = ENOMEM;
return ( char * ) -1; heap_ptr += incr;
} return base;
}
heap_ptr += incr;
return base; //-----------------------------------------------------------------------------
} // Global initialization for C library.
//-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ void
/* Global initialization for C library. */ vPortClibInit(void)
/*----------------------------------------------------------------------------- */ {
void vPortClibInit( void ) }
{
} //-----------------------------------------------------------------------------
// Per-thread cleanup stub provided for linking, does nothing.
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
/* Per-thread cleanup stub provided for linking, does nothing. */ void
/*----------------------------------------------------------------------------- */ _reclaim_reent(void * ptr)
void _reclaim_reent( void * ptr ) {
{ }
}
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#include <errno.h>
#include <errno.h> #include <malloc.h>
#include <malloc.h> #include <stdio.h>
#include <stdio.h> #include <stdlib.h>
#include <stdlib.h> #include <string.h>
#include <string.h>
#include "semphr.h"
#include "semphr.h"
static SemaphoreHandle_t xClibMutex;
static SemaphoreHandle_t xClibMutex; static uint32_t ulClibInitDone = 0;
static uint32_t ulClibInitDone = 0;
//-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ // Get C library lock.
/* Get C library lock. */ //-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ void
void __malloc_lock( struct _reent * ptr ) __malloc_lock(struct _reent * ptr)
{ {
if( !ulClibInitDone ) if (!ulClibInitDone)
{ return;
return;
} xSemaphoreTakeRecursive(xClibMutex, portMAX_DELAY);
}
xSemaphoreTakeRecursive( xClibMutex, portMAX_DELAY );
} //-----------------------------------------------------------------------------
// Release C library lock.
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
/* Release C library lock. */ void
/*----------------------------------------------------------------------------- */ __malloc_unlock(struct _reent * ptr)
void __malloc_unlock( struct _reent * ptr ) {
{ if (!ulClibInitDone)
if( !ulClibInitDone ) return;
{
return; xSemaphoreGiveRecursive(xClibMutex);
} }
xSemaphoreGiveRecursive( xClibMutex ); //-----------------------------------------------------------------------------
} // Lock for environment. Since we have only one global lock we can just call
// the malloc() lock function.
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
/* Lock for environment. Since we have only one global lock we can just call */ void
/* the malloc() lock function. */ __env_lock(struct _reent * ptr)
/*----------------------------------------------------------------------------- */ {
void __env_lock( struct _reent * ptr ) __malloc_lock(ptr);
{ }
__malloc_lock( ptr );
}
//-----------------------------------------------------------------------------
// Unlock environment.
/*----------------------------------------------------------------------------- */ //-----------------------------------------------------------------------------
/* Unlock environment. */ void
/*----------------------------------------------------------------------------- */ __env_unlock(struct _reent * ptr)
void __env_unlock( struct _reent * ptr ) {
{ __malloc_unlock(ptr);
__malloc_unlock( ptr ); }
}
//-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ // Called by malloc() to allocate blocks of memory from the heap.
/* Called by malloc() to allocate blocks of memory from the heap. */ //-----------------------------------------------------------------------------
/*----------------------------------------------------------------------------- */ void *
void * _sbrk_r( struct _reent * reent, _sbrk_r (struct _reent * reent, int32_t incr)
int32_t incr ) {
{ extern char _end;
extern char _end; extern char _heap_sentry;
extern char _heap_sentry; static char * _heap_sentry_ptr = &_heap_sentry;
static char * _heap_sentry_ptr = &_heap_sentry; static char * heap_ptr;
static char * heap_ptr; char * base;
char * base;
if (!heap_ptr)
if( !heap_ptr ) heap_ptr = (char *) &_end;
{
heap_ptr = ( char * ) &_end; base = heap_ptr;
} if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
base = heap_ptr; return (char *) -1;
}
if( heap_ptr + incr >= _heap_sentry_ptr )
{ heap_ptr += incr;
reent->_errno = ENOMEM; return base;
return ( char * ) -1; }
}
//-----------------------------------------------------------------------------
heap_ptr += incr; // Global initialization for C library.
return base; //-----------------------------------------------------------------------------
} void
vPortClibInit(void)
/*----------------------------------------------------------------------------- */ {
/* Global initialization for C library. */ configASSERT(!ulClibInitDone);
/*----------------------------------------------------------------------------- */
void vPortClibInit( void ) xClibMutex = xSemaphoreCreateRecursiveMutex();
{ ulClibInitDone = 1;
configASSERT( !ulClibInitDone ); }
xClibMutex = xSemaphoreCreateRecursiveMutex(); #endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
ulClibInitDone = 1;
}
#endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
#endif /* XT_USE_THREAD_SAFE_CLIB */ #endif /* XT_USE_THREAD_SAFE_CLIB */

@ -38,15 +38,15 @@
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#include <stdint.h> #include <stdint.h>
#include <xtensa/tie/xt_core.h> #include <xtensa/tie/xt_core.h>
#include <xtensa/hal.h> #include <xtensa/hal.h>
#include <xtensa/config/core.h> #include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */ #include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h> #include <xtensa/xtruntime.h>
/*#include "xtensa_context.h" */ //#include "xtensa_context.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -60,159 +60,149 @@
/* Type definitions. */ /* Type definitions. */
#define portCHAR int8_t #define portCHAR int8_t
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG int32_t #define portLONG int32_t
#define portSHORT int16_t #define portSHORT int16_t
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE int #define portBASE_TYPE int
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t; typedef portBASE_TYPE BaseType_t;
typedef unsigned portBASE_TYPE UBaseType_t; typedef unsigned portBASE_TYPE UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#else #else
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* portbenchmark */ // portbenchmark
#include "portbenchmark.h" #include "portbenchmark.h"
/* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */ /* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */
/* These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. */ // These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level.
#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL ); portbenchmarkINTERRUPT_DISABLE(); } while( 0 ) #define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE( 0 ); XTOS_SET_INTLEVEL( 0 ); } while( 0 ) #define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
/* These can be nested */ // These can be nested
#define portCRITICAL_NESTING_IN_TCB 1 /* For now, let FreeRTOS' (tasks.c) manage critical nesting */ #define portCRITICAL_NESTING_IN_TCB 1 // For now, let FreeRTOS' (tasks.c) manage critical nesting
void vTaskEnterCritical( void ); void vTaskEnterCritical(void);
void vTaskExitCritical( void ); void vTaskExitCritical(void);
#define portENTER_CRITICAL() vTaskEnterCritical() #define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical() #define portEXIT_CRITICAL() vTaskExitCritical()
/* Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack. */ // Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack.
/* They can be called from interrupts too. */ // They can be called from interrupts too.
static inline unsigned portENTER_CRITICAL_NESTED() static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); return state; }
{ #define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0)
unsigned state = XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL );
// These FreeRTOS versions are similar to the nested versions above
portbenchmarkINTERRUPT_DISABLE(); #define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED()
return state; #define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state)
}
#define portEXIT_CRITICAL_NESTED( state ) do { portbenchmarkINTERRUPT_RESTORE( state ); XTOS_RESTORE_JUST_INTLEVEL( state ); } while( 0 )
/* These FreeRTOS versions are similar to the nested versions above */
#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( state ) portEXIT_CRITICAL_NESTED( state )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portNOP() XT_NOP() #define portNOP() XT_NOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Fine resolution time */ /* Fine resolution time */
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount() #define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
/* Kernel utilities. */ /* Kernel utilities. */
void vPortYield( void ); void vPortYield( void );
void _frxt_setup_switch( void ); void _frxt_setup_switch( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) \ #define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) \
if( ( xHigherPriorityTaskWoken ) != 0 ) { \ if ( ( xHigherPriorityTaskWoken ) != 0 ) { \
_frxt_setup_switch(); \ _frxt_setup_switch(); \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* When coprocessors are defined, we to maintain a pointer to coprocessors area. */ // When coprocessors are defined, we to maintain a pointer to coprocessors area.
/* We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: */ // We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold:
/* MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. */ // MPU wrappers, coprocessor area pointer, trace code structure, and more if needed.
/* The field is normally used for memory protection. FreeRTOS should create another general purpose field. */ // The field is normally used for memory protection. FreeRTOS should create another general purpose field.
typedef struct typedef struct {
{ #if XCHAL_CP_NUM > 0
#if XCHAL_CP_NUM > 0 volatile StackType_t* coproc_area; // Pointer to coprocessor save area; MUST BE FIRST
volatile StackType_t * coproc_area; /* Pointer to coprocessor save area; MUST BE FIRST */
#endif
#if portUSING_MPU_WRAPPERS
/* Define here mpu_settings, which is port dependent */
int mpu_setting; /* Just a dummy example here; MPU not ported to Xtensa yet */
#endif
#if configUSE_TRACE_FACILITY_2
struct
{
/* Cf. porttraceStamp() */
int taskstamp; /* Stamp from inside task to see where we are */
int taskstampcount; /* A counter usually incremented when we restart the task's loop */
} porttrace;
#endif
} xMPU_SETTINGS;
/* Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) */
#if ( XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2 ) && !portUSING_MPU_WRAPPERS /* If MPU wrappers not used, we still need to allocate coproc area */
#undef portUSING_MPU_WRAPPERS
#define portUSING_MPU_WRAPPERS 1 /* Enable it to allocate coproc area */
#define MPU_WRAPPERS_H /* Override mpu_wrapper.h to disable unwanted code */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA
#endif #endif
/* porttrace */ #if portUSING_MPU_WRAPPERS
#if configUSE_TRACE_FACILITY_2 // Define here mpu_settings, which is port dependent
#include "porttrace.h" int mpu_setting; // Just a dummy example here; MPU not ported to Xtensa yet
#endif #endif
/* configASSERT_2 if requested */ #if configUSE_TRACE_FACILITY_2
#if configASSERT_2 struct {
#include <stdio.h> // Cf. porttraceStamp()
void exit( int ); int taskstamp; /* Stamp from inside task to see where we are */
#define configASSERT( x ) if( !( x ) ) { porttracePrint( -1 ); printf( "\nAssertion failed in %s:%d\n", __FILE__, __LINE__ ); exit( -1 ); } int taskstampcount; /* A counter usually incremented when we restart the task's loop */
} porttrace;
#endif #endif
} xMPU_SETTINGS;
// Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS)
#if (XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2) && !portUSING_MPU_WRAPPERS // If MPU wrappers not used, we still need to allocate coproc area
#undef portUSING_MPU_WRAPPERS
#define portUSING_MPU_WRAPPERS 1 // Enable it to allocate coproc area
#define MPU_WRAPPERS_H // Override mpu_wrapper.h to disable unwanted code
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA
#endif
// porttrace
#if configUSE_TRACE_FACILITY_2
#include "porttrace.h"
#endif
// configASSERT_2 if requested
#if configASSERT_2
#include <stdio.h>
void exit(int);
#define configASSERT( x ) if (!(x)) { porttracePrint(-1); printf("\nAssertion failed in %s:%d\n", __FILE__, __LINE__); exit(-1); }
#endif
/* C library support -- only XCLIB and NEWLIB are supported. */ /* C library support -- only XCLIB and NEWLIB are supported. */
/* To enable thread-safe C library support, XT_USE_THREAD_SAFE_CLIB must be /* To enable thread-safe C library support, XT_USE_THREAD_SAFE_CLIB must be
* defined to be > 0 somewhere above or on the command line. */ defined to be > 0 somewhere above or on the command line. */
#if ( XT_USE_THREAD_SAFE_CLIB > 0u ) && ( XSHAL_CLIB == XTHAL_CLIB_XCLIB ) #if (XT_USE_THREAD_SAFE_CLIB > 0u) && (XSHAL_CLIB == XTHAL_CLIB_XCLIB)
extern void vPortClibInit( void ); extern void vPortClibInit(void);
#endif // XCLIB support #endif // XCLIB support
#if ( XT_USE_THREAD_SAFE_CLIB > 0u ) && ( XSHAL_CLIB == XTHAL_CLIB_NEWLIB ) #if (XT_USE_THREAD_SAFE_CLIB > 0u) && (XSHAL_CLIB == XTHAL_CLIB_NEWLIB)
extern void vPortClibInit( void ); extern void vPortClibInit(void);
/* This C library cleanup is not currently done by FreeRTOS when deleting a task */ // This C library cleanup is not currently done by FreeRTOS when deleting a task
#include <stdio.h> #include <stdio.h>
#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTcbClib( &( ( pxTCB )->xNewLib_reent ) ) #define portCLEAN_UP_TCB(pxTCB) vPortCleanUpTcbClib(&((pxTCB)->xNewLib_reent))
static inline void vPortCleanUpTcbClib( struct _reent * ptr ) static inline void vPortCleanUpTcbClib(struct _reent *ptr)
{ {
FILE * fp = &( ptr->__sf[ 0 ] ); FILE * fp = &(ptr->__sf[0]);
int i; int i;
for (i = 0; i < 3; ++i, ++fp) {
for( i = 0; i < 3; ++i, ++fp ) fp->_close = NULL;
{ }
fp->_close = NULL; }
} #endif // NEWLIB support
}
#endif // NEWLIB support
#endif // __ASSEMBLER__ #endif // __ASSEMBLER__

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -43,7 +43,7 @@
#error "You need to download the FreeRTOS_trace patch that overwrites this file" #error "You need to download the FreeRTOS_trace patch that overwrites this file"
#endif #endif
#define porttracePrint( nelements ) #define porttracePrint(nelements)
#define porttraceStamp( stamp, count_incr ) #define porttraceStamp(stamp, count_incr)
#endif /* PORTTRACE_H */ #endif /* PORTTRACE_H */

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -40,90 +40,87 @@
/* Typedef for C-callable interrupt handler function */ /* Typedef for C-callable interrupt handler function */
typedef void (* xt_handler)( void * ); typedef void (*xt_handler)(void *);
/* Typedef for C-callable exception handler function */ /* Typedef for C-callable exception handler function */
typedef void (* xt_exc_handler)( XtExcFrame * ); typedef void (*xt_exc_handler)(XtExcFrame *);
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Call this function to set a handler for the specified exception. Call this function to set a handler for the specified exception.
*
* n - Exception number (type) n - Exception number (type)
* f - Handler function address, NULL to uninstall handler. f - Handler function address, NULL to uninstall handler.
*
* The handler will be passed a pointer to the exception frame, which is created The handler will be passed a pointer to the exception frame, which is created
* on the stack of the thread that caused the exception. on the stack of the thread that caused the exception.
*
* If the handler returns, the thread context will be restored and the faulting If the handler returns, the thread context will be restored and the faulting
* instruction will be retried. Any values in the exception frame that are instruction will be retried. Any values in the exception frame that are
* modified by the handler will be restored as part of the context. For details modified by the handler will be restored as part of the context. For details
* of the exception frame structure see xtensa_context.h. of the exception frame structure see xtensa_context.h.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
extern xt_exc_handler xt_set_exception_handler( int n, extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f);
xt_exc_handler f );
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Call this function to set a handler for the specified interrupt. Call this function to set a handler for the specified interrupt.
*
* n - Interrupt number. n - Interrupt number.
* f - Handler function address, NULL to uninstall handler. f - Handler function address, NULL to uninstall handler.
* arg - Argument to be passed to handler. arg - Argument to be passed to handler.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
extern xt_handler xt_set_interrupt_handler( int n, extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg);
xt_handler f,
void * arg );
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Call this function to enable the specified interrupts. Call this function to enable the specified interrupts.
*
* mask - Bit mask of interrupts to be enabled. mask - Bit mask of interrupts to be enabled.
*
* Returns the previous state of the interrupt enables. Returns the previous state of the interrupt enables.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
extern unsigned int xt_ints_on( unsigned int mask ); extern unsigned int xt_ints_on(unsigned int mask);
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Call this function to disable the specified interrupts. Call this function to disable the specified interrupts.
*
* mask - Bit mask of interrupts to be disabled. mask - Bit mask of interrupts to be disabled.
*
* Returns the previous state of the interrupt enables. Returns the previous state of the interrupt enables.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
extern unsigned int xt_ints_off( unsigned int mask ); extern unsigned int xt_ints_off(unsigned int mask);
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Call this function to set the specified (s/w) interrupt. Call this function to set the specified (s/w) interrupt.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
static inline void xt_set_intset( unsigned int arg ) static inline void xt_set_intset(unsigned int arg)
{ {
xthal_set_intset( arg ); xthal_set_intset(arg);
} }
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Call this function to clear the specified (s/w or edge-triggered) Call this function to clear the specified (s/w or edge-triggered)
* interrupt. interrupt.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
static inline void xt_set_intclear( unsigned int arg ) static inline void xt_set_intclear(unsigned int arg)
{ {
xthal_set_intclear( arg ); xthal_set_intclear(arg);
} }

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -47,139 +47,139 @@
#include <xtensa/hal.h> #include <xtensa/hal.h>
#include <xtensa/config/core.h> #include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */ #include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include "xtensa_context.h" #include "xtensa_context.h"
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
* STACK REQUIREMENTS * STACK REQUIREMENTS
* *
* This section defines the minimum stack size, and the extra space required to * This section defines the minimum stack size, and the extra space required to
* be allocated for saving coprocessor state and/or C library state information * be allocated for saving coprocessor state and/or C library state information
* (if thread safety is enabled for the C library). The sizes are in bytes. * (if thread safety is enabled for the C library). The sizes are in bytes.
* *
* Stack sizes for individual tasks should be derived from these minima based on * Stack sizes for individual tasks should be derived from these minima based on
* the maximum call depth of the task and the maximum level of interrupt nesting. * the maximum call depth of the task and the maximum level of interrupt nesting.
* A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based * A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based
* on the requirement for a task that calls nothing else but can be interrupted. * on the requirement for a task that calls nothing else but can be interrupted.
* This assumes that interrupt handlers do not call more than a few levels deep. * This assumes that interrupt handlers do not call more than a few levels deep.
* If this is not true, i.e. one or more interrupt handlers make deep calls then * If this is not true, i.e. one or more interrupt handlers make deep calls then
* the minimum must be increased. * the minimum must be increased.
* *
* If the Xtensa processor configuration includes coprocessors, then space is * If the Xtensa processor configuration includes coprocessors, then space is
* allocated to save the coprocessor state on the stack. * allocated to save the coprocessor state on the stack.
* *
* If thread safety is enabled for the C runtime library, (XT_USE_THREAD_SAFE_CLIB * If thread safety is enabled for the C runtime library, (XT_USE_THREAD_SAFE_CLIB
* is defined) then space is allocated to save the C library context in the TCB. * is defined) then space is allocated to save the C library context in the TCB.
* *
* Allocating insufficient stack space is a common source of hard-to-find errors. * Allocating insufficient stack space is a common source of hard-to-find errors.
* During development, it is best to enable the FreeRTOS stack checking features. * During development, it is best to enable the FreeRTOS stack checking features.
* *
* Usage: * Usage:
* *
* XT_USE_THREAD_SAFE_CLIB -- Define this to a nonzero value to enable thread-safe * XT_USE_THREAD_SAFE_CLIB -- Define this to a nonzero value to enable thread-safe
* use of the C library. This will require extra stack * use of the C library. This will require extra stack
* space to be allocated for tasks that use the C library * space to be allocated for tasks that use the C library
* reentrant functions. See below for more information. * reentrant functions. See below for more information.
* *
* NOTE: The Xtensa toolchain supports multiple C libraries and not all of them * NOTE: The Xtensa toolchain supports multiple C libraries and not all of them
* support thread safety. Check your core configuration to see which C library * support thread safety. Check your core configuration to see which C library
* was chosen for your system. * was chosen for your system.
* *
* XT_STACK_MIN_SIZE -- The minimum stack size for any task. It is recommended * XT_STACK_MIN_SIZE -- The minimum stack size for any task. It is recommended
* that you do not use a stack smaller than this for any * that you do not use a stack smaller than this for any
* task. In case you want to use stacks smaller than this * task. In case you want to use stacks smaller than this
* size, you must verify that the smaller size(s) will work * size, you must verify that the smaller size(s) will work
* under all operating conditions. * under all operating conditions.
* *
* XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task * XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task
* that does not make C library reentrant calls. Add this * that does not make C library reentrant calls. Add this
* to the amount of stack space required by the task itself. * to the amount of stack space required by the task itself.
* *
* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state. * XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state.
* *
* -----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
/* Extra space required for interrupt/exception hooks. */ /* Extra space required for interrupt/exception hooks. */
#ifdef XT_INTEXC_HOOKS #ifdef XT_INTEXC_HOOKS
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
#define STK_INTEXC_EXTRA 0x200 #define STK_INTEXC_EXTRA 0x200
#else #else
#define STK_INTEXC_EXTRA 0x180 #define STK_INTEXC_EXTRA 0x180
#endif #endif
#else #else
#define STK_INTEXC_EXTRA 0 #define STK_INTEXC_EXTRA 0
#endif #endif
/* Check C library thread safety support and compute size of C library save area. /* Check C library thread safety support and compute size of C library save area.
* For the supported libraries, we enable thread safety by default, and this can For the supported libraries, we enable thread safety by default, and this can
* be overridden from the compiler/make command line. */ be overridden from the compiler/make command line. */
#if ( XSHAL_CLIB == XTHAL_CLIB_NEWLIB ) || ( XSHAL_CLIB == XTHAL_CLIB_XCLIB ) #if (XSHAL_CLIB == XTHAL_CLIB_NEWLIB) || (XSHAL_CLIB == XTHAL_CLIB_XCLIB)
#ifndef XT_USE_THREAD_SAFE_CLIB #ifndef XT_USE_THREAD_SAFE_CLIB
#define XT_USE_THREAD_SAFE_CLIB 1 #define XT_USE_THREAD_SAFE_CLIB 1
#endif #endif
#else #else
#define XT_USE_THREAD_SAFE_CLIB 0 #define XT_USE_THREAD_SAFE_CLIB 0
#endif #endif
#if XT_USE_THREAD_SAFE_CLIB > 0u #if XT_USE_THREAD_SAFE_CLIB > 0u
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB #if XSHAL_CLIB == XTHAL_CLIB_XCLIB
#define XT_HAVE_THREAD_SAFE_CLIB 1 #define XT_HAVE_THREAD_SAFE_CLIB 1
#if !defined __ASSEMBLER__ #if !defined __ASSEMBLER__
#include <sys/reent.h> #include <sys/reent.h>
#define XT_CLIB_CONTEXT_AREA_SIZE ( ( sizeof( struct _reent ) + 15 ) + ( -16 ) ) #define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16))
#define XT_CLIB_GLOBAL_PTR _reent_ptr #define XT_CLIB_GLOBAL_PTR _reent_ptr
#define _REENT_INIT_PTR _init_reent #define _REENT_INIT_PTR _init_reent
#define _impure_ptr _reent_ptr #define _impure_ptr _reent_ptr
void _reclaim_reent( void * ptr ); void _reclaim_reent(void * ptr);
#endif #endif
#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB #elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#define XT_HAVE_THREAD_SAFE_CLIB 1 #define XT_HAVE_THREAD_SAFE_CLIB 1
#if !defined __ASSEMBLER__ #if !defined __ASSEMBLER__
#include <sys/reent.h> #include <sys/reent.h>
#define XT_CLIB_CONTEXT_AREA_SIZE ( ( sizeof( struct _reent ) + 15 ) + ( -16 ) ) #define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16))
#define XT_CLIB_GLOBAL_PTR _impure_ptr #define XT_CLIB_GLOBAL_PTR _impure_ptr
#endif #endif
#else /* if XSHAL_CLIB == XTHAL_CLIB_XCLIB */ #else
#define XT_HAVE_THREAD_SAFE_CLIB 0 #define XT_HAVE_THREAD_SAFE_CLIB 0
#error The selected C runtime library is not thread safe. #error The selected C runtime library is not thread safe.
#endif /* if XSHAL_CLIB == XTHAL_CLIB_XCLIB */ #endif
#else /* if XT_USE_THREAD_SAFE_CLIB > 0u */ #else
#define XT_CLIB_CONTEXT_AREA_SIZE 0 #define XT_CLIB_CONTEXT_AREA_SIZE 0
#endif /* if XT_USE_THREAD_SAFE_CLIB > 0u */ #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Extra size -- interrupt frame plus coprocessor save area plus hook space. Extra size -- interrupt frame plus coprocessor save area plus hook space.
* NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks. NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks.
* ------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE ) #define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE)
#else #else
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE ) #define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE)
#endif #endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Space allocated for user code -- function calls and local variables. Space allocated for user code -- function calls and local variables.
* NOTE: This number can be adjusted to suit your needs. You must verify that the NOTE: This number can be adjusted to suit your needs. You must verify that the
* amount of space you reserve is adequate for the worst-case conditions in your amount of space you reserve is adequate for the worst-case conditions in your
* application. application.
* NOTE: The windowed ABI requires more stack, since space has to be reserved NOTE: The windowed ABI requires more stack, since space has to be reserved
* for spilling register windows. for spilling register windows.
* ------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200 #define XT_USER_SIZE 0x200
#else #else
#define XT_USER_SIZE 0x400 #define XT_USER_SIZE 0x400
#endif #endif
/* Minimum recommended stack size. */ /* Minimum recommended stack size. */
#define XT_STACK_MIN_SIZE ( ( XT_XTRA_SIZE + XT_USER_SIZE ) / sizeof( unsigned char ) ) #define XT_STACK_MIN_SIZE ((XT_XTRA_SIZE + XT_USER_SIZE) / sizeof(unsigned char))
/* OS overhead with and without C library thread context. */ /* OS overhead with and without C library thread context. */
#define XT_STACK_EXTRA ( XT_XTRA_SIZE ) #define XT_STACK_EXTRA (XT_XTRA_SIZE)
#define XT_STACK_EXTRA_CLIB ( XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE ) #define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE)
/* *INDENT-OFF* */ /* *INDENT-OFF* */

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -44,7 +44,7 @@
#define XTENSA_CONTEXT_H #define XTENSA_CONTEXT_H
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
#include <xtensa/coreasm.h> #include <xtensa/coreasm.h>
#endif #endif
#include <xtensa/config/tie.h> #include <xtensa/config/tie.h>
@ -53,307 +53,303 @@
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */ /* Align a value up to nearest n-byte boundary, where n is a power of 2. */
#define ALIGNUP( n, val ) ( ( ( val ) + ( n ) - 1 ) & -( n ) ) #define ALIGNUP(n, val) (((val) + (n)-1) & -(n))
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* Macros that help define structures for both C and assembler. Macros that help define structures for both C and assembler.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
#if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ ) #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define STRUCT_BEGIN .pushsection.text; .struct 0 #define STRUCT_BEGIN .pushsection .text; .struct 0
#define STRUCT_FIELD( ctype, size, asname, name ) asname :.space size #define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
#define STRUCT_AFIELD( ctype, size, asname, name, n ) asname :.space( size ) *( n ) #define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
#define STRUCT_END( sname ) sname ## Size:; .popsection #define STRUCT_END(sname) sname##Size:; .popsection
#else #else
#define STRUCT_BEGIN typedef struct { #define STRUCT_BEGIN typedef struct {
#define STRUCT_FIELD( ctype, size, asname, name ) ctype name; #define STRUCT_FIELD(ctype,size,asname,name) ctype name;
#define STRUCT_AFIELD( ctype, size, asname, name, n ) ctype name[ n ]; #define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
#define STRUCT_END( sname ) \ #define STRUCT_END(sname) } sname;
} \
sname;
#endif //_ASMLANGUAGE || __ASSEMBLER__ #endif //_ASMLANGUAGE || __ASSEMBLER__
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
*
* A stack frame of this structure is allocated for any interrupt or exception.
* It goes on the current stack. If the RTOS has a system stack for handling
* interrupts, every thread stack must allow space for just one interrupt stack
* frame, then nested interrupt stack frames go on the system stack.
*
* The frame includes basic registers (explicit) and "extra" registers introduced
* by user TIE or the use of the MAC16 option in the user's Xtensa config.
* The frame size is minimized by omitting regs not applicable to user's config.
*
* For Windowed ABI, this stack frame includes the interruptee's base save area,
* another base save area to manage gcc nested functions, and a little temporary
* space to help manage the spilling of the register windows.
* -------------------------------------------------------------------------------
*/
STRUCT_BEGIN STRUCT_FIELD( long, A stack frame of this structure is allocated for any interrupt or exception.
4, It goes on the current stack. If the RTOS has a system stack for handling
XT_STK_EXIT, interrupts, every thread stack must allow space for just one interrupt stack
exit ) /* exit point for dispatch */ frame, then nested interrupt stack frames go on the system stack.
STRUCT_FIELD( long, 4, XT_STK_PC, pc ) /* return PC */
STRUCT_FIELD( long, 4, XT_STK_PS, ps ) /* return PS */ The frame includes basic registers (explicit) and "extra" registers introduced
STRUCT_FIELD( long, 4, XT_STK_A0, a0 ) by user TIE or the use of the MAC16 option in the user's Xtensa config.
STRUCT_FIELD( long, 4, XT_STK_A1, a1 ) /* stack pointer before interrupt */ The frame size is minimized by omitting regs not applicable to user's config.
STRUCT_FIELD( long, 4, XT_STK_A2, a2 )
STRUCT_FIELD( long, 4, XT_STK_A3, a3 ) For Windowed ABI, this stack frame includes the interruptee's base save area,
STRUCT_FIELD( long, 4, XT_STK_A4, a4 ) another base save area to manage gcc nested functions, and a little temporary
STRUCT_FIELD( long, 4, XT_STK_A5, a5 ) space to help manage the spilling of the register windows.
STRUCT_FIELD( long, 4, XT_STK_A6, a6 ) -------------------------------------------------------------------------------
STRUCT_FIELD( long, 4, XT_STK_A7, a7 ) */
STRUCT_FIELD( long, 4, XT_STK_A8, a8 )
STRUCT_FIELD( long, 4, XT_STK_A9, a9 ) STRUCT_BEGIN
STRUCT_FIELD( long, 4, XT_STK_A10, a10 ) STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */
STRUCT_FIELD( long, 4, XT_STK_A11, a11 ) STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */
STRUCT_FIELD( long, 4, XT_STK_A12, a12 ) STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */
STRUCT_FIELD( long, 4, XT_STK_A13, a13 ) STRUCT_FIELD (long, 4, XT_STK_A0, a0)
STRUCT_FIELD( long, 4, XT_STK_A14, a14 ) STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
STRUCT_FIELD( long, 4, XT_STK_A15, a15 ) STRUCT_FIELD (long, 4, XT_STK_A2, a2)
STRUCT_FIELD( long, 4, XT_STK_SAR, sar ) STRUCT_FIELD (long, 4, XT_STK_A3, a3)
STRUCT_FIELD( long, 4, XT_STK_EXCCAUSE, exccause ) STRUCT_FIELD (long, 4, XT_STK_A4, a4)
STRUCT_FIELD( long, 4, XT_STK_EXCVADDR, excvaddr ) STRUCT_FIELD (long, 4, XT_STK_A5, a5)
STRUCT_FIELD (long, 4, XT_STK_A6, a6)
STRUCT_FIELD (long, 4, XT_STK_A7, a7)
STRUCT_FIELD (long, 4, XT_STK_A8, a8)
STRUCT_FIELD (long, 4, XT_STK_A9, a9)
STRUCT_FIELD (long, 4, XT_STK_A10, a10)
STRUCT_FIELD (long, 4, XT_STK_A11, a11)
STRUCT_FIELD (long, 4, XT_STK_A12, a12)
STRUCT_FIELD (long, 4, XT_STK_A13, a13)
STRUCT_FIELD (long, 4, XT_STK_A14, a14)
STRUCT_FIELD (long, 4, XT_STK_A15, a15)
STRUCT_FIELD (long, 4, XT_STK_SAR, sar)
STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
#if XCHAL_HAVE_LOOPS #if XCHAL_HAVE_LOOPS
STRUCT_FIELD( long, 4, XT_STK_LBEG, lbeg ) STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
STRUCT_FIELD( long, 4, XT_STK_LEND, lend ) STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
STRUCT_FIELD( long, 4, XT_STK_LCOUNT, lcount ) STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
#endif #endif
#ifndef __XTENSA_CALL0_ABI__ #ifndef __XTENSA_CALL0_ABI__
/* Temporary space for saving stuff during window spill */ /* Temporary space for saving stuff during window spill */
STRUCT_FIELD( long, 4, XT_STK_TMP0, tmp0 ) STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
STRUCT_FIELD( long, 4, XT_STK_TMP1, tmp1 ) STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
STRUCT_FIELD( long, 4, XT_STK_TMP2, tmp2 ) STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
#endif #endif
#ifdef XT_USE_SWPRI #ifdef XT_USE_SWPRI
/* Storage for virtual priority mask */ /* Storage for virtual priority mask */
STRUCT_FIELD( long, 4, XT_STK_VPRI, vpri ) STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
#endif #endif
#ifdef XT_USE_OVLY #ifdef XT_USE_OVLY
/* Storage for overlay state */ /* Storage for overlay state */
STRUCT_FIELD( long, 4, XT_STK_OVLY, ovly ) STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
#endif #endif
STRUCT_END( XtExcFrame ) STRUCT_END(XtExcFrame)
#if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ ) #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define XT_STK_NEXT1 XtExcFrameSize #define XT_STK_NEXT1 XtExcFrameSize
#else #else
#define XT_STK_NEXT1 sizeof( XtExcFrame ) #define XT_STK_NEXT1 sizeof(XtExcFrame)
#endif #endif
/* Allocate extra storage if needed */ /* Allocate extra storage if needed */
#if XCHAL_EXTRA_SA_SIZE != 0 #if XCHAL_EXTRA_SA_SIZE != 0
#if XCHAL_EXTRA_SA_ALIGN <= 16 #if XCHAL_EXTRA_SA_ALIGN <= 16
#define XT_STK_EXTRA ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 ) #define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
#else #else
/* If need more alignment than stack, add space for dynamic alignment */ /* If need more alignment than stack, add space for dynamic alignment */
#define XT_STK_EXTRA ( ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 ) + XCHAL_EXTRA_SA_ALIGN ) #define XT_STK_EXTRA (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN)
#endif #endif
#define XT_STK_NEXT2 ( XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE ) #define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
#else #else
#define XT_STK_NEXT2 XT_STK_NEXT1 #define XT_STK_NEXT2 XT_STK_NEXT1
#endif /* if XCHAL_EXTRA_SA_SIZE != 0 */ #endif
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* This is the frame size. Add space for 4 registers (interruptee's base save This is the frame size. Add space for 4 registers (interruptee's base save
* area) and some space for gcc nested functions if any. area) and some space for gcc nested functions if any.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
#define XT_STK_FRMSZ ( ALIGNUP( 0x10, XT_STK_NEXT2 ) + 0x20 ) #define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20)
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* SOLICITED STACK FRAME FOR A THREAD SOLICITED STACK FRAME FOR A THREAD
*
* A stack frame of this structure is allocated whenever a thread enters the A stack frame of this structure is allocated whenever a thread enters the
* RTOS kernel intentionally (and synchronously) to submit to thread scheduling. RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
* It goes on the current thread's stack. It goes on the current thread's stack.
*
* The solicited frame only includes registers that are required to be preserved The solicited frame only includes registers that are required to be preserved
* by the callee according to the compiler's ABI conventions, some space to save by the callee according to the compiler's ABI conventions, some space to save
* the return address for returning to the caller, and the caller's PS register. the return address for returning to the caller, and the caller's PS register.
*
* For Windowed ABI, this stack frame includes the caller's base save area. For Windowed ABI, this stack frame includes the caller's base save area.
*
* Note on XT_SOL_EXIT field: Note on XT_SOL_EXIT field:
* It is necessary to distinguish a solicited from an interrupt stack frame. It is necessary to distinguish a solicited from an interrupt stack frame.
* This field corresponds to XT_STK_EXIT in the interrupt stack frame and is This field corresponds to XT_STK_EXIT in the interrupt stack frame and is
* always at the same offset (0). It can be written with a code (usually 0) always at the same offset (0). It can be written with a code (usually 0)
* to distinguish a solicted frame from an interrupt frame. An RTOS port may to distinguish a solicted frame from an interrupt frame. An RTOS port may
* opt to ignore this field if it has another way of distinguishing frames. opt to ignore this field if it has another way of distinguishing frames.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
STRUCT_BEGIN STRUCT_BEGIN
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
STRUCT_FIELD( long, 4, XT_SOL_EXIT, exit ) STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD( long, 4, XT_SOL_PC, pc ) STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD( long, 4, XT_SOL_PS, ps ) STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
STRUCT_FIELD( long, 4, XT_SOL_NEXT, next ) STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
STRUCT_FIELD( long, 4, XT_SOL_A12, a12 ) /* should be on 16-byte alignment */ STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */
STRUCT_FIELD( long, 4, XT_SOL_A13, a13 ) STRUCT_FIELD (long, 4, XT_SOL_A13, a13)
STRUCT_FIELD( long, 4, XT_SOL_A14, a14 ) STRUCT_FIELD (long, 4, XT_SOL_A14, a14)
STRUCT_FIELD( long, 4, XT_SOL_A15, a15 ) STRUCT_FIELD (long, 4, XT_SOL_A15, a15)
#else #else
STRUCT_FIELD( long, 4, XT_SOL_EXIT, exit ) STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD( long, 4, XT_SOL_PC, pc ) STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD( long, 4, XT_SOL_PS, ps ) STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
STRUCT_FIELD( long, 4, XT_SOL_NEXT, next ) STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
STRUCT_FIELD( long, 4, XT_SOL_A0, a0 ) /* should be on 16-byte alignment */ STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */
STRUCT_FIELD( long, 4, XT_SOL_A1, a1 ) STRUCT_FIELD (long, 4, XT_SOL_A1, a1)
STRUCT_FIELD( long, 4, XT_SOL_A2, a2 ) STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
STRUCT_FIELD( long, 4, XT_SOL_A3, a3 ) STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
#endif /* ifdef __XTENSA_CALL0_ABI__ */ #endif
STRUCT_END( XtSolFrame ) STRUCT_END(XtSolFrame)
/* Size of solicited stack frame */ /* Size of solicited stack frame */
#define XT_SOL_FRMSZ ALIGNUP( 0x10, XtSolFrameSize ) #define XT_SOL_FRMSZ ALIGNUP(0x10, XtSolFrameSize)
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* CO-PROCESSOR STATE SAVE AREA FOR A THREAD CO-PROCESSOR STATE SAVE AREA FOR A THREAD
*
* The RTOS must provide an area per thread to save the state of co-processors The RTOS must provide an area per thread to save the state of co-processors
* when that thread does not have control. Co-processors are context-switched when that thread does not have control. Co-processors are context-switched
* lazily (on demand) only when a new thread uses a co-processor instruction, lazily (on demand) only when a new thread uses a co-processor instruction,
* otherwise a thread retains ownership of the co-processor even when it loses otherwise a thread retains ownership of the co-processor even when it loses
* control of the processor. An Xtensa co-processor exception is triggered when control of the processor. An Xtensa co-processor exception is triggered when
* any co-processor instruction is executed by a thread that is not the owner, any co-processor instruction is executed by a thread that is not the owner,
* and the context switch of that co-processor is then peformed by the handler. and the context switch of that co-processor is then peformed by the handler.
* Ownership represents which thread's state is currently in the co-processor. Ownership represents which thread's state is currently in the co-processor.
*
* Co-processors may not be used by interrupt or exception handlers. If an Co-processors may not be used by interrupt or exception handlers. If an
* co-processor instruction is executed by an interrupt or exception handler, co-processor instruction is executed by an interrupt or exception handler,
* the co-processor exception handler will trigger a kernel panic and freeze. the co-processor exception handler will trigger a kernel panic and freeze.
* This restriction is introduced to reduce the overhead of saving and restoring This restriction is introduced to reduce the overhead of saving and restoring
* co-processor state (which can be quite large) and in particular remove that co-processor state (which can be quite large) and in particular remove that
* overhead from interrupt handlers. overhead from interrupt handlers.
*
* The co-processor state save area may be in any convenient per-thread location The co-processor state save area may be in any convenient per-thread location
* such as in the thread control block or above the thread stack area. It need such as in the thread control block or above the thread stack area. It need
* not be in the interrupt stack frame since interrupts don't use co-processors. not be in the interrupt stack frame since interrupts don't use co-processors.
*
* Along with the save area for each co-processor, two bitmasks with flags per Along with the save area for each co-processor, two bitmasks with flags per
* co-processor (laid out as in the CPENABLE reg) help manage context-switching co-processor (laid out as in the CPENABLE reg) help manage context-switching
* co-processors as efficiently as possible: co-processors as efficiently as possible:
*
* XT_CPENABLE XT_CPENABLE
* The contents of a non-running thread's CPENABLE register. The contents of a non-running thread's CPENABLE register.
* It represents the co-processors owned (and whose state is still needed) It represents the co-processors owned (and whose state is still needed)
* by the thread. When a thread is preempted, its CPENABLE is saved here. by the thread. When a thread is preempted, its CPENABLE is saved here.
* When a thread solicits a context-swtich, its CPENABLE is cleared - the When a thread solicits a context-swtich, its CPENABLE is cleared - the
* compiler has saved the (caller-saved) co-proc state if it needs to. compiler has saved the (caller-saved) co-proc state if it needs to.
* When a non-running thread loses ownership of a CP, its bit is cleared. When a non-running thread loses ownership of a CP, its bit is cleared.
* When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg. When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg.
* Avoids co-processor exceptions when no change of ownership is needed. Avoids co-processor exceptions when no change of ownership is needed.
*
* XT_CPSTORED XT_CPSTORED
* A bitmask with the same layout as CPENABLE, a bit per co-processor. A bitmask with the same layout as CPENABLE, a bit per co-processor.
* Indicates whether the state of each co-processor is saved in the state Indicates whether the state of each co-processor is saved in the state
* save area. When a thread enters the kernel, only the state of co-procs save area. When a thread enters the kernel, only the state of co-procs
* still enabled in CPENABLE is saved. When the co-processor exception still enabled in CPENABLE is saved. When the co-processor exception
* handler assigns ownership of a co-processor to a thread, it restores handler assigns ownership of a co-processor to a thread, it restores
* the saved state only if this bit is set, and clears this bit. the saved state only if this bit is set, and clears this bit.
*
* XT_CP_CS_ST XT_CP_CS_ST
* A bitmask with the same layout as CPENABLE, a bit per co-processor. A bitmask with the same layout as CPENABLE, a bit per co-processor.
* Indicates whether callee-saved state is saved in the state save area. Indicates whether callee-saved state is saved in the state save area.
* Callee-saved state is saved by itself on a solicited context switch, Callee-saved state is saved by itself on a solicited context switch,
* and restored when needed by the coprocessor exception handler. and restored when needed by the coprocessor exception handler.
* Unsolicited switches will cause the entire coprocessor to be saved Unsolicited switches will cause the entire coprocessor to be saved
* when necessary. when necessary.
*
* XT_CP_ASA XT_CP_ASA
* Pointer to the aligned save area. Allows it to be aligned more than Pointer to the aligned save area. Allows it to be aligned more than
* the overall save area (which might only be stack-aligned or TCB-aligned). the overall save area (which might only be stack-aligned or TCB-aligned).
* Especially relevant for Xtensa cores configured with a very large data Especially relevant for Xtensa cores configured with a very large data
* path that requires alignment greater than 16 bytes (ABI stack alignment). path that requires alignment greater than 16 bytes (ABI stack alignment).
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0
/* Offsets of each coprocessor save area within the 'aligned save area': */ /* Offsets of each coprocessor save area within the 'aligned save area': */
#define XT_CP0_SA 0 #define XT_CP0_SA 0
#define XT_CP1_SA ALIGNUP( XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE ) #define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE)
#define XT_CP2_SA ALIGNUP( XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE ) #define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE)
#define XT_CP3_SA ALIGNUP( XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE ) #define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE)
#define XT_CP4_SA ALIGNUP( XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE ) #define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE)
#define XT_CP5_SA ALIGNUP( XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE ) #define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE)
#define XT_CP6_SA ALIGNUP( XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE ) #define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE)
#define XT_CP7_SA ALIGNUP( XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE ) #define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE)
#define XT_CP_SA_SIZE ALIGNUP( 16, XT_CP7_SA + XCHAL_CP7_SA_SIZE ) #define XT_CP_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE)
/* Offsets within the overall save area: */ /* Offsets within the overall save area: */
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */ #define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */
#define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */ #define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */
#define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */ #define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */
#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */ #define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */
/* Overall size allows for dynamic alignment: */ /* Overall size allows for dynamic alignment: */
#define XT_CP_SIZE ( 12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN ) #define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)
#else /* if XCHAL_CP_NUM > 0 */ #else
#define XT_CP_SIZE 0 #define XT_CP_SIZE 0
#endif /* if XCHAL_CP_NUM > 0 */ #endif
/* /*
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
*
* Convenient where the frame size requirements are the same for both ABIs. Convenient where the frame size requirements are the same for both ABIs.
* ENTRY(sz), RET(sz) are for framed functions (have locals or make calls). ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
* ENTRY0, RET0 are for frameless functions (no locals, no calls). ENTRY0, RET0 are for frameless functions (no locals, no calls).
*
* where size = size of stack frame in bytes (must be >0 and aligned to 16). where size = size of stack frame in bytes (must be >0 and aligned to 16).
* For framed functions the frame is created and the return address saved at For framed functions the frame is created and the return address saved at
* base of frame (Call0 ABI) or as determined by hardware (Windowed ABI). base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
* For frameless functions, there is no frame and return address remains in a0. For frameless functions, there is no frame and return address remains in a0.
* Note: Because CPP macros expand to a single line, macros requiring multi-line Note: Because CPP macros expand to a single line, macros requiring multi-line
* expansions are implemented as assembler macros. expansions are implemented as assembler macros.
* ------------------------------------------------------------------------------- -------------------------------------------------------------------------------
*/ */
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
/* Call0 */ /* Call0 */
#define ENTRY( sz ) entry1 sz #define ENTRY(sz) entry1 sz
.macro entry1 size = 0x10 .macro entry1 size=0x10
addi sp, sp, -\ size addi sp, sp, -\size
s32i a0, sp, 0 s32i a0, sp, 0
.endm .endm
#define ENTRY0 #define ENTRY0
#define RET( sz ) ret1 sz #define RET(sz) ret1 sz
.macro ret1 size = 0x10 .macro ret1 size=0x10
l32i a0, sp, 0 l32i a0, sp, 0
addi sp, sp, \ size addi sp, sp, \size
ret ret
.endm .endm
#define RET0 ret #define RET0 ret
#else /* ifdef __XTENSA_CALL0_ABI__ */ #else
/* Windowed */ /* Windowed */
#define ENTRY( sz ) entry sp, sz #define ENTRY(sz) entry sp, sz
#define ENTRY0 entry sp, 0x10 #define ENTRY0 entry sp, 0x10
#define RET( sz ) retw #define RET(sz) retw
#define RET0 retw #define RET0 retw
#endif /* ifdef __XTENSA_CALL0_ABI__ */ #endif
#endif /* ifdef __ASSEMBLER__ */ #endif
#endif /* XTENSA_CONTEXT_H */ #endif /* XTENSA_CONTEXT_H */

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -36,31 +36,35 @@
#ifdef XT_BOARD #ifdef XT_BOARD
#include <xtensa/xtbsp.h> #include <xtensa/xtbsp.h>
#endif #endif
#include "xtensa_rtos.h" #include "xtensa_rtos.h"
#ifdef XT_RTOS_TIMER_INT #ifdef XT_RTOS_TIMER_INT
unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */ unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */
/* /*
* Compute and initialize at run-time the tick divisor (the number of Compute and initialize at run-time the tick divisor (the number of
* processor clock cycles in an RTOS tick, used to set the tick timer). processor clock cycles in an RTOS tick, used to set the tick timer).
* Called when the processor clock frequency is not known at compile-time. Called when the processor clock frequency is not known at compile-time.
*/ */
void _xt_tick_divisor_init( void ) void _xt_tick_divisor_init(void)
{ {
#ifdef XT_CLOCK_FREQ #ifdef XT_CLOCK_FREQ
_xt_tick_divisor = ( XT_CLOCK_FREQ / XT_TICK_PER_SEC );
#else _xt_tick_divisor = (XT_CLOCK_FREQ / XT_TICK_PER_SEC);
#ifdef XT_BOARD
_xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; #else
#else
#error "No way to obtain processor clock frequency" #ifdef XT_BOARD
#endif /* XT_BOARD */ _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC;
#endif /* XT_CLOCK_FREQ */ #else
} #error "No way to obtain processor clock frequency"
#endif /* XT_BOARD */
#endif /* XT_CLOCK_FREQ */
}
#endif /* XT_RTOS_TIMER_INT */ #endif /* XT_RTOS_TIMER_INT */

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -43,110 +43,95 @@
/* Handler table is in xtensa_intr_asm.S */ /* Handler table is in xtensa_intr_asm.S */
extern xt_exc_handler _xt_exception_table[ XCHAL_EXCCAUSE_NUM ]; extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM];
/* /*
* Default handler for unhandled exceptions. Default handler for unhandled exceptions.
*/ */
void xt_unhandled_exception( XtExcFrame * frame ) void xt_unhandled_exception(XtExcFrame *frame)
{ {
exit( -1 ); exit(-1);
} }
/* /*
* This function registers a handler for the specified exception. This function registers a handler for the specified exception.
* The function returns the address of the previous handler. The function returns the address of the previous handler.
* On error, it returns 0. On error, it returns 0.
*/ */
xt_exc_handler xt_set_exception_handler( int n, xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f)
xt_exc_handler f ) {
{ xt_exc_handler old;
xt_exc_handler old;
if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) ) return 0; /* invalid exception number */
{
return 0; /* invalid exception number */ old = _xt_exception_table[n];
}
if (f) {
old = _xt_exception_table[ n ]; _xt_exception_table[n] = f;
if( f )
{
_xt_exception_table[ n ] = f;
}
else
{
_xt_exception_table[ n ] = &xt_unhandled_exception;
}
return( ( old == &xt_unhandled_exception ) ? 0 : old );
} }
else {
_xt_exception_table[n] = &xt_unhandled_exception;
}
return ((old == &xt_unhandled_exception) ? 0 : old);
}
#endif /* if XCHAL_HAVE_EXCEPTIONS */ #endif
#if XCHAL_HAVE_INTERRUPTS #if XCHAL_HAVE_INTERRUPTS
/* Handler table is in xtensa_intr_asm.S */ /* Handler table is in xtensa_intr_asm.S */
typedef struct xt_handler_table_entry typedef struct xt_handler_table_entry {
{ void * handler;
void * handler; void * arg;
void * arg; } xt_handler_table_entry;
} xt_handler_table_entry;
extern xt_handler_table_entry _xt_interrupt_table[ XCHAL_NUM_INTERRUPTS ]; extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS];
/* /*
* Default handler for unhandled interrupts. Default handler for unhandled interrupts.
*/ */
void xt_unhandled_interrupt( void * arg ) void xt_unhandled_interrupt(void * arg)
{ {
exit( -1 ); exit(-1);
} }
/* /*
* This function registers a handler for the specified interrupt. The "arg" This function registers a handler for the specified interrupt. The "arg"
* parameter specifies the argument to be passed to the handler when it is parameter specifies the argument to be passed to the handler when it is
* invoked. The function returns the address of the previous handler. invoked. The function returns the address of the previous handler.
* On error, it returns 0. On error, it returns 0.
*/ */
xt_handler xt_set_interrupt_handler( int n, xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg)
xt_handler f, {
void * arg ) xt_handler_table_entry * entry;
{ xt_handler old;
xt_handler_table_entry * entry;
xt_handler old; if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
return 0; /* invalid interrupt number */
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) ) if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL )
{ return 0; /* priority level too high to safely handle in C */
return 0; /* invalid interrupt number */
} entry = _xt_interrupt_table + n;
old = entry->handler;
if( Xthal_intlevel[ n ] > XCHAL_EXCM_LEVEL )
{ if (f) {
return 0; /* priority level too high to safely handle in C */ entry->handler = f;
} entry->arg = arg;
}
entry = _xt_interrupt_table + n; else {
old = entry->handler; entry->handler = &xt_unhandled_interrupt;
entry->arg = (void*)n;
if( f )
{
entry->handler = f;
entry->arg = arg;
}
else
{
entry->handler = &xt_unhandled_interrupt;
entry->arg = ( void * ) n;
}
return( ( old == &xt_unhandled_interrupt ) ? 0 : old );
} }
return ((old == &xt_unhandled_interrupt) ? 0 : old);
}
#endif /* XCHAL_HAVE_INTERRUPTS */ #endif /* XCHAL_HAVE_INTERRUPTS */

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -39,7 +39,7 @@
/* Mutex object that controls access to the overlay. Currently only one /* Mutex object that controls access to the overlay. Currently only one
* overlay region is supported so one mutex suffices. * overlay region is supported so one mutex suffices.
*/ */
static SemaphoreHandle_t xt_overlay_mutex; static SemaphoreHandle_t xt_overlay_mutex;
/* This function should be overridden to provide OS specific init such /* This function should be overridden to provide OS specific init such
@ -47,30 +47,30 @@
* Typically this mutex would be set up with priority inheritance. See * Typically this mutex would be set up with priority inheritance. See
* overlay manager documentation for more details. * overlay manager documentation for more details.
*/ */
void xt_overlay_init_os( void ) void xt_overlay_init_os(void)
{ {
/* Create the mutex for overlay access. Priority inheritance is /* Create the mutex for overlay access. Priority inheritance is
* required. * required.
*/ */
xt_overlay_mutex = xSemaphoreCreateMutex(); xt_overlay_mutex = xSemaphoreCreateMutex();
} }
/* This function locks access to shared overlay resources, typically /* This function locks access to shared overlay resources, typically
* by acquiring a mutex. * by acquiring a mutex.
*/ */
void xt_overlay_lock( void ) void xt_overlay_lock(void)
{ {
xSemaphoreTake( xt_overlay_mutex, 0 ); xSemaphoreTake(xt_overlay_mutex, 0);
} }
/* This function releases access to shared overlay resources, typically /* This function releases access to shared overlay resources, typically
* by unlocking a mutex. * by unlocking a mutex.
*/ */
void xt_overlay_unlock( void ) void xt_overlay_unlock(void)
{ {
xSemaphoreGive( xt_overlay_mutex ); xSemaphoreGive(xt_overlay_mutex);
} }
#endif /* if configUSE_MUTEX */ #endif

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -49,9 +49,9 @@
#define XTENSA_RTOS_H #define XTENSA_RTOS_H
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
#include <xtensa/coreasm.h> #include <xtensa/coreasm.h>
#else #else
#include <xtensa/config/core.h> #include <xtensa/config/core.h>
#endif #endif
#include <xtensa/corebits.h> #include <xtensa/corebits.h>
@ -59,180 +59,180 @@
#include <xtensa/simcall.h> #include <xtensa/simcall.h>
/* /*
* Include any RTOS specific definitions that are needed by this header. Include any RTOS specific definitions that are needed by this header.
*/ */
#include <FreeRTOSConfig.h> #include <FreeRTOSConfig.h>
/* /*
* Convert FreeRTOSConfig definitions to XTENSA definitions. Convert FreeRTOSConfig definitions to XTENSA definitions.
* However these can still be overridden from the command line. However these can still be overridden from the command line.
*/ */
#ifndef XT_SIMULATOR #ifndef XT_SIMULATOR
#if configXT_SIMULATOR #if configXT_SIMULATOR
#define XT_SIMULATOR 1 /* Simulator mode */ #define XT_SIMULATOR 1 /* Simulator mode */
#endif #endif
#endif #endif
#ifndef XT_BOARD #ifndef XT_BOARD
#if configXT_BOARD #if configXT_BOARD
#define XT_BOARD 1 /* Board mode */ #define XT_BOARD 1 /* Board mode */
#endif #endif
#endif #endif
#ifndef XT_TIMER_INDEX #ifndef XT_TIMER_INDEX
#if defined configXT_TIMER_INDEX #if defined configXT_TIMER_INDEX
#define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */ #define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */
#endif #endif
#endif #endif
#ifndef XT_INTEXC_HOOKS #ifndef XT_INTEXC_HOOKS
#if configXT_INTEXC_HOOKS #if configXT_INTEXC_HOOKS
#define XT_INTEXC_HOOKS 1 /* Enables exception hooks */ #define XT_INTEXC_HOOKS 1 /* Enables exception hooks */
#endif #endif
#endif #endif
#if ( !XT_SIMULATOR ) && ( !XT_BOARD ) #if (!XT_SIMULATOR) && (!XT_BOARD)
#error Either XT_SIMULATOR or XT_BOARD must be defined. #error Either XT_SIMULATOR or XT_BOARD must be defined.
#endif #endif
/* /*
* Name of RTOS (for messages). Name of RTOS (for messages).
*/ */
#define XT_RTOS_NAME FreeRTOS #define XT_RTOS_NAME FreeRTOS
/* /*
* Check some Xtensa configuration requirements and report error if not met. Check some Xtensa configuration requirements and report error if not met.
* Error messages can be customize to the RTOS port. Error messages can be customize to the RTOS port.
*/ */
#if !XCHAL_HAVE_XEA2 #if !XCHAL_HAVE_XEA2
#error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)." #error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)."
#endif #endif
/******************************************************************************* /*******************************************************************************
*
* RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS. RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS.
*
* Define callout macros used in generic Xtensa code to interact with the RTOS. Define callout macros used in generic Xtensa code to interact with the RTOS.
* The macros are simply the function names for use in calls from assembler code. The macros are simply the function names for use in calls from assembler code.
* Some of these functions may call back to generic functions in xtensa_context.h . Some of these functions may call back to generic functions in xtensa_context.h .
*
*******************************************************************************/ *******************************************************************************/
/* /*
* Inform RTOS of entry into an interrupt handler that will affect it. Inform RTOS of entry into an interrupt handler that will affect it.
* Allows RTOS to manage switch to any system stack and count nesting level. Allows RTOS to manage switch to any system stack and count nesting level.
* Called after minimal context has been saved, with interrupts disabled. Called after minimal context has been saved, with interrupts disabled.
* RTOS port can call0 _xt_context_save to save the rest of the context. RTOS port can call0 _xt_context_save to save the rest of the context.
* May only be called from assembly code by the 'call0' instruction. May only be called from assembly code by the 'call0' instruction.
*/ */
/* void XT_RTOS_INT_ENTER(void) */ // void XT_RTOS_INT_ENTER(void)
#define XT_RTOS_INT_ENTER _frxt_int_enter #define XT_RTOS_INT_ENTER _frxt_int_enter
/* /*
* Inform RTOS of completion of an interrupt handler, and give control to Inform RTOS of completion of an interrupt handler, and give control to
* RTOS to perform thread/task scheduling, switch back from any system stack RTOS to perform thread/task scheduling, switch back from any system stack
* and restore the context, and return to the exit dispatcher saved in the and restore the context, and return to the exit dispatcher saved in the
* stack frame at XT_STK_EXIT. RTOS port can call0 _xt_context_restore stack frame at XT_STK_EXIT. RTOS port can call0 _xt_context_restore
* to save the context saved in XT_RTOS_INT_ENTER via _xt_context_save, to save the context saved in XT_RTOS_INT_ENTER via _xt_context_save,
* leaving only a minimal part of the context to be restored by the exit leaving only a minimal part of the context to be restored by the exit
* dispatcher. This function does not return to the place it was called from. dispatcher. This function does not return to the place it was called from.
* May only be called from assembly code by the 'call0' instruction. May only be called from assembly code by the 'call0' instruction.
*/ */
/* void XT_RTOS_INT_EXIT(void) */ // void XT_RTOS_INT_EXIT(void)
#define XT_RTOS_INT_EXIT _frxt_int_exit #define XT_RTOS_INT_EXIT _frxt_int_exit
/* /*
* Inform RTOS of the occurrence of a tick timer interrupt. Inform RTOS of the occurrence of a tick timer interrupt.
* If RTOS has no tick timer, leave XT_RTOS_TIMER_INT undefined. If RTOS has no tick timer, leave XT_RTOS_TIMER_INT undefined.
* May be coded in or called from C or assembly, per ABI conventions. May be coded in or called from C or assembly, per ABI conventions.
* RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro). RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro).
*/ */
/* void XT_RTOS_TIMER_INT(void) */ // void XT_RTOS_TIMER_INT(void)
#define XT_RTOS_TIMER_INT _frxt_timer_int #define XT_RTOS_TIMER_INT _frxt_timer_int
#define XT_TICK_PER_SEC configTICK_RATE_HZ #define XT_TICK_PER_SEC configTICK_RATE_HZ
/* /*
* Return in a15 the base address of the co-processor state save area for the Return in a15 the base address of the co-processor state save area for the
* thread that triggered a co-processor exception, or 0 if no thread was running. thread that triggered a co-processor exception, or 0 if no thread was running.
* The state save area is structured as defined in xtensa_context.h and has size The state save area is structured as defined in xtensa_context.h and has size
* XT_CP_SIZE. Co-processor instructions should only be used in thread code, never XT_CP_SIZE. Co-processor instructions should only be used in thread code, never
* in interrupt handlers or the RTOS kernel. May only be called from assembly code in interrupt handlers or the RTOS kernel. May only be called from assembly code
* and by the 'call0' instruction. A result of 0 indicates an unrecoverable error. and by the 'call0' instruction. A result of 0 indicates an unrecoverable error.
* The implementation may use only a2-4, a15 (all other regs must be preserved). The implementation may use only a2-4, a15 (all other regs must be preserved).
*/ */
/* void* XT_RTOS_CP_STATE(void) */ // void* XT_RTOS_CP_STATE(void)
#define XT_RTOS_CP_STATE _frxt_task_coproc_state #define XT_RTOS_CP_STATE _frxt_task_coproc_state
/******************************************************************************* /*******************************************************************************
*
* HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL. HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL.
*
* This Xtensa RTOS port provides hooks for dynamically installing exception This Xtensa RTOS port provides hooks for dynamically installing exception
* and interrupt handlers to facilitate automated testing where each test and interrupt handlers to facilitate automated testing where each test
* case can install its own handler for user exceptions and each interrupt case can install its own handler for user exceptions and each interrupt
* priority (level). This consists of an array of function pointers indexed priority (level). This consists of an array of function pointers indexed
* by interrupt priority, with index 0 being the user exception handler hook. by interrupt priority, with index 0 being the user exception handler hook.
* Each entry in the array is initially 0, and may be replaced by a function Each entry in the array is initially 0, and may be replaced by a function
* pointer of type XT_INTEXC_HOOK. A handler may be uninstalled by installing 0. pointer of type XT_INTEXC_HOOK. A handler may be uninstalled by installing 0.
*
* The handler for low and medium priority obeys ABI conventions so may be coded The handler for low and medium priority obeys ABI conventions so may be coded
* in C. For the exception handler, the cause is the contents of the EXCCAUSE in C. For the exception handler, the cause is the contents of the EXCCAUSE
* reg, and the result is -1 if handled, else the cause (still needs handling). reg, and the result is -1 if handled, else the cause (still needs handling).
* For interrupt handlers, the cause is a mask of pending enabled interrupts at For interrupt handlers, the cause is a mask of pending enabled interrupts at
* that level, and the result is the same mask with the bits for the handled that level, and the result is the same mask with the bits for the handled
* interrupts cleared (those not cleared still need handling). This allows a test interrupts cleared (those not cleared still need handling). This allows a test
* case to either pre-handle or override the default handling for the exception case to either pre-handle or override the default handling for the exception
* or interrupt level (see xtensa_vectors.S). or interrupt level (see xtensa_vectors.S).
*
* High priority handlers (including NMI) must be coded in assembly, are always High priority handlers (including NMI) must be coded in assembly, are always
* called by 'call0' regardless of ABI, must preserve all registers except a0, called by 'call0' regardless of ABI, must preserve all registers except a0,
* and must not use or modify the interrupted stack. The hook argument 'cause' and must not use or modify the interrupted stack. The hook argument 'cause'
* is not passed and the result is ignored, so as not to burden the caller with is not passed and the result is ignored, so as not to burden the caller with
* saving and restoring a2 (it assumes only one interrupt per level - see the saving and restoring a2 (it assumes only one interrupt per level - see the
* discussion in high priority interrupts in xtensa_vectors.S). The handler discussion in high priority interrupts in xtensa_vectors.S). The handler
* therefore should be coded to prototype 'void h(void)' even though it plugs therefore should be coded to prototype 'void h(void)' even though it plugs
* into an array of handlers of prototype 'unsigned h(unsigned)'. into an array of handlers of prototype 'unsigned h(unsigned)'.
*
* To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'. To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'.
*
*******************************************************************************/ *******************************************************************************/
#define XT_INTEXC_HOOK_NUM ( 1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI ) #define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI)
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
typedef unsigned (* XT_INTEXC_HOOK)( unsigned cause ); typedef unsigned (*XT_INTEXC_HOOK)(unsigned cause);
extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[ XT_INTEXC_HOOK_NUM ]; extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
#endif #endif
/******************************************************************************* /*******************************************************************************
*
* CONVENIENCE INCLUSIONS. CONVENIENCE INCLUSIONS.
*
* Ensures RTOS specific files need only include this one Xtensa-generic header. Ensures RTOS specific files need only include this one Xtensa-generic header.
* These headers are included last so they can use the RTOS definitions above. These headers are included last so they can use the RTOS definitions above.
*
*******************************************************************************/ *******************************************************************************/
#include "xtensa_context.h" #include "xtensa_context.h"
#ifdef XT_RTOS_TIMER_INT #ifdef XT_RTOS_TIMER_INT
#include "xtensa_timer.h" #include "xtensa_timer.h"
#endif #endif
/******************************************************************************* /*******************************************************************************
*
* Xtensa Port Version. Xtensa Port Version.
*
*******************************************************************************/ *******************************************************************************/
#define XTENSA_PORT_VERSION 1.7 #define XTENSA_PORT_VERSION 1.7
#define XTENSA_PORT_VERSION_STRING "1.7" #define XTENSA_PORT_VERSION_STRING "1.7"
#endif /* XTENSA_RTOS_H */ #endif /* XTENSA_RTOS_H */

@ -1,4 +1,4 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2015-2019 Cadence Design Systems, Inc. * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -47,118 +47,118 @@
#define XTENSA_TIMER_H #define XTENSA_TIMER_H
#ifdef __ASSEMBLER__ #ifdef __ASSEMBLER__
#include <xtensa/coreasm.h> #include <xtensa/coreasm.h>
#endif #endif
#include <xtensa/corebits.h> #include <xtensa/corebits.h>
#include <xtensa/config/system.h> #include <xtensa/config/system.h>
#include "xtensa_rtos.h" /* in case this wasn't included directly */ #include "xtensa_rtos.h" /* in case this wasn't included directly */
#include <FreeRTOSConfig.h> #include <FreeRTOSConfig.h>
/* /*
* Select timer to use for periodic tick, and determine its interrupt number Select timer to use for periodic tick, and determine its interrupt number
* and priority. User may specify a timer by defining XT_TIMER_INDEX with -D, and priority. User may specify a timer by defining XT_TIMER_INDEX with -D,
* in which case its validity is checked (it must exist in this core and must in which case its validity is checked (it must exist in this core and must
* not be on a high priority interrupt - an error will be reported in invalid). not be on a high priority interrupt - an error will be reported in invalid).
* Otherwise select the first low or medium priority interrupt timer available. Otherwise select the first low or medium priority interrupt timer available.
*/ */
#if XCHAL_NUM_TIMERS == 0 #if XCHAL_NUM_TIMERS == 0
#error "This Xtensa configuration is unsupported, it has no timers." #error "This Xtensa configuration is unsupported, it has no timers."
#else #else
#ifndef XT_TIMER_INDEX #ifndef XT_TIMER_INDEX
#if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER3_INTERRUPT ) <= XCHAL_EXCM_LEVEL #if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX #undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 3 #define XT_TIMER_INDEX 3
#endif #endif
#endif #endif
#if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER2_INTERRUPT ) <= XCHAL_EXCM_LEVEL #if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX #undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 2 #define XT_TIMER_INDEX 2
#endif #endif
#endif #endif
#if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER1_INTERRUPT ) <= XCHAL_EXCM_LEVEL #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX #undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 1 #define XT_TIMER_INDEX 1
#endif
#endif
#if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER0_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 0
#endif
#endif
#endif /* ifndef XT_TIMER_INDEX */
#ifndef XT_TIMER_INDEX
#error "There is no suitable timer in this Xtensa configuration."
#endif #endif
#endif
#if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 0
#endif
#endif
#endif
#ifndef XT_TIMER_INDEX
#error "There is no suitable timer in this Xtensa configuration."
#endif
#define XT_CCOMPARE ( CCOMPARE + XT_TIMER_INDEX ) #define XT_CCOMPARE (CCOMPARE + XT_TIMER_INDEX)
#define XT_TIMER_INTNUM XCHAL_TIMER_INTERRUPT( XT_TIMER_INDEX ) #define XT_TIMER_INTNUM XCHAL_TIMER_INTERRUPT(XT_TIMER_INDEX)
#define XT_TIMER_INTPRI XCHAL_INT_LEVEL( XT_TIMER_INTNUM ) #define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM)
#define XT_TIMER_INTEN ( 1 << XT_TIMER_INTNUM ) #define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM)
#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED #if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
#error "The timer selected by XT_TIMER_INDEX does not exist in this core." #error "The timer selected by XT_TIMER_INDEX does not exist in this core."
#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL #elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
#error "The timer interrupt cannot be high priority (use medium or low)." #error "The timer interrupt cannot be high priority (use medium or low)."
#endif #endif
#endif /* XCHAL_NUM_TIMERS */ #endif /* XCHAL_NUM_TIMERS */
/* /*
* Set processor clock frequency, used to determine clock divisor for timer tick. Set processor clock frequency, used to determine clock divisor for timer tick.
* User should BE SURE TO ADJUST THIS for the Xtensa platform being used. User should BE SURE TO ADJUST THIS for the Xtensa platform being used.
* If using a supported board via the board-independent API defined in xtbsp.h, If using a supported board via the board-independent API defined in xtbsp.h,
* this may be left undefined and frequency and tick divisor will be computed this may be left undefined and frequency and tick divisor will be computed
* and cached during run-time initialization. and cached during run-time initialization.
*
* NOTE ON SIMULATOR: NOTE ON SIMULATOR:
* Under the Xtensa instruction set simulator, the frequency can only be estimated Under the Xtensa instruction set simulator, the frequency can only be estimated
* because it depends on the speed of the host and the version of the simulator. because it depends on the speed of the host and the version of the simulator.
* Also because it runs much slower than hardware, it is not possible to achieve Also because it runs much slower than hardware, it is not possible to achieve
* real-time performance for most applications under the simulator. A frequency real-time performance for most applications under the simulator. A frequency
* too low does not allow enough time between timer interrupts, starving threads. too low does not allow enough time between timer interrupts, starving threads.
* To obtain a more convenient but non-real-time tick duration on the simulator, To obtain a more convenient but non-real-time tick duration on the simulator,
* compile with xt-xcc option "-DXT_SIMULATOR". compile with xt-xcc option "-DXT_SIMULATOR".
* Adjust this frequency to taste (it's not real-time anyway!). Adjust this frequency to taste (it's not real-time anyway!).
*/ */
#if defined( XT_SIMULATOR ) && !defined( XT_CLOCK_FREQ ) #if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ)
#define XT_CLOCK_FREQ configCPU_CLOCK_HZ #define XT_CLOCK_FREQ configCPU_CLOCK_HZ
#endif #endif
#if !defined( XT_CLOCK_FREQ ) && !defined( XT_BOARD ) #if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD)
#error "XT_CLOCK_FREQ must be defined for the target platform." #error "XT_CLOCK_FREQ must be defined for the target platform."
#endif #endif
/* /*
* Default number of timer "ticks" per second (default 100 for 10ms tick). Default number of timer "ticks" per second (default 100 for 10ms tick).
* RTOS may define this in its own way (if applicable) in xtensa_rtos.h. RTOS may define this in its own way (if applicable) in xtensa_rtos.h.
* User may redefine this to an optimal value for the application, either by User may redefine this to an optimal value for the application, either by
* editing this here or in xtensa_rtos.h, or compiling with xt-xcc option editing this here or in xtensa_rtos.h, or compiling with xt-xcc option
* "-DXT_TICK_PER_SEC=<value>" where <value> is a suitable number. "-DXT_TICK_PER_SEC=<value>" where <value> is a suitable number.
*/ */
#ifndef XT_TICK_PER_SEC #ifndef XT_TICK_PER_SEC
#define XT_TICK_PER_SEC configTICK_RATE_HZ /* 10 ms tick = 100 ticks per second */ #define XT_TICK_PER_SEC configTICK_RATE_HZ /* 10 ms tick = 100 ticks per second */
#endif #endif
/* /*
* Derivation of clock divisor for timer tick and interrupt (one per tick). Derivation of clock divisor for timer tick and interrupt (one per tick).
*/ */
#ifdef XT_CLOCK_FREQ #ifdef XT_CLOCK_FREQ
#define XT_TICK_DIVISOR ( XT_CLOCK_FREQ / XT_TICK_PER_SEC ) #define XT_TICK_DIVISOR (XT_CLOCK_FREQ / XT_TICK_PER_SEC)
#endif #endif
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
extern unsigned _xt_tick_divisor; extern unsigned _xt_tick_divisor;
extern void _xt_tick_divisor_init( void ); extern void _xt_tick_divisor_init(void);
#endif #endif
#endif /* XTENSA_TIMER_H */ #endif /* XTENSA_TIMER_H */

Loading…
Cancel
Save