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

This commit is contained in:
Soren Ptak 2024-01-10 09:58:45 -05:00 committed by GitHub
parent 94cb87ad30
commit 529de5606e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1012 additions and 1049 deletions

View file

@ -46,30 +46,25 @@ extern void _xt_coproc_init( void );
/*-----------------------------------------------------------*/
/* 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;
extern volatile TCB_t * volatile pxCurrentTCB;
unsigned port_xSchedulerRunning = 0; /* Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting */
unsigned port_interruptNesting = 0; /* Interrupt nesting level */
unsigned port_xSchedulerRunning = 0; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
unsigned port_interruptNesting = 0; // Interrupt nesting level
/*-----------------------------------------------------------*/
/* User exception dispatcher when exiting */
// User exception dispatcher when exiting
void _xt_user_exit(void);
/*
* Stack initialization
*/
#if portUSING_MPU_WRAPPERS
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
#else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
#endif
{
StackType_t * sp;
@ -134,14 +129,14 @@ void _xt_user_exit( void );
void vPortEndScheduler( void )
{
/* 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 )
{
/* 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
/* Initialize co-processor management for tasks. Leave CPENABLE alone. */
@ -155,13 +150,13 @@ BaseType_t xPortStartScheduler( void )
_frxt_tick_timer_init();
#if XT_USE_THREAD_SAFE_CLIB
/* Init C library */
// Init C library
vPortClibInit();
#endif
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");
/* Should not get here. */

View file

@ -40,58 +40,59 @@
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;
/*----------------------------------------------------------------------------- */
/* Init lock. */
/*----------------------------------------------------------------------------- */
void _Mtxinit( _Rmtx * mtx )
//-----------------------------------------------------------------------------
// Init lock.
//-----------------------------------------------------------------------------
void
_Mtxinit(_Rmtx * mtx)
{
*mtx = xSemaphoreCreateRecursiveMutex();
}
/*----------------------------------------------------------------------------- */
/* Destroy lock. */
/*----------------------------------------------------------------------------- */
void _Mtxdst( _Rmtx * mtx )
{
if( ( mtx != NULL ) && ( *mtx != NULL ) )
//-----------------------------------------------------------------------------
// Destroy lock.
//-----------------------------------------------------------------------------
void
_Mtxdst(_Rmtx * mtx)
{
if ((mtx != NULL) && (*mtx != NULL)) {
vSemaphoreDelete(*mtx);
}
}
/*----------------------------------------------------------------------------- */
/* Lock. */
/*----------------------------------------------------------------------------- */
void _Mtxlock( _Rmtx * mtx )
{
if( ( mtx != NULL ) && ( *mtx != NULL ) )
//-----------------------------------------------------------------------------
// Lock.
//-----------------------------------------------------------------------------
void
_Mtxlock(_Rmtx * mtx)
{
if ((mtx != NULL) && (*mtx != NULL)) {
xSemaphoreTakeRecursive(*mtx, portMAX_DELAY);
}
}
/*----------------------------------------------------------------------------- */
/* Unlock. */
/*----------------------------------------------------------------------------- */
void _Mtxunlock( _Rmtx * mtx )
{
if( ( mtx != NULL ) && ( *mtx != NULL ) )
//-----------------------------------------------------------------------------
// Unlock.
//-----------------------------------------------------------------------------
void
_Mtxunlock(_Rmtx * mtx)
{
if ((mtx != NULL) && (*mtx != NULL)) {
xSemaphoreGiveRecursive(*mtx);
}
}
/*----------------------------------------------------------------------------- */
/* Called by malloc() to allocate blocks of memory from the heap. */
/*----------------------------------------------------------------------------- */
void * _sbrk_r( struct _reent * reent,
int32_t incr )
//-----------------------------------------------------------------------------
// Called by malloc() to allocate blocks of memory from the heap.
//-----------------------------------------------------------------------------
void *
_sbrk_r (struct _reent * reent, int32_t incr)
{
extern char _end;
extern char _heap_sentry;
@ -100,14 +101,10 @@
char * base;
if (!heap_ptr)
{
heap_ptr = (char *) &_end;
}
base = heap_ptr;
if( heap_ptr + incr >= _heap_sentry_ptr )
{
if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
return (char *) -1;
}
@ -116,17 +113,19 @@
return base;
}
/*----------------------------------------------------------------------------- */
/* Global initialization for C library. */
/*----------------------------------------------------------------------------- */
void vPortClibInit( void )
//-----------------------------------------------------------------------------
// Global initialization for C library.
//-----------------------------------------------------------------------------
void
vPortClibInit(void)
{
}
/*----------------------------------------------------------------------------- */
/* Per-thread cleanup stub provided for linking, does nothing. */
/*----------------------------------------------------------------------------- */
void _reclaim_reent( void * ptr )
//-----------------------------------------------------------------------------
// Per-thread cleanup stub provided for linking, does nothing.
//-----------------------------------------------------------------------------
void
_reclaim_reent(void * ptr)
{
}
@ -145,55 +144,55 @@
static SemaphoreHandle_t xClibMutex;
static uint32_t ulClibInitDone = 0;
/*----------------------------------------------------------------------------- */
/* Get C library lock. */
/*----------------------------------------------------------------------------- */
void __malloc_lock( struct _reent * ptr )
//-----------------------------------------------------------------------------
// Get C library lock.
//-----------------------------------------------------------------------------
void
__malloc_lock(struct _reent * ptr)
{
if (!ulClibInitDone)
{
return;
}
xSemaphoreTakeRecursive(xClibMutex, portMAX_DELAY);
}
/*----------------------------------------------------------------------------- */
/* Release C library lock. */
/*----------------------------------------------------------------------------- */
void __malloc_unlock( struct _reent * ptr )
//-----------------------------------------------------------------------------
// Release C library lock.
//-----------------------------------------------------------------------------
void
__malloc_unlock(struct _reent * ptr)
{
if (!ulClibInitDone)
{
return;
}
xSemaphoreGiveRecursive(xClibMutex);
}
/*----------------------------------------------------------------------------- */
/* Lock for environment. Since we have only one global lock we can just call */
/* the malloc() lock function. */
/*----------------------------------------------------------------------------- */
void __env_lock( struct _reent * ptr )
//-----------------------------------------------------------------------------
// Lock for environment. Since we have only one global lock we can just call
// the malloc() lock function.
//-----------------------------------------------------------------------------
void
__env_lock(struct _reent * ptr)
{
__malloc_lock(ptr);
}
/*----------------------------------------------------------------------------- */
/* Unlock environment. */
/*----------------------------------------------------------------------------- */
void __env_unlock( struct _reent * ptr )
//-----------------------------------------------------------------------------
// Unlock environment.
//-----------------------------------------------------------------------------
void
__env_unlock(struct _reent * ptr)
{
__malloc_unlock(ptr);
}
/*----------------------------------------------------------------------------- */
/* Called by malloc() to allocate blocks of memory from the heap. */
/*----------------------------------------------------------------------------- */
void * _sbrk_r( struct _reent * reent,
int32_t incr )
//-----------------------------------------------------------------------------
// Called by malloc() to allocate blocks of memory from the heap.
//-----------------------------------------------------------------------------
void *
_sbrk_r (struct _reent * reent, int32_t incr)
{
extern char _end;
extern char _heap_sentry;
@ -202,14 +201,10 @@
char * base;
if (!heap_ptr)
{
heap_ptr = (char *) &_end;
}
base = heap_ptr;
if( heap_ptr + incr >= _heap_sentry_ptr )
{
if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
return (char *) -1;
}
@ -218,10 +213,11 @@
return base;
}
/*----------------------------------------------------------------------------- */
/* Global initialization for C library. */
/*----------------------------------------------------------------------------- */
void vPortClibInit( void )
//-----------------------------------------------------------------------------
// Global initialization for C library.
//-----------------------------------------------------------------------------
void
vPortClibInit(void)
{
configASSERT(!ulClibInitDone);

View file

@ -46,7 +46,7 @@
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h>
/*#include "xtensa_context.h" */
//#include "xtensa_context.h"
/*-----------------------------------------------------------
* Port specific definitions.
@ -83,33 +83,27 @@
#endif
/*-----------------------------------------------------------*/
/* portbenchmark */
// portbenchmark
#include "portbenchmark.h"
/* 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 portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
/* These can be nested */
#define portCRITICAL_NESTING_IN_TCB 1 /* For now, let FreeRTOS' (tasks.c) manage critical nesting */
// These can be nested
#define portCRITICAL_NESTING_IN_TCB 1 // For now, let FreeRTOS' (tasks.c) manage critical nesting
void vTaskEnterCritical(void);
void vTaskExitCritical(void);
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
/* Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack. */
/* They can be called from interrupts too. */
static inline unsigned portENTER_CRITICAL_NESTED()
{
unsigned state = XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL );
portbenchmarkINTERRUPT_DISABLE();
return state;
}
// Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
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)
/* These FreeRTOS versions are similar to the nested versions above */
// 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)
@ -140,46 +134,44 @@
#define portTASK_FUNCTION_PROTO( 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. */
/* 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. */
/* The field is normally used for memory protection. FreeRTOS should create another general purpose field. */
typedef struct
{
// 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:
// 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.
typedef struct {
#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 */
// 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() */
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 */
// 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 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 */
// porttrace
#if configUSE_TRACE_FACILITY_2
#include "porttrace.h"
#endif
/* configASSERT_2 if requested */
// configASSERT_2 if requested
#if configASSERT_2
#include <stdio.h>
void exit(int);
@ -190,7 +182,7 @@
/* C library support -- only XCLIB and NEWLIB are supported. */
/* 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)
extern void vPortClibInit(void);
@ -199,16 +191,14 @@
#if (XT_USE_THREAD_SAFE_CLIB > 0u) && (XSHAL_CLIB == XTHAL_CLIB_NEWLIB)
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>
#define portCLEAN_UP_TCB(pxTCB) vPortCleanUpTcbClib(&((pxTCB)->xNewLib_reent))
static inline void vPortCleanUpTcbClib(struct _reent *ptr)
{
FILE * fp = &(ptr->__sf[0]);
int i;
for( i = 0; i < 3; ++i, ++fp )
{
for (i = 0; i < 3; ++i, ++fp) {
fp->_close = NULL;
}
}

View file

@ -47,67 +47,64 @@ typedef void (* xt_exc_handler)( XtExcFrame * );
/*
* -------------------------------------------------------------------------------
* Call this function to set a handler for the specified exception.
*
* n - Exception number (type)
* f - Handler function address, NULL to uninstall handler.
*
* The handler will be passed a pointer to the exception frame, which is created
* on the stack of the thread that caused the exception.
*
* 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
* modified by the handler will be restored as part of the context. For details
* of the exception frame structure see xtensa_context.h.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Call this function to set a handler for the specified exception.
n - Exception number (type)
f - Handler function address, NULL to uninstall handler.
The handler will be passed a pointer to the exception frame, which is created
on the stack of the thread that caused the exception.
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
modified by the handler will be restored as part of the context. For details
of the exception frame structure see xtensa_context.h.
-------------------------------------------------------------------------------
*/
extern xt_exc_handler xt_set_exception_handler( int n,
xt_exc_handler f );
extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f);
/*
* -------------------------------------------------------------------------------
* Call this function to set a handler for the specified interrupt.
*
* n - Interrupt number.
* f - Handler function address, NULL to uninstall handler.
* arg - Argument to be passed to handler.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Call this function to set a handler for the specified interrupt.
n - Interrupt number.
f - Handler function address, NULL to uninstall handler.
arg - Argument to be passed to handler.
-------------------------------------------------------------------------------
*/
extern xt_handler xt_set_interrupt_handler( int n,
xt_handler f,
void * arg );
extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg);
/*
* -------------------------------------------------------------------------------
* Call this function to enable the specified interrupts.
*
* mask - Bit mask of interrupts to be enabled.
*
* Returns the previous state of the interrupt enables.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Call this function to enable the specified interrupts.
mask - Bit mask of interrupts to be enabled.
Returns the previous state of the interrupt enables.
-------------------------------------------------------------------------------
*/
extern unsigned int xt_ints_on(unsigned int mask);
/*
* -------------------------------------------------------------------------------
* Call this function to disable the specified interrupts.
*
* mask - Bit mask of interrupts to be disabled.
*
* Returns the previous state of the interrupt enables.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Call this function to disable the specified interrupts.
mask - Bit mask of interrupts to be disabled.
Returns the previous state of the interrupt enables.
-------------------------------------------------------------------------------
*/
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)
{
@ -116,10 +113,10 @@ static inline void xt_set_intset( unsigned int arg )
/*
* -------------------------------------------------------------------------------
* Call this function to clear the specified (s/w or edge-triggered)
* interrupt.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Call this function to clear the specified (s/w or edge-triggered)
interrupt.
-------------------------------------------------------------------------------
*/
static inline void xt_set_intclear(unsigned int arg)
{

View file

@ -99,7 +99,7 @@
*
* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state.
*
* -----------------------------------------------------------------------------*/
-----------------------------------------------------------------------------*/
/* Extra space required for interrupt/exception hooks. */
#ifdef XT_INTEXC_HOOKS
@ -113,8 +113,8 @@
#endif
/* 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
* be overridden from the compiler/make command line. */
For the supported libraries, we enable thread safety by default, and this can
be overridden from the compiler/make command line. */
#if (XSHAL_CLIB == XTHAL_CLIB_NEWLIB) || (XSHAL_CLIB == XTHAL_CLIB_XCLIB)
#ifndef XT_USE_THREAD_SAFE_CLIB
#define XT_USE_THREAD_SAFE_CLIB 1
@ -142,18 +142,18 @@
#define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16))
#define XT_CLIB_GLOBAL_PTR _impure_ptr
#endif
#else /* if XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#else
#define XT_HAVE_THREAD_SAFE_CLIB 0
#error The selected C runtime library is not thread safe.
#endif /* if XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#else /* if XT_USE_THREAD_SAFE_CLIB > 0u */
#endif
#else
#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.
* NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks.
* ------------------------------------------------------------------------------*/
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.
------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE)
#else
@ -161,13 +161,13 @@
#endif
/*------------------------------------------------------------------------------
* 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
* amount of space you reserve is adequate for the worst-case conditions in your
* application.
* NOTE: The windowed ABI requires more stack, since space has to be reserved
* for spilling register windows.
* ------------------------------------------------------------------------------*/
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
amount of space you reserve is adequate for the worst-case conditions in your
application.
NOTE: The windowed ABI requires more stack, since space has to be reserved
for spilling register windows.
------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else

View file

@ -57,9 +57,9 @@
/*
* -------------------------------------------------------------------------------
* 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__)
@ -73,36 +73,32 @@
#define STRUCT_BEGIN typedef struct {
#define STRUCT_FIELD(ctype,size,asname,name) ctype name;
#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
#define STRUCT_END( sname ) \
} \
sname;
#define STRUCT_END(sname) } sname;
#endif //_ASMLANGUAGE || __ASSEMBLER__
/*
* -------------------------------------------------------------------------------
* 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.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
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,
4,
XT_STK_EXIT,
exit ) /* exit point for dispatch */
STRUCT_BEGIN
STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */
STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */
STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */
STRUCT_FIELD (long, 4, XT_STK_A0, a0)
@ -166,38 +162,38 @@ STRUCT_END( XtExcFrame )
#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
* area) and some space for gcc nested functions if any.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
This is the frame size. Add space for 4 registers (interruptee's base save
area) and some space for gcc nested functions if any.
-------------------------------------------------------------------------------
*/
#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20)
/*
* -------------------------------------------------------------------------------
* SOLICITED STACK FRAME FOR A THREAD
*
* A stack frame of this structure is allocated whenever a thread enters the
* RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
* It goes on the current thread's stack.
*
* 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
* 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.
*
* Note on XT_SOL_EXIT field:
* 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
* 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
* opt to ignore this field if it has another way of distinguishing frames.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
SOLICITED STACK FRAME FOR A THREAD
A stack frame of this structure is allocated whenever a thread enters the
RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
It goes on the current thread's stack.
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
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.
Note on XT_SOL_EXIT field:
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
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
opt to ignore this field if it has another way of distinguishing frames.
-------------------------------------------------------------------------------
*/
STRUCT_BEGIN
@ -219,7 +215,7 @@ STRUCT_BEGIN
STRUCT_FIELD (long, 4, XT_SOL_A1, a1)
STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
#endif /* ifdef __XTENSA_CALL0_ABI__ */
#endif
STRUCT_END(XtSolFrame)
/* Size of solicited stack frame */
@ -227,65 +223,65 @@ STRUCT_END( XtSolFrame )
/*
* -------------------------------------------------------------------------------
* CO-PROCESSOR STATE SAVE AREA FOR A THREAD
*
* 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
* 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
* 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,
* 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.
*
* Co-processors may not be used by interrupt or exception handlers. If an
* co-processor instruction is executed by an interrupt or exception handler,
* the co-processor exception handler will trigger a kernel panic and freeze.
* 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
* overhead from interrupt handlers.
*
* 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
* 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
* co-processor (laid out as in the CPENABLE reg) help manage context-switching
* co-processors as efficiently as possible:
*
* XT_CPENABLE
* The contents of a non-running thread's CPENABLE register.
* 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.
* 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.
* 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.
* Avoids co-processor exceptions when no change of ownership is needed.
*
* XT_CPSTORED
* 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
* 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
* 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.
*
* XT_CP_CS_ST
* 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.
* Callee-saved state is saved by itself on a solicited context switch,
* and restored when needed by the coprocessor exception handler.
* Unsolicited switches will cause the entire coprocessor to be saved
* when necessary.
*
* XT_CP_ASA
* 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).
* Especially relevant for Xtensa cores configured with a very large data
* path that requires alignment greater than 16 bytes (ABI stack alignment).
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
CO-PROCESSOR STATE SAVE AREA FOR A THREAD
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
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
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,
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.
Co-processors may not be used by interrupt or exception handlers. If an
co-processor instruction is executed by an interrupt or exception handler,
the co-processor exception handler will trigger a kernel panic and freeze.
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
overhead from interrupt handlers.
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
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
co-processor (laid out as in the CPENABLE reg) help manage context-switching
co-processors as efficiently as possible:
XT_CPENABLE
The contents of a non-running thread's CPENABLE register.
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.
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.
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.
Avoids co-processor exceptions when no change of ownership is needed.
XT_CPSTORED
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
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
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.
XT_CP_CS_ST
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.
Callee-saved state is saved by itself on a solicited context switch,
and restored when needed by the coprocessor exception handler.
Unsolicited switches will cause the entire coprocessor to be saved
when necessary.
XT_CP_ASA
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).
Especially relevant for Xtensa cores configured with a very large data
path that requires alignment greater than 16 bytes (ABI stack alignment).
-------------------------------------------------------------------------------
*/
#if XCHAL_CP_NUM > 0
@ -308,26 +304,26 @@ STRUCT_END( XtSolFrame )
#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */
/* Overall size allows for dynamic alignment: */
#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
#endif /* if XCHAL_CP_NUM > 0 */
#endif
/*
* -------------------------------------------------------------------------------
* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
*
* 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).
* 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).
* 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).
* 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
* expansions are implemented as assembler macros.
* -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
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).
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).
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).
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
expansions are implemented as assembler macros.
-------------------------------------------------------------------------------
*/
#ifdef __ASSEMBLER__
@ -346,14 +342,14 @@ STRUCT_END( XtSolFrame )
ret
.endm
#define RET0 ret
#else /* ifdef __XTENSA_CALL0_ABI__ */
#else
/* Windowed */
#define ENTRY(sz) entry sp, sz
#define ENTRY0 entry sp, 0x10
#define RET(sz) retw
#define RET0 retw
#endif /* ifdef __XTENSA_CALL0_ABI__ */
#endif /* ifdef __ASSEMBLER__ */
#endif
#endif
#endif /* XTENSA_CONTEXT_H */

View file

@ -46,20 +46,24 @@
unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */
/*
* 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).
* Called when the processor clock frequency is not known at compile-time.
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).
Called when the processor clock frequency is not known at compile-time.
*/
void _xt_tick_divisor_init(void)
{
#ifdef XT_CLOCK_FREQ
_xt_tick_divisor = (XT_CLOCK_FREQ / XT_TICK_PER_SEC);
#else
#ifdef XT_BOARD
_xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC;
#else
#error "No way to obtain processor clock frequency"
#endif /* XT_BOARD */
#endif /* XT_CLOCK_FREQ */
}

View file

@ -47,7 +47,7 @@
/*
* Default handler for unhandled exceptions.
Default handler for unhandled exceptions.
*/
void xt_unhandled_exception(XtExcFrame *frame)
{
@ -56,42 +56,36 @@
/*
* This function registers a handler for the specified exception.
* The function returns the address of the previous handler.
* On error, it returns 0.
This function registers a handler for the specified exception.
The function returns the address of the previous handler.
On error, it returns 0.
*/
xt_exc_handler xt_set_exception_handler( int n,
xt_exc_handler f )
xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f)
{
xt_exc_handler old;
if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) )
{
if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
return 0; /* invalid exception number */
}
old = _xt_exception_table[n];
if( f )
{
if (f) {
_xt_exception_table[n] = f;
}
else
{
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
/* Handler table is in xtensa_intr_asm.S */
typedef struct xt_handler_table_entry
{
typedef struct xt_handler_table_entry {
void * handler;
void * arg;
} xt_handler_table_entry;
@ -100,7 +94,7 @@
/*
* Default handler for unhandled interrupts.
Default handler for unhandled interrupts.
*/
void xt_unhandled_interrupt(void * arg)
{
@ -109,38 +103,29 @@
/*
* This function registers a handler for the specified interrupt. The "arg"
* parameter specifies the argument to be passed to the handler when it is
* invoked. The function returns the address of the previous handler.
* On error, it returns 0.
This function registers a handler for the specified interrupt. The "arg"
parameter specifies the argument to be passed to the handler when it is
invoked. The function returns the address of the previous handler.
On error, it returns 0.
*/
xt_handler xt_set_interrupt_handler( int n,
xt_handler f,
void * arg )
xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg)
{
xt_handler_table_entry * entry;
xt_handler old;
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
{
if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
return 0; /* invalid interrupt number */
}
if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL )
{
return 0; /* priority level too high to safely handle in C */
}
entry = _xt_interrupt_table + n;
old = entry->handler;
if( f )
{
if (f) {
entry->handler = f;
entry->arg = arg;
}
else
{
else {
entry->handler = &xt_unhandled_interrupt;
entry->arg = (void*)n;
}

View file

@ -73,4 +73,4 @@
xSemaphoreGive(xt_overlay_mutex);
}
#endif /* if configUSE_MUTEX */
#endif

View file

@ -59,13 +59,13 @@
#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>
/*
* Convert FreeRTOSConfig definitions to XTENSA definitions.
* However these can still be overridden from the command line.
Convert FreeRTOSConfig definitions to XTENSA definitions.
However these can still be overridden from the command line.
*/
#ifndef XT_SIMULATOR
@ -98,13 +98,13 @@
/*
* Name of RTOS (for messages).
Name of RTOS (for messages).
*/
#define XT_RTOS_NAME FreeRTOS
/*
* Check some Xtensa configuration requirements and report error if not met.
* Error messages can be customize to the RTOS port.
Check some Xtensa configuration requirements and report error if not met.
Error messages can be customize to the RTOS port.
*/
#if !XCHAL_HAVE_XEA2
@ -113,93 +113,93 @@
/*******************************************************************************
*
* RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS.
*
* 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.
* Some of these functions may call back to generic functions in xtensa_context.h .
*
RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS.
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.
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.
* Allows RTOS to manage switch to any system stack and count nesting level.
* Called after minimal context has been saved, with interrupts disabled.
* 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.
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.
Called after minimal context has been saved, with interrupts disabled.
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.
*/
/* void XT_RTOS_INT_ENTER(void) */
// void XT_RTOS_INT_ENTER(void)
#define XT_RTOS_INT_ENTER _frxt_int_enter
/*
* Inform RTOS of completion of an interrupt handler, and give control to
* 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
* 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,
* 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.
* May only be called from assembly code by the 'call0' instruction.
Inform RTOS of completion of an interrupt handler, and give control to
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
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,
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.
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
/*
* Inform RTOS of the occurrence of a tick timer interrupt.
* 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.
* RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro).
Inform RTOS of the occurrence of a tick timer interrupt.
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.
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_TICK_PER_SEC configTICK_RATE_HZ
/*
* 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.
* 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
* 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.
* The implementation may use only a2-4, a15 (all other regs must be preserved).
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.
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
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.
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
/*******************************************************************************
*
* HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL.
*
* This Xtensa RTOS port provides hooks for dynamically installing exception
* and interrupt handlers to facilitate automated testing where each test
* case can install its own handler for user exceptions and each interrupt
* priority (level). This consists of an array of function pointers indexed
* 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
* 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
* 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).
* 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
* 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
* or interrupt level (see xtensa_vectors.S).
*
* High priority handlers (including NMI) must be coded in assembly, are always
* 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'
* 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
* discussion in high priority interrupts in xtensa_vectors.S). The handler
* therefore should be coded to prototype 'void h(void)' even though it plugs
* into an array of handlers of prototype 'unsigned h(unsigned)'.
*
* To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'.
*
HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL.
This Xtensa RTOS port provides hooks for dynamically installing exception
and interrupt handlers to facilitate automated testing where each test
case can install its own handler for user exceptions and each interrupt
priority (level). This consists of an array of function pointers indexed
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
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
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).
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
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
or interrupt level (see xtensa_vectors.S).
High priority handlers (including NMI) must be coded in assembly, are always
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'
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
discussion in high priority interrupts in xtensa_vectors.S). The handler
therefore should be coded to prototype 'void h(void)' even though it plugs
into an array of handlers of prototype 'unsigned h(unsigned)'.
To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'.
*******************************************************************************/
#define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI)
@ -211,12 +211,12 @@
/*******************************************************************************
*
* CONVENIENCE INCLUSIONS.
*
* 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.
*
CONVENIENCE INCLUSIONS.
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.
*******************************************************************************/
#include "xtensa_context.h"
@ -227,9 +227,9 @@
/*******************************************************************************
*
* Xtensa Port Version.
*
Xtensa Port Version.
*******************************************************************************/
#define XTENSA_PORT_VERSION 1.7

View file

@ -58,11 +58,11 @@
#include <FreeRTOSConfig.h>
/*
* 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,
* 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).
* Otherwise select the first low or medium priority interrupt timer available.
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,
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).
Otherwise select the first low or medium priority interrupt timer available.
*/
#if XCHAL_NUM_TIMERS == 0
@ -95,7 +95,7 @@
#define XT_TIMER_INDEX 0
#endif
#endif
#endif /* ifndef XT_TIMER_INDEX */
#endif
#ifndef XT_TIMER_INDEX
#error "There is no suitable timer in this Xtensa configuration."
#endif
@ -114,21 +114,21 @@
#endif /* XCHAL_NUM_TIMERS */
/*
* 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.
* 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
* and cached during run-time initialization.
*
* NOTE ON SIMULATOR:
* 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.
* 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
* 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,
* compile with xt-xcc option "-DXT_SIMULATOR".
* Adjust this frequency to taste (it's not real-time anyway!).
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.
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
and cached during run-time initialization.
NOTE ON SIMULATOR:
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.
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
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,
compile with xt-xcc option "-DXT_SIMULATOR".
Adjust this frequency to taste (it's not real-time anyway!).
*/
#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ)
#define XT_CLOCK_FREQ configCPU_CLOCK_HZ
@ -139,18 +139,18 @@
#endif
/*
* 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.
* 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
* "-DXT_TICK_PER_SEC=<value>" where <value> is a suitable number.
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.
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
"-DXT_TICK_PER_SEC=<value>" where <value> is a suitable number.
*/
#ifndef XT_TICK_PER_SEC
#define XT_TICK_PER_SEC configTICK_RATE_HZ /* 10 ms tick = 100 ticks per second */
#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
#define XT_TICK_DIVISOR (XT_CLOCK_FREQ / XT_TICK_PER_SEC)