Style: uncrusitfy

This commit is contained in:
Alfred Gedeon 2020-07-01 22:27:40 -07:00 committed by alfred gedeon
parent a5dbc2b1de
commit 718178c68a
406 changed files with 108795 additions and 106323 deletions

View file

@ -24,39 +24,41 @@
#include "FreeRTOS.h"
#include "task.h"
extern void vPortStartTask(void);
extern void vPortStartTask( void );
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
will be set to 0 prior to the first task being started. */
* will be set to 0 prior to the first task being started. */
portLONG ulCriticalNesting = 0x9999UL;
/* Used to record one tack want to swtich task after enter critical area, we need know it
* and implement task switch after exit critical area */
portLONG pendsvflag = 0;
portLONG pendsvflag = 0;
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{
StackType_t *stk = NULL;
StackType_t * stk = NULL;
stk = pxTopOfStack;
stk = pxTopOfStack;
*(--stk) = (uint32_t)pxCode; /* Entry Point */
*(--stk) = (uint32_t)0xE0000140L; /* PSR */
*(--stk) = (uint32_t)0xFFFFFFFEL; /* R15 (LR) (init value will cause fault if ever used) */
*(--stk) = (uint32_t)0x13131313L; /* R13 */
*(--stk) = (uint32_t)0x12121212L; /* R12 */
*(--stk) = (uint32_t)0x11111111L; /* R11 */
*(--stk) = (uint32_t)0x10101010L; /* R10 */
*(--stk) = (uint32_t)0x09090909L; /* R9 */
*(--stk) = (uint32_t)0x08080808L; /* R8 */
*(--stk) = (uint32_t)0x07070707L; /* R7 */
*(--stk) = (uint32_t)0x06060606L; /* R6 */
*(--stk) = (uint32_t)0x05050505L; /* R5 */
*(--stk) = (uint32_t)0x04040404L; /* R4 */
*(--stk) = (uint32_t)0x03030303L; /* R3 */
*(--stk) = (uint32_t)0x02020202L; /* R2 */
*(--stk) = (uint32_t)0x01010101L; /* R1 */
*(--stk) = (uint32_t)pvParameters; /* R0 : argument */
*( --stk ) = ( uint32_t ) pxCode; /* Entry Point */
*( --stk ) = ( uint32_t ) 0xE0000140L; /* PSR */
*( --stk ) = ( uint32_t ) 0xFFFFFFFEL; /* R15 (LR) (init value will cause fault if ever used) */
*( --stk ) = ( uint32_t ) 0x13131313L; /* R13 */
*( --stk ) = ( uint32_t ) 0x12121212L; /* R12 */
*( --stk ) = ( uint32_t ) 0x11111111L; /* R11 */
*( --stk ) = ( uint32_t ) 0x10101010L; /* R10 */
*( --stk ) = ( uint32_t ) 0x09090909L; /* R9 */
*( --stk ) = ( uint32_t ) 0x08080808L; /* R8 */
*( --stk ) = ( uint32_t ) 0x07070707L; /* R7 */
*( --stk ) = ( uint32_t ) 0x06060606L; /* R6 */
*( --stk ) = ( uint32_t ) 0x05050505L; /* R5 */
*( --stk ) = ( uint32_t ) 0x04040404L; /* R4 */
*( --stk ) = ( uint32_t ) 0x03030303L; /* R3 */
*( --stk ) = ( uint32_t ) 0x02020202L; /* R2 */
*( --stk ) = ( uint32_t ) 0x01010101L; /* R1 */
*( --stk ) = ( uint32_t ) pvParameters; /* R0 : argument */
return stk;
}
@ -79,21 +81,25 @@ void vPortEndScheduler( void )
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
ulCriticalNesting ++;
ulCriticalNesting++;
}
void vPortExitCritical( void )
{
if (ulCriticalNesting == 0) {
while(1);
if( ulCriticalNesting == 0 )
{
while( 1 )
{
}
}
ulCriticalNesting --;
if (ulCriticalNesting == 0)
ulCriticalNesting--;
if( ulCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
if (pendsvflag)
if( pendsvflag )
{
pendsvflag = 0;
portYIELD();
@ -102,30 +108,30 @@ void vPortExitCritical( void )
}
#if configUSE_PREEMPTION == 0
void xPortSysTickHandler( void )
{
portLONG ulDummy;
void xPortSysTickHandler( void )
{
portLONG ulDummy;
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
xTaskIncrementTick();
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
xTaskIncrementTick();
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
#else
void xPortSysTickHandler( void )
{
portLONG ulDummy;
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
void xPortSysTickHandler( void )
{
if (xTaskIncrementTick() != pdFALSE)
portLONG ulDummy;
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
{
portYIELD_FROM_ISR(pdTRUE);
if( xTaskIncrementTick() != pdFALSE )
{
portYIELD_FROM_ISR( pdTRUE );
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
#endif
#endif /* if configUSE_PREEMPTION == 0 */
void vPortYieldHandler( void )
{
@ -138,12 +144,17 @@ void vPortYieldHandler( void )
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
}
__attribute__((weak)) void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )
__attribute__( ( weak ) ) void vApplicationStackOverflowHook( xTaskHandle * pxTask,
signed portCHAR * pcTaskName )
{
for(;;);
for( ; ; )
{
}
}
__attribute__((weak)) void vApplicationMallocFailedHook( void )
__attribute__( ( weak ) ) void vApplicationMallocFailedHook( void )
{
for(;;);
for( ; ; )
{
}
}

View file

@ -21,17 +21,17 @@
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#include <stdlib.h>
#include <stdint.h>
#include <csi_core.h>
#include <stdlib.h>
#include <stdint.h>
#include <csi_core.h>
extern void vPortYield(void);
#ifdef __cplusplus
class vPortYield;
extern "C" {
#endif
extern void vPortYield( void );
#ifdef __cplusplus
class vPortYield;
extern "C" {
#endif
/*-----------------------------------------------------------
@ -45,114 +45,116 @@ extern "C" {
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef void (*portvectorfunc)(void);
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef void (* portvectorfunc)( void );
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/* Hardware specifics. */
#define portBYTE_ALIGNMENT 8
#define portSTACK_GROWTH -1
#define portMS_PERIOD_TICK 10
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#define portSTACK_GROWTH -1
#define portMS_PERIOD_TICK 10
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
static inline void vPortEnableInterrupt( void )
{
__enable_irq();
}
static inline void vPortEnableInterrupt( void )
{
__enable_irq();
}
static inline void vPortDisableInterrupt( void )
{
__disable_irq();
}
static inline void vPortDisableInterrupt( void )
{
__disable_irq();
}
static inline portLONG GetCurrentPSR (void)
{
return __get_PSR();
}
static inline portLONG GetCurrentPSR( void )
{
return __get_PSR();
}
static inline portLONG SaveLocalPSR (void)
{
portLONG flags = __get_PSR();
__disable_irq();
return flags;
}
static inline portLONG SaveLocalPSR( void )
{
portLONG flags = __get_PSR();
static inline void RestoreLocalPSR (portLONG newMask)
{
__asm__ __volatile__(
"mtcr %0, psr \n"
:
:"r" (newMask)
:"memory"
);
}
__disable_irq();
return flags;
}
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern __attribute__((naked)) void cpu_yeild(void);
static inline void RestoreLocalPSR( portLONG newMask )
{
__asm__ __volatile__ (
"mtcr %0, psr \n"
:
: "r" ( newMask )
: "memory"
);
}
#define portDISABLE_INTERRUPTS() vPortDisableInterrupt()
#define portENABLE_INTERRUPTS() vPortEnableInterrupt()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() SaveLocalPSR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(a) RestoreLocalPSR(a)
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern __attribute__( ( naked ) ) void cpu_yeild( void );
#define portNOP() asm("nop")
#define portDISABLE_INTERRUPTS() vPortDisableInterrupt()
#define portENABLE_INTERRUPTS() vPortEnableInterrupt()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() SaveLocalPSR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( a ) RestoreLocalPSR( a )
extern portLONG ulCriticalNesting;
extern portLONG pendsvflag;
#define portNOP() asm ( "nop" )
#define portYIELD() if (ulCriticalNesting == 0) \
{ \
vPortYield(); \
} \
else \
{ \
pendsvflag = 1; \
} \
portNOP();portNOP()
extern portLONG ulCriticalNesting;
extern portLONG pendsvflag;
#define portYIELD() \
if( ulCriticalNesting == 0 ) \
{ \
vPortYield(); \
} \
else \
{ \
pendsvflag = 1; \
} \
portNOP(); portNOP()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { \
if( xSwitchRequired != pdFALSE ) \
{ \
portYIELD(); \
} \
}while(0)
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
do { \
if( xSwitchRequired != pdFALSE ) \
{ \
portYIELD(); \
} \
} while( 0 )
#define portYIELD_FROM_ISR( a ) vTaskSwitchContext()
#define portYIELD_FROM_ISR( a ) vTaskSwitchContext()
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -29,23 +29,22 @@
* \brief exception processing for freertos
*/
// #include "embARC.h"
/* #include "embARC.h" */
#include "arc_freertos_exceptions.h"
#ifdef __GNU__
extern void gnu_printf_setup(void);
extern void gnu_printf_setup( void );
#endif
/**
* \brief freertos related cpu exception initialization, all the interrupts handled by freertos must be not
* fast irqs. If fiq is needed, please install the default firq_exc_entry or your own fast irq entry into
* the specific interrupt exception.
*/
void freertos_exc_init(void)
void freertos_exc_init( void )
{
#ifdef __GNU__
gnu_printf_setup();
#endif
#ifdef __GNU__
gnu_printf_setup();
#endif
}

View file

@ -31,14 +31,14 @@
* here, all arc cpu exceptions share the same entry, also for all interrupt
* exceptions
*/
extern void exc_entry_cpu(void); /* cpu exception entry for freertos */
extern void exc_entry_int(void); /* int exception entry for freertos */
extern void exc_entry_cpu( void ); /* cpu exception entry for freertos */
extern void exc_entry_int( void ); /* int exception entry for freertos */
/* task dispatch functions in .s */
extern void start_r(void);
extern void start_r( void );
extern void start_dispatch();
extern void dispatch();
extern void freertos_exc_init(void);
extern void freertos_exc_init( void );
#endif /* ARC_FREERTOS_EXCEPTIONS_H */
#endif /* ARC_FREERTOS_EXCEPTIONS_H */

View file

@ -24,181 +24,213 @@
*
*/
#if defined(__MW__)
#if defined( __MW__ )
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "FreeRTOS.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#include "arc/arc_exception.h"
#include "embARC_toolchain.h"
#include "embARC_debug.h"
#include "arc/arc_exception.h"
#include "embARC_toolchain.h"
#include "embARC_debug.h"
#ifdef ENABLE_FREERTOS_TLS_DEBUG
#define TLS_DEBUG(fmt, ...) EMBARC_PRINTF(fmt, ##__VA_ARGS__)
#else
#define TLS_DEBUG(fmt, ...)
#endif
#ifdef ENABLE_FREERTOS_TLS_DEBUG
#define TLS_DEBUG( fmt, ... ) EMBARC_PRINTF( fmt, ## __VA_ARGS__ )
#else
#define TLS_DEBUG( fmt, ... )
#endif
/*
* Runtime routines to execute constructors and
* destructors for task local storage.
*/
extern void __mw_run_tls_dtor();
extern void __mw_run_tls_ctor();
extern void __mw_run_tls_dtor();
extern void __mw_run_tls_ctor();
/*
* Linker generated symbols to mark .tls section addresses
* first byte .. last byte
*/
extern char _ftls[], _etls[];
#pragma weak _ftls
#pragma weak _etls
extern char _ftls[], _etls[];
#pragma weak _ftls
#pragma weak _etls
void executable_requires_tls_section(void)
{
#if _ARC
for (;;) {
_flag(1);
_nop();
_nop();
_nop();
_nop();
_nop();
}
#endif
}
#pragma off_inline(executable_requires_tls_section);
#pragma alias(executable_requires_tls_section, "executable_requires_.tls_section");
void executable_requires_tls_section( void )
{
#if _ARC
for( ; ; )
{
_flag( 1 );
_nop();
_nop();
_nop();
_nop();
_nop();
}
#endif
}
#pragma off_inline(executable_requires_tls_section);
#pragma alias(executable_requires_tls_section, "executable_requires_.tls_section");
static void* init_task_tls(void)
{
uint32_t len = (uint32_t)(_etls - _ftls);
void *tls = NULL;
static void * init_task_tls( void )
{
uint32_t len = ( uint32_t ) ( _etls - _ftls );
void * tls = NULL;
#if FREERTOS_HEAP_SEL == 3
#warning "FreeRTOS TLS support is not compatible with heap 3 solution(FREERTOS_HEAP_SEL=3)!"
#warning "You can change FREERTOS_HEAP_SEL in freertos.mk to select other heap solution."
#else
tls = pvPortMalloc(len);
#endif
if (tls) {
TLS_DEBUG("Malloc task tls:%dbytes\r\n", len);
memcpy(tls, _ftls, len);
__mw_run_tls_ctor(); // Run constructors
}
return tls;
}
#if FREERTOS_HEAP_SEL == 3
#warning "FreeRTOS TLS support is not compatible with heap 3 solution(FREERTOS_HEAP_SEL=3)!"
#warning "You can change FREERTOS_HEAP_SEL in freertos.mk to select other heap solution."
#else
tls = pvPortMalloc( len );
#endif
static void free_task_tls(void *pxTCB)
{
TaskHandle_t task2free = (TaskHandle_t)pxTCB;
if( tls )
{
TLS_DEBUG( "Malloc task tls:%dbytes\r\n", len );
memcpy( tls, _ftls, len );
__mw_run_tls_ctor(); /* Run constructors */
}
if (task2free != NULL) {
void *tls = pvTaskGetThreadLocalStoragePointer(task2free, 0);
if (tls) {
TLS_DEBUG("Free task tls\r\n");
__mw_run_tls_dtor();
vPortFree(tls);
vTaskSetThreadLocalStoragePointer(task2free, 0, NULL);
}
}
}
return tls;
}
void task_end_hook(void *pxTCB)
{
free_task_tls(pxTCB);
}
static void free_task_tls( void * pxTCB )
{
TaskHandle_t task2free = ( TaskHandle_t ) pxTCB;
static void* get_isr_tls(void)
{
// In an ISR
static int first = 1;
if (_Rarely(first)) {
first = 0;
__mw_run_tls_ctor(); // Run constructors
}
return (void *)_ftls;
}
#pragma off_inline(get_isr_tls)
if( task2free != NULL )
{
void * tls = pvTaskGetThreadLocalStoragePointer( task2free, 0 );
static void* get_task_tls(void)
{
TaskHandle_t cur_task;
if( tls )
{
TLS_DEBUG( "Free task tls\r\n" );
__mw_run_tls_dtor();
vPortFree( tls );
vTaskSetThreadLocalStoragePointer( task2free, 0, NULL );
}
}
}
cur_task = xTaskGetCurrentTaskHandle();
if (cur_task == NULL) return get_isr_tls();
void *tls = pvTaskGetThreadLocalStoragePointer(cur_task, 0);
if (tls == NULL) {
tls = init_task_tls();
if (tls) {
vTaskSetThreadLocalStoragePointer(cur_task, 0, tls);
} else {
tls = get_isr_tls();
}
}
return tls;
}
#pragma off_inline(get_task_tls)
void task_end_hook( void * pxTCB )
{
free_task_tls( pxTCB );
}
#if _ARC /* for ARC XCALLs need to preserve flags */
extern void * _Preserve_flags _mwget_tls(void);
#endif
static void * get_isr_tls( void )
{
/* In an ISR */
static int first = 1;
if( _Rarely( first ) )
{
first = 0;
__mw_run_tls_ctor(); /* Run constructors */
}
return ( void * ) _ftls;
}
#pragma off_inline(get_isr_tls)
static void * get_task_tls( void )
{
TaskHandle_t cur_task;
cur_task = xTaskGetCurrentTaskHandle();
if( cur_task == NULL )
{
return get_isr_tls();
}
void * tls = pvTaskGetThreadLocalStoragePointer( cur_task, 0 );
if( tls == NULL )
{
tls = init_task_tls();
if( tls )
{
vTaskSetThreadLocalStoragePointer( cur_task, 0, tls );
}
else
{
tls = get_isr_tls();
}
}
return tls;
}
#pragma off_inline(get_task_tls)
#if _ARC /* for ARC XCALLs need to preserve flags */
extern void * _Preserve_flags _mwget_tls( void );
#endif
/*
* Back end gens calls to find local data for this task
*/
void* _mwget_tls(void)
{
if (_ftls == (char *)0) {
executable_requires_tls_section();
}
if (exc_sense()) { /* In ISR */
return get_isr_tls();
} else { /* In Task */
return get_task_tls();
}
}
void * _mwget_tls( void )
{
if( _ftls == ( char * ) 0 )
{
executable_requires_tls_section();
}
if( exc_sense() ) /* In ISR */
{
return get_isr_tls();
}
else /* In Task */
{
return get_task_tls();
}
}
// simple interface of thread safe
typedef xSemaphoreHandle _lock_t;
#if configUSE_RECURSIVE_MUTEXES != 1
#error "configUSE_RECURSIVE_MUTEXES in FreeRTOSConfig.h need to 1"
#endif
/* simple interface of thread safe */
typedef xSemaphoreHandle _lock_t;
#if configUSE_RECURSIVE_MUTEXES != 1
#error "configUSE_RECURSIVE_MUTEXES in FreeRTOSConfig.h need to 1"
#endif
void _mwmutex_create(_lock_t *mutex_ptr)
{
*mutex_ptr = xSemaphoreCreateRecursiveMutex();
}
void _mwmutex_create( _lock_t * mutex_ptr )
{
*mutex_ptr = xSemaphoreCreateRecursiveMutex();
}
void _mwmutex_delete(_lock_t *mutex_ptr)
{
if ((*mutex_ptr) != NULL) {
vSemaphoreDelete(*mutex_ptr);
}
}
void _mwmutex_delete( _lock_t * mutex_ptr )
{
if( ( *mutex_ptr ) != NULL )
{
vSemaphoreDelete( *mutex_ptr );
}
}
void _mwmutex_lock(_lock_t mutex)
{
if ((mutex) != NULL) {
while (xSemaphoreTakeRecursive(mutex, portMAX_DELAY) != pdTRUE);
}
}
void _mwmutex_lock( _lock_t mutex )
{
if( ( mutex ) != NULL )
{
while( xSemaphoreTakeRecursive( mutex, portMAX_DELAY ) != pdTRUE )
{
}
}
}
void _mwmutex_unlock(_lock_t mutex)
{
if ((mutex) != NULL) {
xSemaphoreGiveRecursive(mutex);
}
}
void _mwmutex_unlock( _lock_t mutex )
{
if( ( mutex ) != NULL )
{
xSemaphoreGiveRecursive( mutex );
}
}
#else
#else /* if defined( __MW__ ) */
#endif /* __MW__ */

View file

@ -39,40 +39,43 @@
#include "arc_freertos_exceptions.h"
volatile unsigned int ulCriticalNesting = 999UL;
volatile unsigned int context_switch_reqflg; /* task context switch request flag in exceptions and interrupts handling */
volatile unsigned int context_switch_reqflg; /* task context switch request flag in exceptions and interrupts handling */
/* --------------------------------------------------------------------------*/
/**
* @brief kernel tick interrupt handler of freertos
*/
/* ----------------------------------------------------------------------------*/
static void vKernelTick( void *ptr )
static void vKernelTick( void * ptr )
{
/* clear timer interrupt */
timer_int_clear(BOARD_OS_TIMER_ID);
board_timer_update(configTICK_RATE_HZ);
/* clear timer interrupt */
timer_int_clear( BOARD_OS_TIMER_ID );
board_timer_update( configTICK_RATE_HZ );
if (xTaskIncrementTick()) {
portYIELD_FROM_ISR(); /* need to make task switch */
}
if( xTaskIncrementTick() )
{
portYIELD_FROM_ISR(); /* need to make task switch */
}
}
/* --------------------------------------------------------------------------*/
/**
* @brief setup freertos kernel tick
*/
/* ----------------------------------------------------------------------------*/
static void prvSetupTimerInterrupt(void)
static void prvSetupTimerInterrupt( void )
{
unsigned int cyc = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
unsigned int cyc = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
int_disable(BOARD_OS_TIMER_INTNO); /* disable os timer interrupt */
timer_stop(BOARD_OS_TIMER_ID);
timer_start(BOARD_OS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc);
int_disable( BOARD_OS_TIMER_INTNO ); /* disable os timer interrupt */
timer_stop( BOARD_OS_TIMER_ID );
timer_start( BOARD_OS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc );
int_handler_install(BOARD_OS_TIMER_INTNO, (INT_HANDLER_T)vKernelTick);
int_pri_set(BOARD_OS_TIMER_INTNO, INT_PRI_MIN);
int_enable(BOARD_OS_TIMER_INTNO);
int_handler_install( BOARD_OS_TIMER_INTNO, ( INT_HANDLER_T ) vKernelTick );
int_pri_set( BOARD_OS_TIMER_INTNO, INT_PRI_MIN );
int_enable( BOARD_OS_TIMER_INTNO );
}
/*
@ -84,32 +87,35 @@ static void prvSetupTimerInterrupt(void)
* It's not efficient but simple.
*
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{
/* To ensure asserts in tasks.c don't fail, although in this case the assert
is not really required. */
pxTopOfStack--;
/* To ensure asserts in tasks.c don't fail, although in this case the assert
* is not really required. */
pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as
expected by the portRESTORE_CONTEXT() macro. */
/* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */
/* When the task starts is will expect to find the function parameter in
R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* When the task starts is will expect to find the function parameter in
* R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* function body */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* function body */
/* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) start_r; /* dispatch return address */
/* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) start_r; /* dispatch return address */
pxTopOfStack--;
*pxTopOfStack = (StackType_t) portNO_CRITICAL_NESTING;
return pxTopOfStack;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING;
return pxTopOfStack;
}
/* --------------------------------------------------------------------------*/
/**
* @brief start the freertos scheduler, go to the first task
*
@ -118,67 +124,70 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
/* ----------------------------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
/* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt();
start_dispatch();
/* Start the timer that generates the tick ISR. */
prvSetupTimerInterrupt();
start_dispatch();
/* Should not get here! */
return 0;
/* Should not get here! */
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief
*/
/* ----------------------------------------------------------------------------*/
void vPortEndScheduler( void )
{
}
/* --------------------------------------------------------------------------*/
/**
* @brief generate a task switch request in ISR
*/
/* ----------------------------------------------------------------------------*/
void vPortYieldFromIsr(void)
void vPortYieldFromIsr( void )
{
unsigned int status32;
unsigned int status32;
status32 = cpu_lock_save();
context_switch_reqflg = true;
cpu_unlock_restore(status32);
status32 = cpu_lock_save();
context_switch_reqflg = true;
cpu_unlock_restore( status32 );
}
/* --------------------------------------------------------------------------*/
/**
* @brief
*/
/* ----------------------------------------------------------------------------*/
void vPortYield(void)
void vPortYield( void )
{
unsigned int status32;
unsigned int status32;
status32 = cpu_lock_save();
dispatch();
cpu_unlock_restore(status32);
status32 = cpu_lock_save();
dispatch();
cpu_unlock_restore( status32 );
}
/* --------------------------------------------------------------------------*/
/**
* @brief
*/
/* ----------------------------------------------------------------------------*/
void vPortEndTask(void)
void vPortEndTask( void )
{
#if ( INCLUDE_vTaskDelete == 1 )
vTaskDelete( NULL ); /* Delete task itself */
#endif
#if ( INCLUDE_vTaskDelete == 1 )
vTaskDelete(NULL); /* Delete task itself */
#endif
while(1) { /* Yield to other task */
vPortYield();
}
while( 1 ) /* Yield to other task */
{
vPortYield();
}
}
#if ARC_FEATURE_STACK_CHECK
@ -189,94 +198,95 @@ void vPortEndTask(void)
* It's a copy from task.c. We need to konw the definition of TCB for the purpose of hardware
* stack check. Pls don't forget to update it when FreeRTOS is updated.
*/
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
#endif
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
#endif
ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
StackType_t *pxStack; /*< Points to the start of the stack. */
char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
StackType_t * pxStack; /*< Points to the start of the stack. */
char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
#endif
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
UBaseType_t uxMutexesHeld;
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
UBaseType_t uxMutexesHeld;
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag;
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag;
#endif
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#if( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif
#if ( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 )
/* Allocate a Newlib reent structure that is specific to this task.
Note Newlib support has been included by popular demand, but is not
used by the FreeRTOS maintainers themselves. FreeRTOS is not
responsible for resulting newlib operation. User must be familiar with
newlib and must provide system-wide implementations of the necessary
stubs. Be warned that (at the time of writing) the current newlib design
implements a system-wide malloc() that must be provided with locks. */
struct _reent xNewLib_reent;
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 )
#if( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue;
volatile uint8_t ucNotifyState;
#endif
/* Allocate a Newlib reent structure that is specific to this task.
* Note Newlib support has been included by popular demand, but is not
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
* responsible for resulting newlib operation. User must be familiar with
* newlib and must provide system-wide implementations of the necessary
* stubs. Be warned that (at the time of writing) the current newlib design
* implements a system-wide malloc() that must be provided with locks. */
struct _reent xNewLib_reent;
#endif
/* See the comments above the definition of
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
#endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue;
volatile uint8_t ucNotifyState;
#endif
#if( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif
/* See the comments above the definition of
* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
#endif
#if( configUSE_POSIX_ERRNO == 1 )
int iTaskErrno;
#endif
#if ( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif
} tskTCB;
#if ( configUSE_POSIX_ERRNO == 1 )
int iTaskErrno;
#endif
} tskTCB;
void vPortSetStackCheck(TaskHandle_t old, TaskHandle_t new)
{
if (new != NULL) {
#if ARC_FEATURE_SEC_PRESENT
arc_aux_write(AUX_S_KSTACK_BASE, (uint32_t)(new->pxEndOfStack));
arc_aux_write(AUX_S_KSTACK_TOP, (uint32_t)(new->pxStack));
#else
arc_aux_write(AUX_KSTACK_BASE, (uint32_t)(new->pxEndOfStack));
arc_aux_write(AUX_KSTACK_TOP, (uint32_t)(new->pxStack));
#endif
}
}
#endif
void vPortSetStackCheck( TaskHandle_t old,
TaskHandle_t new )
{
if( new != NULL )
{
#if ARC_FEATURE_SEC_PRESENT
arc_aux_write( AUX_S_KSTACK_BASE, ( uint32_t ) ( new->pxEndOfStack ) );
arc_aux_write( AUX_S_KSTACK_TOP, ( uint32_t ) ( new->pxStack ) );
#else
arc_aux_write( AUX_KSTACK_BASE, ( uint32_t ) ( new->pxEndOfStack ) );
arc_aux_write( AUX_KSTACK_TOP, ( uint32_t ) ( new->pxStack ) );
#endif
}
}
#endif /* if ARC_FEATURE_STACK_CHECK */

View file

@ -25,16 +25,16 @@
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* record stack high address for stack check */
#ifndef configRECORD_STACK_HIGH_ADDRESS
#define configRECORD_STACK_HIGH_ADDRESS 1
#endif
#ifndef configRECORD_STACK_HIGH_ADDRESS
#define configRECORD_STACK_HIGH_ADDRESS 1
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -47,111 +47,111 @@ extern "C" {
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned int
#define portBASE_TYPE portLONG
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned int
#define portBASE_TYPE portLONG
#ifndef Inline
#define Inline static __inline__
#endif
#ifndef Asm
#define Asm __asm__ volatile
#endif
#ifndef Inline
#define Inline static __inline__
#endif
#ifndef Asm
#define Asm __asm__ volatile
#endif
/*
* normal constants
*/
#ifndef NULL
#define NULL 0 /* invalid pointer */
#endif /* NULL */
#ifndef NULL
#define NULL 0 /* invalid pointer */
#endif /* NULL */
#ifndef true
#define true 1 /* true */
#endif /* true */
#ifndef true
#define true 1 /* true */
#endif /* true */
#ifndef false
#define false 0 /* false */
#endif /* false */
#ifndef false
#define false 0 /* false */
#endif /* false */
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef unsigned int TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef unsigned int TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
#define portNO_CRITICAL_NESTING 0x0
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#define portNOP() Asm( "nop_s" );
#define IPM_ENABLE_ALL 1
#define portNO_CRITICAL_NESTING 0x0
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#define portNOP() Asm( "nop_s" );
#define IPM_ENABLE_ALL 1
#define portYIELD_FROM_ISR() vPortYieldFromIsr()
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR() vPortYieldFromIsr()
#define portYIELD() vPortYield()
/* Critical section management. */
#define portDISABLE_INTERRUPTS() \
{ \
Asm("clri"); \
Asm("":::"memory"); \
} \
#define portDISABLE_INTERRUPTS() \
{ \
Asm( "clri" ); \
Asm( "" ::: "memory" ); \
} \
#define portENABLE_INTERRUPTS() \
{ \
Asm("":::"memory"); \
Asm("seti"); \
} \
extern volatile unsigned int ulCriticalNesting;
#define portENTER_CRITICAL() \
{ \
portDISABLE_INTERRUPTS() \
ulCriticalNesting++; \
}
#define portEXIT_CRITICAL() \
{ \
if (ulCriticalNesting > portNO_CRITICAL_NESTING) \
#define portENABLE_INTERRUPTS() \
{ \
ulCriticalNesting--; \
if (ulCriticalNesting == portNO_CRITICAL_NESTING) \
{ \
portENABLE_INTERRUPTS() \
} \
Asm( "" ::: "memory" ); \
Asm( "seti" ); \
} \
}
extern volatile unsigned int ulCriticalNesting;
#define portENTER_CRITICAL() \
{ \
portDISABLE_INTERRUPTS() \
ulCriticalNesting++; \
}
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portEXIT_CRITICAL() \
{ \
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) \
{ \
ulCriticalNesting--; \
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) \
{ \
portENABLE_INTERRUPTS() \
} \
} \
}
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() do {} while (0) /* we use the timer */
#define portALT_GET_RUN_TIME_COUNTER_VALUE(dest) (dest = xTickCount)
#if defined(__MW__)
extern void task_end_hook(void *pxTCB);
#define portCLEAN_UP_TCB( pxTCB ) task_end_hook((void *)pxTCB)
#else
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
#endif
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
void vPortYield(void);
void vPortYieldFromIsr(void);
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() do {} while( 0 ) /* we use the timer */
#define portALT_GET_RUN_TIME_COUNTER_VALUE( dest ) ( dest = xTickCount )
#ifdef __cplusplus
}
#endif
#if defined( __MW__ )
extern void task_end_hook( void * pxTCB );
#define portCLEAN_UP_TCB( pxTCB ) task_end_hook( ( void * ) pxTCB )
#else
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
#endif
#endif /* PORTMACRO_H */
void vPortYield( void );
void vPortYieldFromIsr( void );
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

File diff suppressed because it is too large Load diff

View file

@ -22,14 +22,14 @@
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
*/
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -41,47 +41,49 @@ extern "C" {
*-----------------------------------------------------------
*/
#include <avr/wdt.h>
#include <avr/wdt.h>
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT int
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT int
typedef uint8_t StackType_t;
typedef int8_t BaseType_t;
typedef uint8_t UBaseType_t;
typedef uint8_t StackType_t;
typedef int8_t BaseType_t;
typedef uint8_t UBaseType_t;
#if configUSE_16_BIT_TICKS == 1
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
#if configUSE_16_BIT_TICKS == 1
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Critical section management. */
#define portENTER_CRITICAL() __asm__ __volatile__ ( \
"in __tmp_reg__, __SREG__" "\n\t" \
"cli" "\n\t" \
"push __tmp_reg__" "\n\t" \
::: "memory" \
)
#define portENTER_CRITICAL() \
__asm__ __volatile__ ( \
"in __tmp_reg__, __SREG__" "\n\t" \
"cli" "\n\t" \
"push __tmp_reg__" "\n\t" \
::: "memory" \
)
#define portEXIT_CRITICAL() __asm__ __volatile__ ( \
"pop __tmp_reg__" "\n\t" \
"out __SREG__, __tmp_reg__" "\n\t" \
::: "memory" \
)
#define portEXIT_CRITICAL() \
__asm__ __volatile__ ( \
"pop __tmp_reg__" "\n\t" \
"out __SREG__, __tmp_reg__" "\n\t" \
::: "memory" \
)
#define portDISABLE_INTERRUPTS() __asm__ __volatile__ ( "cli" ::: "memory")
#define portENABLE_INTERRUPTS() __asm__ __volatile__ ( "sei" ::: "memory")
#define portDISABLE_INTERRUPTS() __asm__ __volatile__ ( "cli" ::: "memory" )
#define portENABLE_INTERRUPTS() __asm__ __volatile__ ( "sei" ::: "memory" )
/*-----------------------------------------------------------*/
/* Architecture specifics. */
@ -90,66 +92,66 @@ typedef uint8_t UBaseType_t;
* Prefer to use the enhanced Watchdog Timer, but also Timer0 is ok.
*/
#if defined(WDIE) && defined(WDIF) /* If Enhanced WDT with interrupt capability is available */
#if defined( WDIE ) && defined( WDIF ) /* If Enhanced WDT with interrupt capability is available */
#define portUSE_WDTO WDTO_15MS /* use the Watchdog Timer for xTaskIncrementTick */
#define portUSE_WDTO WDTO_15MS /* use the Watchdog Timer for xTaskIncrementTick */
/* Watchdog period options: WDTO_15MS
WDTO_30MS
WDTO_60MS
WDTO_120MS
WDTO_250MS
WDTO_500MS
WDTO_1S
WDTO_2S
*/
* WDTO_30MS
* WDTO_60MS
* WDTO_120MS
* WDTO_250MS
* WDTO_500MS
* WDTO_1S
* WDTO_2S
*/
#else
#else
#define portUSE_TIMER0 /* use the 8-bit Timer0 for xTaskIncrementTick */
#define portUSE_TIMER0 /* use the 8-bit Timer0 for xTaskIncrementTick */
#endif
#endif
#define portSTACK_GROWTH ( -1 )
#define portSTACK_GROWTH ( -1 )
/* Timing for the scheduler.
* Watchdog Timer is 128kHz nominal,
* but 120 kHz at 5V DC and 25 degrees is actually more accurate,
* from data sheet.
*/
#if defined( portUSE_WDTO )
#define portTICK_PERIOD_MS ( (TickType_t) _BV( portUSE_WDTO + 4 ) )
#else
#define portTICK_PERIOD_MS ( (TickType_t) 1000 / configTICK_RATE_HZ )
#endif
#if defined( portUSE_WDTO )
#define portTICK_PERIOD_MS ( ( TickType_t ) _BV( portUSE_WDTO + 4 ) )
#else
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#endif
#define portBYTE_ALIGNMENT 1
#define portNOP() __asm__ __volatile__ ( "nop" );
#define portBYTE_ALIGNMENT 1
#define portNOP() __asm__ __volatile__ ( "nop" );
/*-----------------------------------------------------------*/
/* Kernel utilities. */
extern void vPortYield( void ) __attribute__ ( ( naked ) );
#define portYIELD() vPortYield()
extern void vPortYield( void ) __attribute__( ( naked ) );
#define portYIELD() vPortYield()
extern void vPortYieldFromISR( void ) __attribute__ ( ( naked ) );
#define portYIELD_FROM_ISR() vPortYieldFromISR()
extern void vPortYieldFromISR( void ) __attribute__( ( naked ) );
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
#if defined(__AVR_3_BYTE_PC__)
#if defined( __AVR_3_BYTE_PC__ )
/* Task function macros as described on the FreeRTOS.org WEB site. */
/* Add .lowtext tag from the avr linker script avr6.x for ATmega2560 and ATmega2561
* to make sure functions are loaded in low memory.
*/
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__ ((section (".lowtext")))
#else
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#endif
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( section( ".lowtext" ) ) )
#else
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#endif
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -25,31 +25,31 @@
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Posix port.
*
* Each task has a pthread which eases use of standard debuggers
* (allowing backtraces of tasks etc). Threads for tasks that are not
* running are blocked in sigwait().
*
* Task switch is done by resuming the thread for the next task by
* sending it the resume signal (SIGUSR1) and then suspending the
* current thread.
*
* The timer interrupt uses SIGALRM and care is taken to ensure that
* the signal handler runs only on the thread for the current task.
*
* Use of part of the standard C library requires care as some
* functions can take pthread mutexes internally which can result in
* deadlocks as the FreeRTOS kernel can switch tasks while they're
* holding a pthread mutex.
*
* Replacement malloc(), free(), calloc(), and realloc() are provided
* for glibc (see below for more information).
*
* stdio (printf() and friends) should be called from a single task
* only or serialized with a FreeRTOS primitive such as a binary
* semaphore or mutex.
*----------------------------------------------------------*/
* Implementation of functions defined in portable.h for the Posix port.
*
* Each task has a pthread which eases use of standard debuggers
* (allowing backtraces of tasks etc). Threads for tasks that are not
* running are blocked in sigwait().
*
* Task switch is done by resuming the thread for the next task by
* sending it the resume signal (SIGUSR1) and then suspending the
* current thread.
*
* The timer interrupt uses SIGALRM and care is taken to ensure that
* the signal handler runs only on the thread for the current task.
*
* Use of part of the standard C library requires care as some
* functions can take pthread mutexes internally which can result in
* deadlocks as the FreeRTOS kernel can switch tasks while they're
* holding a pthread mutex.
*
* Replacement malloc(), free(), calloc(), and realloc() are provided
* for glibc (see below for more information).
*
* stdio (printf() and friends) should be called from a single task
* only or serialized with a FreeRTOS primitive such as a binary
* semaphore or mutex.
*----------------------------------------------------------*/
#include <errno.h>
#include <pthread.h>
@ -66,44 +66,45 @@
#include "task.h"
/*-----------------------------------------------------------*/
#define SIG_RESUME SIGUSR1
#define SIG_RESUME SIGUSR1
typedef struct THREAD
{
pthread_t pthread;
pdTASK_CODE pxCode;
void *pvParams;
BaseType_t xDying;
pthread_t pthread;
pdTASK_CODE pxCode;
void * pvParams;
BaseType_t xDying;
} Thread_t;
/*
* The additional per-thread data is stored at the beginning of the
* task's stack.
*/
static inline Thread_t *prvGetThreadFromTask(TaskHandle_t xTask)
static inline Thread_t * prvGetThreadFromTask( TaskHandle_t xTask )
{
StackType_t *pxTopOfStack = *(StackType_t **)xTask;
StackType_t * pxTopOfStack = *( StackType_t ** ) xTask;
return (Thread_t *)(pxTopOfStack + 1);
return ( Thread_t * ) ( pxTopOfStack + 1 );
}
/*-----------------------------------------------------------*/
static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT;
static sigset_t xResumeSignals;
static sigset_t xAllSignals;
static sigset_t xSchedulerOriginalSignalMask;
static pthread_t hMainThread = ( pthread_t )NULL;
static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT;
static sigset_t xResumeSignals;
static sigset_t xAllSignals;
static sigset_t xSchedulerOriginalSignalMask;
static pthread_t hMainThread = ( pthread_t ) NULL;
static volatile portBASE_TYPE uxCriticalNesting;
/*-----------------------------------------------------------*/
static portBASE_TYPE xSchedulerEnd = pdFALSE;
static portBASE_TYPE xSchedulerEnd = pdFALSE;
/*-----------------------------------------------------------*/
static void prvSetupSignalsAndSchedulerPolicy( void );
static void prvSetupTimerInterrupt( void );
static void *prvWaitForStart( void * pvParams );
static void prvSwitchThread( Thread_t *xThreadToResume, Thread_t *xThreadToSuspend );
static void * prvWaitForStart( void * pvParams );
static void prvSwitchThread( Thread_t * xThreadToResume,
Thread_t * xThreadToSuspend );
static void prvSuspendSelf( void );
static void prvResumeThread( pthread_t xThreadId );
static void vPortSystemTickHandler( int sig );
@ -130,110 +131,117 @@ static void vPortStartFirstTask( void );
* timer (SIGALRM) and other signals.
*/
extern void *__libc_malloc(size_t);
extern void __libc_free(void *);
extern void *__libc_calloc(size_t, size_t);
extern void *__libc_realloc(void *ptr, size_t);
extern void * __libc_malloc( size_t );
extern void __libc_free( void * );
extern void * __libc_calloc( size_t,
size_t );
extern void * __libc_realloc( void * ptr,
size_t );
void *malloc(size_t size)
void * malloc( size_t size )
{
sigset_t xSavedSignals;
void *ptr;
sigset_t xSavedSignals;
void * ptr;
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
ptr = __libc_malloc( size );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
ptr = __libc_malloc( size );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
return ptr;
return ptr;
}
void free(void *ptr)
void free( void * ptr )
{
sigset_t xSavedSignals;
sigset_t xSavedSignals;
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
__libc_free( ptr );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
__libc_free( ptr );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
}
void *calloc(size_t nmemb, size_t size)
void * calloc( size_t nmemb,
size_t size )
{
sigset_t xSavedSignals;
void *ptr;
sigset_t xSavedSignals;
void * ptr;
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
ptr = __libc_calloc( nmemb, size );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
ptr = __libc_calloc( nmemb, size );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
return ptr;
return ptr;
}
void *realloc(void *ptr, size_t size)
void * realloc( void * ptr,
size_t size )
{
sigset_t xSavedSignals;
sigset_t xSavedSignals;
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
ptr = __libc_realloc( ptr, size );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
ptr = __libc_realloc( ptr, size );
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
return ptr;
return ptr;
}
static void prvFatalError( const char *pcCall, int iErrno )
static void prvFatalError( const char * pcCall,
int iErrno )
{
fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) );
abort();
fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) );
abort();
}
/*
* See header file for description.
*/
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack,
portSTACK_TYPE *pxEndOfStack,
pdTASK_CODE pxCode, void *pvParameters )
portSTACK_TYPE * pxPortInitialiseStack( portSTACK_TYPE * pxTopOfStack,
portSTACK_TYPE * pxEndOfStack,
pdTASK_CODE pxCode,
void * pvParameters )
{
Thread_t *thread;
pthread_attr_t xThreadAttributes;
size_t ulStackSize;
int iRet;
Thread_t * thread;
pthread_attr_t xThreadAttributes;
size_t ulStackSize;
int iRet;
(void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy );
( void ) pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy );
/*
* Store the additional thread data at the start of the stack.
*/
thread = (Thread_t *)(pxTopOfStack + 1) - 1;
pxTopOfStack = (portSTACK_TYPE *)thread - 1;
ulStackSize = (pxTopOfStack + 1 - pxEndOfStack) * sizeof(*pxTopOfStack);
/*
* Store the additional thread data at the start of the stack.
*/
thread = ( Thread_t * ) ( pxTopOfStack + 1 ) - 1;
pxTopOfStack = ( portSTACK_TYPE * ) thread - 1;
ulStackSize = ( pxTopOfStack + 1 - pxEndOfStack ) * sizeof( *pxTopOfStack );
thread->pxCode = pxCode;
thread->pvParams = pvParameters;
thread->xDying = pdFALSE;
thread->pxCode = pxCode;
thread->pvParams = pvParameters;
thread->xDying = pdFALSE;
pthread_attr_init( &xThreadAttributes );
pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
pthread_attr_init( &xThreadAttributes );
pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
vPortEnterCritical();
vPortEnterCritical();
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
prvWaitForStart, thread );
if ( iRet )
{
prvFatalError( "pthread_create", iRet );
}
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
prvWaitForStart, thread );
vPortExitCritical();
if( iRet )
{
prvFatalError( "pthread_create", iRet );
}
return pxTopOfStack;
vPortExitCritical();
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
void vPortStartFirstTask( void )
{
Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
Thread_t * pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
/* Start the first task. */
prvResumeThread( pxFirstThread->pthread );
/* Start the first task. */
prvResumeThread( pxFirstThread->pthread );
}
/*-----------------------------------------------------------*/
@ -242,125 +250,126 @@ Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
*/
portBASE_TYPE xPortStartScheduler( void )
{
int iSignal;
sigset_t xSignals;
int iSignal;
sigset_t xSignals;
hMainThread = pthread_self();
hMainThread = pthread_self();
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
prvSetupTimerInterrupt();
/* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */
prvSetupTimerInterrupt();
/* Start the first task. */
vPortStartFirstTask();
/* Start the first task. */
vPortStartFirstTask();
/* Wait until signaled by vPortEndScheduler(). */
sigemptyset( &xSignals );
sigaddset( &xSignals, SIG_RESUME );
/* Wait until signaled by vPortEndScheduler(). */
sigemptyset( &xSignals );
sigaddset( &xSignals, SIG_RESUME );
while ( !xSchedulerEnd )
{
sigwait( &xSignals, &iSignal );
}
while( !xSchedulerEnd )
{
sigwait( &xSignals, &iSignal );
}
/* Restore original signal mask. */
(void)pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL );
/* Restore original signal mask. */
( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL );
return 0;
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
struct itimerval itimer;
struct sigaction sigtick;
struct itimerval itimer;
struct sigaction sigtick;
/* Stop the timer and ignore any pending SIGALRMs that would end
* up running on the main thread when it is resumed. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = 0;
/* Stop the timer and ignore any pending SIGALRMs that would end
* up running on the main thread when it is resumed. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = 0;
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = 0;
(void)setitimer( ITIMER_REAL, &itimer, NULL );
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = 0;
( void ) setitimer( ITIMER_REAL, &itimer, NULL );
sigtick.sa_flags = 0;
sigtick.sa_handler = SIG_IGN;
sigemptyset( &sigtick.sa_mask );
sigaction( SIGALRM, &sigtick, NULL );
sigtick.sa_flags = 0;
sigtick.sa_handler = SIG_IGN;
sigemptyset( &sigtick.sa_mask );
sigaction( SIGALRM, &sigtick, NULL );
/* Signal the scheduler to exit its loop. */
xSchedulerEnd = pdTRUE;
(void)pthread_kill( hMainThread, SIG_RESUME );
/* Signal the scheduler to exit its loop. */
xSchedulerEnd = pdTRUE;
( void ) pthread_kill( hMainThread, SIG_RESUME );
prvSuspendSelf();
prvSuspendSelf();
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
if ( uxCriticalNesting == 0 )
{
vPortDisableInterrupts();
}
uxCriticalNesting++;
if( uxCriticalNesting == 0 )
{
vPortDisableInterrupts();
}
uxCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
uxCriticalNesting--;
uxCriticalNesting--;
/* If we have reached 0 then re-enable the interrupts. */
if( uxCriticalNesting == 0 )
{
vPortEnableInterrupts();
}
/* If we have reached 0 then re-enable the interrupts. */
if( uxCriticalNesting == 0 )
{
vPortEnableInterrupts();
}
}
/*-----------------------------------------------------------*/
void vPortYieldFromISR( void )
{
Thread_t *xThreadToSuspend;
Thread_t *xThreadToResume;
Thread_t * xThreadToSuspend;
Thread_t * xThreadToResume;
xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
vTaskSwitchContext();
vTaskSwitchContext();
xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
prvSwitchThread( xThreadToResume, xThreadToSuspend );
prvSwitchThread( xThreadToResume, xThreadToSuspend );
}
/*-----------------------------------------------------------*/
void vPortYield( void )
{
vPortEnterCritical();
vPortEnterCritical();
vPortYieldFromISR();
vPortYieldFromISR();
vPortExitCritical();
vPortExitCritical();
}
/*-----------------------------------------------------------*/
void vPortDisableInterrupts( void )
{
pthread_sigmask( SIG_BLOCK, &xAllSignals, NULL );
pthread_sigmask( SIG_BLOCK, &xAllSignals, NULL );
}
/*-----------------------------------------------------------*/
void vPortEnableInterrupts( void )
{
pthread_sigmask( SIG_UNBLOCK, &xAllSignals, NULL );
pthread_sigmask( SIG_UNBLOCK, &xAllSignals, NULL );
}
/*-----------------------------------------------------------*/
portBASE_TYPE xPortSetInterruptMask( void )
{
/* Interrupts are always disabled inside ISRs (signals
handlers). */
return pdTRUE;
/* Interrupts are always disabled inside ISRs (signals
* handlers). */
return pdTRUE;
}
/*-----------------------------------------------------------*/
@ -369,13 +378,13 @@ void vPortClearInterruptMask( portBASE_TYPE xMask )
}
/*-----------------------------------------------------------*/
static uint64_t prvGetTimeNs(void)
static uint64_t prvGetTimeNs( void )
{
struct timespec t;
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
clock_gettime( CLOCK_MONOTONIC, &t );
return t.tv_sec * 1000000000ull + t.tv_nsec;
return t.tv_sec * 1000000000ull + t.tv_nsec;
}
static uint64_t prvStartTimeNs;
@ -387,218 +396,228 @@ static uint64_t prvTickCount;
*/
void prvSetupTimerInterrupt( void )
{
struct itimerval itimer;
int iRet;
struct itimerval itimer;
int iRet;
/* Initialise the structure with the current timer information. */
iRet = getitimer( ITIMER_REAL, &itimer );
if ( iRet )
{
prvFatalError( "getitimer", errno );
}
/* Initialise the structure with the current timer information. */
iRet = getitimer( ITIMER_REAL, &itimer );
/* Set the interval between timer events. */
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = portTICK_RATE_MICROSECONDS;
if( iRet )
{
prvFatalError( "getitimer", errno );
}
/* Set the current count-down. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS;
/* Set the interval between timer events. */
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = portTICK_RATE_MICROSECONDS;
/* Set-up the timer interrupt. */
iRet = setitimer( ITIMER_REAL, &itimer, NULL );
if ( iRet )
{
prvFatalError( "setitimer", errno );
}
/* Set the current count-down. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS;
prvStartTimeNs = prvGetTimeNs();
/* Set-up the timer interrupt. */
iRet = setitimer( ITIMER_REAL, &itimer, NULL );
if( iRet )
{
prvFatalError( "setitimer", errno );
}
prvStartTimeNs = prvGetTimeNs();
}
/*-----------------------------------------------------------*/
static void vPortSystemTickHandler( int sig )
{
Thread_t *pxThreadToSuspend;
Thread_t *pxThreadToResume;
uint64_t xExpectedTicks;
Thread_t * pxThreadToSuspend;
Thread_t * pxThreadToResume;
uint64_t xExpectedTicks;
uxCriticalNesting++; /* Signals are blocked in this signal handler. */
uxCriticalNesting++; /* Signals are blocked in this signal handler. */
pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
/* Tick Increment, accounting for any lost signals or drift in
* the timer. */
xExpectedTicks = (prvGetTimeNs() - prvStartTimeNs)
/ (portTICK_RATE_MICROSECONDS * 1000);
do {
xTaskIncrementTick();
prvTickCount++;
} while (prvTickCount < xExpectedTicks);
/* Tick Increment, accounting for any lost signals or drift in
* the timer. */
xExpectedTicks = ( prvGetTimeNs() - prvStartTimeNs )
/ ( portTICK_RATE_MICROSECONDS * 1000 );
#if ( configUSE_PREEMPTION == 1 )
/* Select Next Task. */
vTaskSwitchContext();
do
{
xTaskIncrementTick();
prvTickCount++;
} while( prvTickCount < xExpectedTicks );
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
#if ( configUSE_PREEMPTION == 1 )
/* Select Next Task. */
vTaskSwitchContext();
prvSwitchThread(pxThreadToResume, pxThreadToSuspend);
#endif
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
uxCriticalNesting--;
prvSwitchThread( pxThreadToResume, pxThreadToSuspend );
#endif
uxCriticalNesting--;
}
/*-----------------------------------------------------------*/
void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield )
void vPortThreadDying( void * pxTaskToDelete,
volatile BaseType_t * pxPendYield )
{
Thread_t *pxThread = prvGetThreadFromTask( pxTaskToDelete );
Thread_t * pxThread = prvGetThreadFromTask( pxTaskToDelete );
pxThread->xDying = pdTRUE;
pxThread->xDying = pdTRUE;
}
void vPortCancelThread( void *pxTaskToDelete )
void vPortCancelThread( void * pxTaskToDelete )
{
Thread_t *pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
/*
* The thread has already been suspended so it can be safely
* cancelled.
*/
pthread_cancel( pxThreadToCancel->pthread );
pthread_join( pxThreadToCancel->pthread, NULL );
/*
* The thread has already been suspended so it can be safely
* cancelled.
*/
pthread_cancel( pxThreadToCancel->pthread );
pthread_join( pxThreadToCancel->pthread, NULL );
}
/*-----------------------------------------------------------*/
static void *prvWaitForStart( void * pvParams )
static void * prvWaitForStart( void * pvParams )
{
Thread_t *pxThread = pvParams;
Thread_t * pxThread = pvParams;
prvSuspendSelf();
prvSuspendSelf();
/* Resumed for the first time, unblocks all signals. */
uxCriticalNesting = 0;
vPortEnableInterrupts();
/* Resumed for the first time, unblocks all signals. */
uxCriticalNesting = 0;
vPortEnableInterrupts();
/* Call the task's entry point. */
pxThread->pxCode( pxThread->pvParams );
/* Call the task's entry point. */
pxThread->pxCode( pxThread->pvParams );
return NULL;
return NULL;
}
/*-----------------------------------------------------------*/
static void prvSwitchThread( Thread_t *pxThreadToResume,
Thread_t *pxThreadToSuspend )
static void prvSwitchThread( Thread_t * pxThreadToResume,
Thread_t * pxThreadToSuspend )
{
BaseType_t uxSavedCriticalNesting;
BaseType_t uxSavedCriticalNesting;
if ( pxThreadToSuspend != pxThreadToResume )
{
/*
* Switch tasks.
*
* The critical section nesting is per-task, so save it on the
* stack of the current (suspending thread), restoring it when
* we switch back to this task.
*/
uxSavedCriticalNesting = uxCriticalNesting;
if( pxThreadToSuspend != pxThreadToResume )
{
/*
* Switch tasks.
*
* The critical section nesting is per-task, so save it on the
* stack of the current (suspending thread), restoring it when
* we switch back to this task.
*/
uxSavedCriticalNesting = uxCriticalNesting;
prvResumeThread( pxThreadToResume->pthread );
if ( pxThreadToSuspend->xDying )
{
pthread_exit( NULL );
}
prvSuspendSelf();
prvResumeThread( pxThreadToResume->pthread );
uxCriticalNesting = uxSavedCriticalNesting;
}
if( pxThreadToSuspend->xDying )
{
pthread_exit( NULL );
}
prvSuspendSelf();
uxCriticalNesting = uxSavedCriticalNesting;
}
}
/*-----------------------------------------------------------*/
static void prvSuspendSelf( void )
{
int iSig;
int iSig;
/*
* Suspend this thread by waiting for a SIG_RESUME signal.
*
* A suspended thread must not handle signals (interrupts) so
* all signals must be blocked by calling this from:
*
* - Inside a critical section (vPortEnterCritical() /
* vPortExitCritical()).
*
* - From a signal handler that has all signals masked.
*
* - A thread with all signals blocked with pthread_sigmask().
*/
sigwait( &xResumeSignals, &iSig );
/*
* Suspend this thread by waiting for a SIG_RESUME signal.
*
* A suspended thread must not handle signals (interrupts) so
* all signals must be blocked by calling this from:
*
* - Inside a critical section (vPortEnterCritical() /
* vPortExitCritical()).
*
* - From a signal handler that has all signals masked.
*
* - A thread with all signals blocked with pthread_sigmask().
*/
sigwait( &xResumeSignals, &iSig );
}
/*-----------------------------------------------------------*/
static void prvResumeThread( pthread_t xThreadId )
{
if ( pthread_self() != xThreadId )
{
pthread_kill( xThreadId, SIG_RESUME );
}
if( pthread_self() != xThreadId )
{
pthread_kill( xThreadId, SIG_RESUME );
}
}
/*-----------------------------------------------------------*/
static void prvSetupSignalsAndSchedulerPolicy( void )
{
struct sigaction sigresume, sigtick;
int iRet;
struct sigaction sigresume, sigtick;
int iRet;
hMainThread = pthread_self();
hMainThread = pthread_self();
/* Initialise common signal masks. */
sigemptyset( &xResumeSignals );
sigaddset( &xResumeSignals, SIG_RESUME );
sigfillset( &xAllSignals );
/* Don't block SIGINT so this can be used to break into GDB while
* in a critical section. */
sigdelset( &xAllSignals, SIGINT );
/* Initialise common signal masks. */
sigemptyset( &xResumeSignals );
sigaddset( &xResumeSignals, SIG_RESUME );
sigfillset( &xAllSignals );
/*
* Block all signals in this thread so all new threads
* inherits this mask.
*
* When a thread is resumed for the first time, all signals
* will be unblocked.
*/
(void)pthread_sigmask( SIG_SETMASK, &xAllSignals,
&xSchedulerOriginalSignalMask );
/* Don't block SIGINT so this can be used to break into GDB while
* in a critical section. */
sigdelset( &xAllSignals, SIGINT );
/* SIG_RESUME is only used with sigwait() so doesn't need a
handler. */
sigresume.sa_flags = 0;
sigresume.sa_handler = SIG_IGN;
sigfillset( &sigresume.sa_mask );
/*
* Block all signals in this thread so all new threads
* inherits this mask.
*
* When a thread is resumed for the first time, all signals
* will be unblocked.
*/
( void ) pthread_sigmask( SIG_SETMASK, &xAllSignals,
&xSchedulerOriginalSignalMask );
sigtick.sa_flags = 0;
sigtick.sa_handler = vPortSystemTickHandler;
sigfillset( &sigtick.sa_mask );
/* SIG_RESUME is only used with sigwait() so doesn't need a
* handler. */
sigresume.sa_flags = 0;
sigresume.sa_handler = SIG_IGN;
sigfillset( &sigresume.sa_mask );
iRet = sigaction( SIG_RESUME, &sigresume, NULL );
if ( iRet )
{
prvFatalError( "sigaction", errno );
}
sigtick.sa_flags = 0;
sigtick.sa_handler = vPortSystemTickHandler;
sigfillset( &sigtick.sa_mask );
iRet = sigaction( SIGALRM, &sigtick, NULL );
if ( iRet )
{
prvFatalError( "sigaction", errno );
}
iRet = sigaction( SIG_RESUME, &sigresume, NULL );
if( iRet )
{
prvFatalError( "sigaction", errno );
}
iRet = sigaction( SIGALRM, &sigtick, NULL );
if( iRet )
{
prvFatalError( "sigaction", errno );
}
}
/*-----------------------------------------------------------*/
unsigned long ulPortGetRunTime( void )
{
struct tms xTimes;
struct tms xTimes;
times( &xTimes );
times( &xTimes );
return ( unsigned long ) xTimes.tms_utime;
return ( unsigned long ) xTimes.tms_utime;
}
/*-----------------------------------------------------------*/

View file

@ -26,13 +26,13 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <limits.h>
#include <limits.h>
/*-----------------------------------------------------------
* Port specific definitions.
@ -45,71 +45,72 @@ extern "C" {
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned long
#define portBASE_TYPE long
#define portPOINTER_SIZE_TYPE intptr_t
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned long
#define portBASE_TYPE long
#define portPOINTER_SIZE_TYPE intptr_t
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef unsigned long TickType_t;
#define portMAX_DELAY ( TickType_t ) ULONG_MAX
typedef unsigned long TickType_t;
#define portMAX_DELAY ( TickType_t ) ULONG_MAX
#define portTICK_TYPE_IS_ATOMIC 1
#define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portHAS_STACK_OVERFLOW_CHECKING ( 1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICK_RATE_MICROSECONDS ( ( portTickType ) 1000000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#define portSTACK_GROWTH ( -1 )
#define portHAS_STACK_OVERFLOW_CHECKING ( 1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICK_RATE_MICROSECONDS ( ( portTickType ) 1000000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
extern void vPortYield( void );
extern void vPortYield( void );
#define portYIELD() vPortYield()
#define portYIELD() vPortYield()
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortDisableInterrupts( void );
extern void vPortEnableInterrupts( void );
#define portSET_INTERRUPT_MASK() ( vPortDisableInterrupts() )
#define portCLEAR_INTERRUPT_MASK() ( vPortEnableInterrupts() )
extern void vPortDisableInterrupts( void );
extern void vPortEnableInterrupts( void );
#define portSET_INTERRUPT_MASK() ( vPortDisableInterrupts() )
#define portCLEAR_INTERRUPT_MASK() ( vPortEnableInterrupts() )
extern portBASE_TYPE xPortSetInterruptMask( void );
extern void vPortClearInterruptMask( portBASE_TYPE xMask );
extern portBASE_TYPE xPortSetInterruptMask( void );
extern void vPortClearInterruptMask( portBASE_TYPE xMask );
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
extern void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield );
extern void vPortCancelThread( void *pxTaskToDelete );
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortThreadDying( ( pvTaskToDelete ), ( pxPendYield ) )
#define portCLEAN_UP_TCB( pxTCB ) vPortCancelThread( pxTCB )
extern void vPortThreadDying( void * pxTaskToDelete,
volatile BaseType_t * pxPendYield );
extern void vPortCancelThread( void * pxTaskToDelete );
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortThreadDying( ( pvTaskToDelete ), ( pxPendYield ) )
#define portCLEAN_UP_TCB( pxTCB ) vPortCancelThread( pxTCB )
/*-----------------------------------------------------------*/
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( 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 )
/*-----------------------------------------------------------*/
/*
@ -120,14 +121,14 @@ extern void vPortCancelThread( void *pxTaskToDelete );
* Thus, only a compilier barrier is needed to prevent the compiler
* reordering.
*/
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
extern unsigned long ulPortGetRunTime( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime()
extern unsigned long ulPortGetRunTime( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime()
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -14,11 +14,11 @@
#include "sdkconfig.h"
#ifdef __GNUC__
#define USED __attribute__((used))
#define USED __attribute__( ( used ) )
#else
#define USED
#define USED
#endif
#ifdef CONFIG_ESP32_DEBUG_OCDAWARE
const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1;
const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1;
#endif

View file

@ -1,26 +1,26 @@
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
*/
* // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
* //
* // Permission is hereby granted, free of charge, to any person obtaining
* // a copy of this software and associated documentation files (the
* // "Software"), to deal in the Software without restriction, including
* // without limitation the rights to use, copy, modify, merge, publish,
* // distribute, sublicense, and/or sell copies of the Software, and to
* // permit persons to whom the Software is furnished to do so, subject to
* // the following conditions:
* //
* // The above copyright notice and this permission notice shall be included
* // in all copies or substantial portions of the Software.
* //
* // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*/
/*
* This utility helps benchmarking interrupt latency and context switches.
@ -37,7 +37,7 @@
#endif
#define portbenchmarkINTERRUPT_DISABLE()
#define portbenchmarkINTERRUPT_RESTORE(newstate)
#define portbenchmarkINTERRUPT_RESTORE( newstate )
#define portbenchmarkIntLatency()
#define portbenchmarkIntWait()
#define portbenchmarkReset()

View file

@ -1,89 +1,89 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available from the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
license and Real Time Engineers Ltd. contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
*/
* FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
* All rights reserved
*
* VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
*
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that has become a de facto standard. *
* *
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book, reference *
* manual, or both from: http://www.FreeRTOS.org/Documentation *
* *
* Thank you! *
* *
***************************************************************************
*
* This file is part of the FreeRTOS distribution.
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
* >>! NOTE: The modification to the GPL is included to allow you to !<<
* >>! distribute a combined work that includes FreeRTOS without being !<<
* >>! obliged to provide the source code for proprietary components !<<
* >>! outside of the FreeRTOS kernel. !<<
*
* FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. Full license text is available from the following
* link: http://www.freertos.org/a00114.html
*
*
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong?" *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
*
* http://www.FreeRTOS.org - Documentation, books, training, latest versions,
* license and Real Time Engineers Ltd. contact details.
*
* http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
* including FreeRTOS+Trace - an indispensable productivity tool, a DOS
* compatible FAT file system, and our tiny thread aware UDP/IP stack.
*
* http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
* Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
* licenses offer ticketed support, indemnification and middleware.
*
* http://www.SafeRTOS.com - High Integrity Systems also provide a safety
* engineered and independently SIL3 certified version for use in safety and
* mission critical applications that require provable dependability.
*
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __ASSEMBLER__
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <stdint.h>
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h>
#include "esp_timer.h" /* required for FreeRTOS run time stats */
#include "esp_system.h"
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h>
#include "esp_timer.h" /* required for FreeRTOS run time stats */
#include "esp_system.h"
#include <esp_heap_caps.h>
#include "soc/soc_memory_layout.h"
#include <esp_heap_caps.h>
#include "soc/soc_memory_layout.h"
//#include "xtensa_context.h"
/*#include "xtensa_context.h" */
/*-----------------------------------------------------------
* Port specific definitions.
@ -97,117 +97,122 @@ extern "C" {
/* Type definitions. */
#define portCHAR int8_t
#define portFLOAT float
#define portDOUBLE double
#define portLONG int32_t
#define portSHORT int16_t
#define portSTACK_TYPE uint8_t
#define portBASE_TYPE int
#define portCHAR int8_t
#define portFLOAT float
#define portDOUBLE double
#define portLONG int32_t
#define portSHORT int16_t
#define portSTACK_TYPE uint8_t
#define portBASE_TYPE int
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned portBASE_TYPE UBaseType_t;
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned portBASE_TYPE UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
// portbenchmark
#include "portbenchmark.h"
/* portbenchmark */
#include "portbenchmark.h"
#include "sdkconfig.h"
#include "esp_attr.h"
#include "sdkconfig.h"
#include "esp_attr.h"
/* "mux" data structure (spinlock) */
typedef struct {
/* owner field values:
* 0 - Uninitialized (invalid)
* portMUX_FREE_VAL - Mux is free, can be locked by either CPU
* CORE_ID_PRO / CORE_ID_APP - Mux is locked to the particular core
*
* Any value other than portMUX_FREE_VAL, CORE_ID_PRO, CORE_ID_APP indicates corruption
*/
uint32_t owner;
/* count field:
* If mux is unlocked, count should be zero.
* If mux is locked, count is non-zero & represents the number of recursive locks on the mux.
*/
uint32_t count;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char *lastLockedFn;
int lastLockedLine;
#endif
} portMUX_TYPE;
typedef struct
{
/* owner field values:
* 0 - Uninitialized (invalid)
* portMUX_FREE_VAL - Mux is free, can be locked by either CPU
* CORE_ID_PRO / CORE_ID_APP - Mux is locked to the particular core
*
* Any value other than portMUX_FREE_VAL, CORE_ID_PRO, CORE_ID_APP indicates corruption
*/
uint32_t owner;
#define portMUX_FREE_VAL 0xB33FFFFF
/* count field:
* If mux is unlocked, count should be zero.
* If mux is locked, count is non-zero & represents the number of recursive locks on the mux.
*/
uint32_t count;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char * lastLockedFn;
int lastLockedLine;
#endif
} portMUX_TYPE;
#define portMUX_FREE_VAL 0xB33FFFFF
/* Special constants for vPortCPUAcquireMutexTimeout() */
#define portMUX_NO_TIMEOUT (-1) /* When passed for 'timeout_cycles', spin forever if necessary */
#define portMUX_TRY_LOCK 0 /* Try to acquire the spinlock a single time only */
#define portMUX_NO_TIMEOUT ( -1 ) /* When passed for 'timeout_cycles', spin forever if necessary */
#define portMUX_TRY_LOCK 0 /* Try to acquire the spinlock a single time only */
// Keep this in sync with the portMUX_TYPE struct definition please.
#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
#define portMUX_INITIALIZER_UNLOCKED { \
.owner = portMUX_FREE_VAL, \
.count = 0, \
}
#else
#define portMUX_INITIALIZER_UNLOCKED { \
.owner = portMUX_FREE_VAL, \
.count = 0, \
.lastLockedFn = "(never locked)", \
.lastLockedLine = -1 \
}
#endif
/* Keep this in sync with the portMUX_TYPE struct definition please. */
#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
#define portMUX_INITIALIZER_UNLOCKED \
{ \
.owner = portMUX_FREE_VAL, \
.count = 0, \
}
#else
#define portMUX_INITIALIZER_UNLOCKED \
{ \
.owner = portMUX_FREE_VAL, \
.count = 0, \
.lastLockedFn = "(never locked)", \
.lastLockedLine = -1 \
}
#endif /* ifndef CONFIG_FREERTOS_PORTMUX_DEBUG */
#define portASSERT_IF_IN_ISR() vPortAssertIfInISR()
void vPortAssertIfInISR();
#define portASSERT_IF_IN_ISR() vPortAssertIfInISR()
void vPortAssertIfInISR();
#define portCRITICAL_NESTING_IN_TCB 1
#define portCRITICAL_NESTING_IN_TCB 1
/*
Modifications to portENTER_CRITICAL.
* Modifications to portENTER_CRITICAL.
*
* For an introduction, see "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst
*
* The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by
* disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because
* interrupts are disabled, ISRs can't corrupt data structures either.
*
* For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop
* the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding
* a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will
* spinlock in the portENTER_CRITICAL code until the first CPU is done.
*
* For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same
* CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the
* data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks
* do not disable the interrupts (because they already are).
*
* This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels
* will break this scheme.
*
* Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning
* that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
* behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
*/
void vPortCPUInitializeMutex( portMUX_TYPE * mux );
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
#error CONFIG_FREERTOS_PORTMUX_DEBUG not supported in Amazon FreeRTOS
#endif
For an introduction, see "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst
The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by
disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because
interrupts are disabled, ISRs can't corrupt data structures either.
For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop
the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding
a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will
spinlock in the portENTER_CRITICAL code until the first CPU is done.
For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same
CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the
data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks
do not disable the interrupts (because they already are).
This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels
will break this scheme.
Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning
that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
*/
void vPortCPUInitializeMutex(portMUX_TYPE *mux);
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
#error CONFIG_FREERTOS_PORTMUX_DEBUG not supported in Amazon FreeRTOS
#endif
void vTaskExitCritical();
void vTaskEnterCritical();
static inline void vPortConsumeSpinlockArg(int unused, ...)
{
}
void vTaskExitCritical();
void vTaskEnterCritical();
static inline void vPortConsumeSpinlockArg( int unused,
... )
{
}
/** @brief Acquire a portmux spinlock with a timeout
*
@ -217,66 +222,73 @@ static inline void vPortConsumeSpinlockArg(int unused, ...)
*
* @return true if mutex is successfully acquired, false on timeout.
*/
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
void vPortCPUReleaseMutex(portMUX_TYPE *mux);
bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,
int timeout_cycles );
void vPortCPUReleaseMutex( portMUX_TYPE * mux );
#define portENTER_CRITICAL(...) do { vTaskEnterCritical(); vPortConsumeSpinlockArg(0, ##__VA_ARGS__); } while(0)
#define portEXIT_CRITICAL(...) do { vTaskExitCritical(); vPortConsumeSpinlockArg(0, ##__VA_ARGS__); } while(0)
#define portENTER_CRITICAL( ... ) do { vTaskEnterCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 )
#define portEXIT_CRITICAL( ... ) do { vTaskExitCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 )
#define portENTER_CRITICAL_ISR(mux) vPortCPUAcquireMutexTimeout(mux, portMUX_NO_TIMEOUT)
#define portEXIT_CRITICAL_ISR(mux) vPortCPUReleaseMutex(mux)
#define portENTER_CRITICAL_ISR( mux ) vPortCPUAcquireMutexTimeout( mux, portMUX_NO_TIMEOUT )
#define portEXIT_CRITICAL_ISR( mux ) vPortCPUReleaseMutex( mux )
#define portENTER_CRITICAL_SAFE(mux) do { \
if (xPortInIsrContext()) { \
portENTER_CRITICAL_ISR(mux); \
} else { \
portENTER_CRITICAL(mux); \
} \
} while(0)
#define portENTER_CRITICAL_SAFE( mux ) \
do { \
if( xPortInIsrContext() ) { \
portENTER_CRITICAL_ISR( mux ); \
} \
else { \
portENTER_CRITICAL( mux ); \
} \
} while( 0 )
#define portEXIT_CRITICAL_SAFE(mux) do { \
if (xPortInIsrContext()) { \
portEXIT_CRITICAL_ISR(mux); \
} else { \
portEXIT_CRITICAL(mux); \
} \
} while(0)
#define portEXIT_CRITICAL_SAFE( mux ) \
do { \
if( xPortInIsrContext() ) { \
portEXIT_CRITICAL_ISR( mux ); \
} \
else { \
portEXIT_CRITICAL( mux ); \
} \
} while( 0 )
// 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.
//
// Only applies to one CPU. See notes above & below for reasons not to use these.
#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)
/* 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. */
/* */
/* Only applies to one CPU. See notes above & below for reasons not to use these. */
#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 )
// Cleaner solution allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
// WARNING: Only applies to current CPU. See notes above.
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)
/* Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. */
/* They can be called from interrupts too. */
/* WARNING: Only applies to current CPU. See notes above. */
static inline unsigned portENTER_CRITICAL_NESTED()
{
unsigned state = XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL );
// 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)
portbenchmarkINTERRUPT_DISABLE();
return state;
}
#define portEXIT_CRITICAL_NESTED( state ) do { portbenchmarkINTERRUPT_RESTORE( state ); XTOS_RESTORE_JUST_INTLEVEL( state ); } while( 0 )
//Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force
//the stack memory to always be internal.
#define pvPortMallocTcbMem(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
#define pvPortMallocStackMem(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
/* 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 )
//xTaskCreateStatic uses these functions to check incoming memory.
#define portVALID_TCB_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr))
#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
#define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr)
#else
#define portVALID_STACK_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr))
#endif
/*Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force */
/*the stack memory to always be internal. */
#define pvPortMallocTcbMem( size ) heap_caps_malloc( size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT )
#define pvPortMallocStackMem( size ) heap_caps_malloc( size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT )
/*xTaskCreateStatic uses these functions to check incoming memory. */
#define portVALID_TCB_MEM( ptr ) ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) )
#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
#define portVALID_STACK_MEM( ptr ) esp_ptr_byte_accessible( ptr )
#else
#define portVALID_STACK_MEM( ptr ) ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) )
#endif
/*
* Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
@ -287,91 +299,98 @@ static inline unsigned portENTER_CRITICAL_NESTED() {
* *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
* ESP32 (portMUX assertions would fail).
*/
static inline void uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
__asm__ __volatile__ (
"WSR %2,SCOMPARE1 \n"
"S32C1I %0, %1, 0 \n"
:"=r"(*set)
:"r"(addr), "r"(compare), "0"(*set)
);
}
static inline void uxPortCompareSet( volatile uint32_t * addr,
uint32_t compare,
uint32_t * set )
{
__asm__ __volatile__ (
"WSR %2,SCOMPARE1 \n"
"S32C1I %0, %1, 0 \n"
: "=r" ( *set )
: "r" ( addr ), "r" ( compare ), "0" ( *set )
);
}
void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set);
void uxPortCompareSetExtram( volatile uint32_t * addr,
uint32_t compare,
uint32_t * set );
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4
#define portNOP() XT_NOP()
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4
#define portNOP() XT_NOP()
/*-----------------------------------------------------------*/
/* Fine resolution time */
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
//ccount or esp_timer are initialized elsewhere
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
/*ccount or esp_timer are initialized elsewhere */
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
/* Coarse resolution time (us) */
#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) x = (uint32_t)esp_timer_get_time()
#endif
#define portALT_GET_RUN_TIME_COUNTER_VALUE( x ) x = ( uint32_t ) esp_timer_get_time()
#endif
/* Kernel utilities. */
void vPortYield( void );
void _frxt_setup_switch( void );
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR() {traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch();}
void vPortYield( void );
void _frxt_setup_switch( void );
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR() { traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch(); }
static inline uint32_t xPortGetCoreID();
static inline uint32_t xPortGetCoreID();
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( 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 )
// 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
#endif
/* 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 */
#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 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;
#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
/* 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
bool vApplicationSleep( TickType_t xExpectedIdleTime );
bool vApplicationSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime )
#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime )
void _xt_coproc_release(volatile void * coproc_sa_base);
void _xt_coproc_release( volatile void * coproc_sa_base );
/*
@ -381,36 +400,36 @@ void _xt_coproc_release(volatile void * coproc_sa_base);
* non-FreeRTOS-specific code, and behave the same as
* pvPortMalloc()/vPortFree().
*/
#define pvPortMalloc heap_caps_malloc_default
#define vPortFree heap_caps_free
#define xPortGetFreeHeapSize esp_get_free_heap_size
#define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size
#define pvPortMalloc heap_caps_malloc_default
#define vPortFree heap_caps_free
#define xPortGetFreeHeapSize esp_get_free_heap_size
#define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size
/*
* Send an interrupt to another core in order to make the task running
* on it yield for a higher-priority task.
*/
void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
void vPortYieldOtherCore( BaseType_t coreid ) PRIVILEGED_FUNCTION;
/*
Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
watchpoint around.
* Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
* watchpoint around.
*/
void vPortSetStackWatchpoint( void* pxStackStart );
void vPortSetStackWatchpoint( void * pxStackStart );
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
*/
BaseType_t xPortInIsrContext();
BaseType_t xPortInIsrContext();
/*
* This function will be called in High prio ISRs. Returns true if the current core was in ISR context
* before calling into high prio ISR context.
*/
BaseType_t xPortInterruptedFromISRContext();
BaseType_t xPortInterruptedFromISRContext();
/*
* The structures and methods of manipulating the MPU are contained within the
@ -419,42 +438,46 @@ BaseType_t xPortInterruptedFromISRContext();
* Fills the xMPUSettings structure with the memory region information
* contained in xRegions.
*/
#if( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION;
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) PRIVILEGED_FUNCTION;
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
#endif
#if ( portUSING_MPU_WRAPPERS == 1 )
struct xMEMORY_REGION;
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t usStackDepth ) PRIVILEGED_FUNCTION;
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings );
#endif
/* Multi-core: get current core ID */
static inline uint32_t IRAM_ATTR xPortGetCoreID() {
int id;
asm (
"rsr.prid %0\n"
" extui %0,%0,13,1"
:"=r"(id));
return id;
}
static inline uint32_t IRAM_ATTR xPortGetCoreID()
{
int id;
asm (
"rsr.prid %0\n"
" extui %0,%0,13,1"
: "=r" ( id ) );
return id;
}
/* Get tick rate per second */
uint32_t xPortGetTickRateHz(void);
uint32_t xPortGetTickRateHz( void );
// porttrace
#if configUSE_TRACE_FACILITY_2
#include "porttrace.h"
#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
/* 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
#endif // __ASSEMBLER__
#endif // __ASSEMBLER__
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -1,28 +1,28 @@
/*******************************************************************************
Copyright (c) 2006-2015 Cadence Design Systems Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
* Copyright (c) 2006-2015 Cadence Design Systems Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
/******************************************************************************
Xtensa-specific API for RTOS ports.
* Xtensa-specific API for RTOS ports.
******************************************************************************/
#ifndef __XTENSA_API_H__
@ -34,97 +34,99 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* 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 void (*xt_exc_handler)(XtExcFrame *);
typedef void (* xt_exc_handler)( XtExcFrame * );
/*
-------------------------------------------------------------------------------
Call this function to set a handler for the specified exception. The handler
will be installed on the core that calls this function.
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);
* -------------------------------------------------------------------------------
* Call this function to set a handler for the specified exception. The handler
* will be installed on the core that calls this function.
*
* 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 );
/*
-------------------------------------------------------------------------------
Call this function to set a handler for the specified interrupt. The handler
will be installed on the core that calls this function.
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);
* -------------------------------------------------------------------------------
* Call this function to set a handler for the specified interrupt. The handler
* will be installed on the core that calls this function.
*
* 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 );
/*
-------------------------------------------------------------------------------
Call this function to enable the specified interrupts on the core that runs
this code.
mask - Bit mask of interrupts to be enabled.
-------------------------------------------------------------------------------
*/
extern void xt_ints_on(unsigned int mask);
* -------------------------------------------------------------------------------
* Call this function to enable the specified interrupts on the core that runs
* this code.
*
* mask - Bit mask of interrupts to be enabled.
* -------------------------------------------------------------------------------
*/
extern void xt_ints_on( unsigned int mask );
/*
-------------------------------------------------------------------------------
Call this function to disable the specified interrupts on the core that runs
this code.
mask - Bit mask of interrupts to be disabled.
-------------------------------------------------------------------------------
*/
extern void xt_ints_off(unsigned int mask);
* -------------------------------------------------------------------------------
* Call this function to disable the specified interrupts on the core that runs
* this code.
*
* mask - Bit mask of interrupts to be disabled.
* -------------------------------------------------------------------------------
*/
extern void xt_ints_off( unsigned int mask );
/*
-------------------------------------------------------------------------------
Call this function to set the specified (s/w) interrupt.
-------------------------------------------------------------------------------
*/
static inline void xt_set_intset(unsigned int arg)
* -------------------------------------------------------------------------------
* Call this function to set the specified (s/w) interrupt.
* -------------------------------------------------------------------------------
*/
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)
interrupt.
-------------------------------------------------------------------------------
*/
static inline void xt_set_intclear(unsigned int arg)
* -------------------------------------------------------------------------------
* Call this function to clear the specified (s/w or edge-triggered)
* interrupt.
* -------------------------------------------------------------------------------
*/
static inline void xt_set_intclear( unsigned int arg )
{
xthal_set_intclear(arg);
xthal_set_intclear( arg );
}
/*
-------------------------------------------------------------------------------
Call this function to get handler's argument for the specified interrupt.
n - Interrupt number.
-------------------------------------------------------------------------------
*/
extern void * xt_get_interrupt_handler_arg(int n);
* -------------------------------------------------------------------------------
* Call this function to get handler's argument for the specified interrupt.
*
* n - Interrupt number.
* -------------------------------------------------------------------------------
*/
extern void * xt_get_interrupt_handler_arg( int n );
#endif /* __XTENSA_API_H__ */

View file

@ -1,47 +1,47 @@
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
Configuration-specific information for Xtensa build. This file must be
included in FreeRTOSConfig.h to properly set up the config-dependent
parameters correctly.
NOTE: 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.
* // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
* //
* // Permission is hereby granted, free of charge, to any person obtaining
* // a copy of this software and associated documentation files (the
* // "Software"), to deal in the Software without restriction, including
* // without limitation the rights to use, copy, modify, merge, publish,
* // distribute, sublicense, and/or sell copies of the Software, and to
* // permit persons to whom the Software is furnished to do so, subject to
* // the following conditions:
* //
* // The above copyright notice and this permission notice shall be included
* // in all copies or substantial portions of the Software.
* //
* // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*
* Configuration-specific information for Xtensa build. This file must be
* included in FreeRTOSConfig.h to properly set up the config-dependent
* parameters correctly.
*
* NOTE: 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.
*
*******************************************************************************/
#ifndef XTENSA_CONFIG_H
#define XTENSA_CONFIG_H
#define XTENSA_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include "xtensa_context.h"
#include "xtensa_context.h"
/*-----------------------------------------------------------------------------
@ -59,26 +59,26 @@ extern "C" {
* If this is not true, i.e. one or more interrupt handlers make deep calls then
* 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.
*
* 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.
*
*
* 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.
*
* Usage:
*
*
* 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
* space to be allocated for tasks that use the C library
* reentrant functions. See below for more information.
*
*
* 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
* was chosen for your system.
*
*
* 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
* task. In case you want to use stacks smaller than this
@ -91,56 +91,55 @@ extern "C" {
*
* 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
#ifdef __XTENSA_CALL0_ABI__
#define STK_INTEXC_EXTRA 0x200
#else
#define STK_INTEXC_EXTRA 0x180
#endif
#else
#define STK_INTEXC_EXTRA 0
#endif
#ifdef XT_INTEXC_HOOKS
#ifdef __XTENSA_CALL0_ABI__
#define STK_INTEXC_EXTRA 0x200
#else
#define STK_INTEXC_EXTRA 0x180
#endif
#else
#define STK_INTEXC_EXTRA 0
#endif
#define XT_CLIB_CONTEXT_AREA_SIZE 0
#define XT_CLIB_CONTEXT_AREA_SIZE 0
/*------------------------------------------------------------------------------
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
#define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE)
#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.
* ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE )
#else
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE )
#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.
------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else
#define XT_USER_SIZE 0x400
#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.
* ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else
#define XT_USER_SIZE 0x400
#endif
/* 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. */
#define XT_STACK_EXTRA (XT_XTRA_SIZE)
#define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE)
#define XT_STACK_EXTRA ( XT_XTRA_SIZE )
#define XT_STACK_EXTRA_CLIB ( XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE )
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* XTENSA_CONFIG_H */

View file

@ -1,44 +1,44 @@
/*******************************************************************************
Copyright (c) 2006-2015 Cadence Design Systems Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
This header contains definitions and macros for use primarily by Xtensa
RTOS assembly coded source files. It includes and uses the Xtensa hardware
abstraction layer (HAL) to deal with config specifics. It may also be
included in C source files.
!! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !!
NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
* Copyright (c) 2006-2015 Cadence Design Systems Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*
* XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
*
* This header contains definitions and macros for use primarily by Xtensa
* RTOS assembly coded source files. It includes and uses the Xtensa hardware
* abstraction layer (HAL) to deal with config specifics. It may also be
* included in C source files.
*
* !! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !!
*
* NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
*
*******************************************************************************/
#ifndef XTENSA_CONTEXT_H
#define XTENSA_CONTEXT_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#endif
#include <xtensa/config/tie.h>
@ -48,331 +48,335 @@ NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
/* 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.
* -------------------------------------------------------------------------------
*/
#ifdef STRUCT_BEGIN
#undef STRUCT_BEGIN
#undef STRUCT_FIELD
#undef STRUCT_AFIELD
#undef STRUCT_END
#undef STRUCT_BEGIN
#undef STRUCT_FIELD
#undef STRUCT_AFIELD
#undef STRUCT_END
#endif
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ )
#define STRUCT_BEGIN .pushsection .text; .struct 0
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
#define STRUCT_END(sname) sname##Size:; .popsection
#define STRUCT_BEGIN .pushsection.text; .struct 0
#define STRUCT_FIELD( ctype, size, asname, name ) asname:.space size
#define STRUCT_AFIELD( ctype, size, asname, name, n ) asname:.space( size ) *( n )
#define STRUCT_END( sname ) sname ## Size:; .popsection
#else
#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_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;
#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.
* -------------------------------------------------------------------------------
*/
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_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)
STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
STRUCT_FIELD (long, 4, XT_STK_A2, a2)
STRUCT_FIELD (long, 4, XT_STK_A3, a3)
STRUCT_FIELD (long, 4, XT_STK_A4, a4)
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)
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 )
STRUCT_FIELD( long, 4, XT_STK_A1, a1 ) /* stack pointer before interrupt */
STRUCT_FIELD( long, 4, XT_STK_A2, a2 )
STRUCT_FIELD( long, 4, XT_STK_A3, a3 )
STRUCT_FIELD( long, 4, XT_STK_A4, a4 )
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
STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
STRUCT_FIELD( long, 4, XT_STK_LBEG, lbeg )
STRUCT_FIELD( long, 4, XT_STK_LEND, lend )
STRUCT_FIELD( long, 4, XT_STK_LCOUNT, lcount )
#endif
#ifndef __XTENSA_CALL0_ABI__
/* Temporary space for saving stuff during window spill */
STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
STRUCT_FIELD( long, 4, XT_STK_TMP0, tmp0 )
STRUCT_FIELD( long, 4, XT_STK_TMP1, tmp1 )
STRUCT_FIELD( long, 4, XT_STK_TMP2, tmp2 )
#endif
#ifdef XT_USE_SWPRI
/* Storage for virtual priority mask */
STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
STRUCT_FIELD( long, 4, XT_STK_VPRI, vpri )
#endif
#ifdef XT_USE_OVLY
/* Storage for overlay state */
STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
STRUCT_FIELD( long, 4, XT_STK_OVLY, ovly )
#endif
STRUCT_END(XtExcFrame)
STRUCT_END( XtExcFrame )
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define XT_STK_NEXT1 XtExcFrameSize
#if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ )
#define XT_STK_NEXT1 XtExcFrameSize
#else
#define XT_STK_NEXT1 sizeof(XtExcFrame)
#define XT_STK_NEXT1 sizeof( XtExcFrame )
#endif
/* Allocate extra storage if needed */
#if XCHAL_EXTRA_SA_SIZE != 0
#if XCHAL_EXTRA_SA_ALIGN <= 16
#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
#else
#if XCHAL_EXTRA_SA_ALIGN <= 16
#define XT_STK_EXTRA ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 )
#else
/* 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)
#endif
#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
#define XT_STK_EXTRA ( ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 ) + XCHAL_EXTRA_SA_ALIGN )
#endif
#define XT_STK_NEXT2 ( XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE )
#else
#define XT_STK_NEXT2 XT_STK_NEXT1
#define XT_STK_NEXT2 XT_STK_NEXT1
#endif
#endif /* if XCHAL_EXTRA_SA_SIZE != 0 */
/*
-------------------------------------------------------------------------------
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)
* -------------------------------------------------------------------------------
* 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
#ifdef __XTENSA_CALL0_ABI__
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
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_A13, a13)
STRUCT_FIELD (long, 4, XT_SOL_A14, a14)
STRUCT_FIELD (long, 4, XT_SOL_A15, a15)
#else
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
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_A1, a1)
STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
#endif
STRUCT_END(XtSolFrame)
STRUCT_FIELD( long,
4,
XT_SOL_EXIT,
exit )
STRUCT_FIELD( long, 4, XT_SOL_PC, pc )
STRUCT_FIELD( long, 4, XT_SOL_PS, ps )
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_A13, a13 )
STRUCT_FIELD( long, 4, XT_SOL_A14, a14 )
STRUCT_FIELD( long, 4, XT_SOL_A15, a15 )
#else /* ifdef __XTENSA_CALL0_ABI__ */
STRUCT_FIELD( long, 4, XT_SOL_EXIT, exit )
STRUCT_FIELD( long, 4, XT_SOL_PC, pc )
STRUCT_FIELD( long, 4, XT_SOL_PS, ps )
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_A1, a1 )
STRUCT_FIELD( long, 4, XT_SOL_A2, a2 )
STRUCT_FIELD( long, 4, XT_SOL_A3, a3 )
#endif /* ifdef __XTENSA_CALL0_ABI__ */
STRUCT_END( XtSolFrame )
/* 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
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
/* Offsets of each coprocessor save area within the 'aligned save area': */
#define XT_CP0_SA 0
#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_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_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_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_CP0_SA 0
#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_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_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_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 )
/* Offsets within the overall save area: */
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active 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_ASA 8 /* (4 bytes) ptr to aligned save area */
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active 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_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
#define XT_CP_SIZE 0
#endif
#define XT_CP_SIZE ( 12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN )
#else /* if XCHAL_CP_NUM > 0 */
#define XT_CP_SIZE 0
#endif /* if XCHAL_CP_NUM > 0 */
/*
Macro to get the current core ID. Only uses the reg given as an argument.
Reading PRID on the ESP32 gives us 0xCDCD on the PRO processor (0)
and 0xABAB on the APP CPU (1). We can distinguish between the two by checking
bit 13: it's 1 on the APP and 0 on the PRO processor.
*/
* Macro to get the current core ID. Only uses the reg given as an argument.
* Reading PRID on the ESP32 gives us 0xCDCD on the PRO processor (0)
* and 0xABAB on the APP CPU (1). We can distinguish between the two by checking
* bit 13: it's 1 on the APP and 0 on the PRO processor.
*/
#ifdef __ASSEMBLER__
.macro getcoreid reg
rsr.prid \reg
extui \reg,\reg,13,1
.endm
.macro getcoreid reg
rsr.prid \ reg
extui \ reg, \ reg, 13, 1
.endm
#endif
#define CORE_ID_PRO 0xCDCD
#define CORE_ID_APP 0xABAB
#define CORE_ID_PRO 0xCDCD
#define CORE_ID_APP 0xABAB
/*
-------------------------------------------------------------------------------
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__
#ifdef __XTENSA_CALL0_ABI__
/* Call0 */
#define ENTRY(sz) entry1 sz
.macro entry1 size=0x10
addi sp, sp, -\size
s32i a0, sp, 0
.endm
#define ENTRY0
#define RET(sz) ret1 sz
.macro ret1 size=0x10
l32i a0, sp, 0
addi sp, sp, \size
ret
.endm
#define RET0 ret
#else
/* Windowed */
#define ENTRY(sz) entry sp, sz
#define ENTRY0 entry sp, 0x10
#define RET(sz) retw
#define RET0 retw
#endif
#endif
#ifdef __XTENSA_CALL0_ABI__
/* Call0 */
#define ENTRY( sz ) entry1 sz
.macro entry1 size = 0x10
addi sp, sp, -\ size
s32i a0, sp, 0
.endm
#define ENTRY0
#define RET( sz ) ret1 sz
.macro ret1 size = 0x10
l32i a0, sp, 0
addi sp, sp, \ size
ret
.endm
#define RET0 ret
#else /* ifdef __XTENSA_CALL0_ABI__ */
/* 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 /* XTENSA_CONTEXT_H */

View file

@ -1,232 +1,231 @@
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
RTOS-SPECIFIC INFORMATION FOR XTENSA RTOS ASSEMBLER SOURCES
(FreeRTOS Port)
This header is the primary glue between generic Xtensa RTOS support
sources and a specific RTOS port for Xtensa. It contains definitions
and macros for use primarily by Xtensa assembly coded source files.
Macros in this header map callouts from generic Xtensa files to specific
RTOS functions. It may also be included in C source files.
Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa
architecture, using the Xtensa hardware abstraction layer (HAL) to deal
with configuration specifics.
Should be included by all Xtensa generic and RTOS port-specific sources.
* // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
* //
* // Permission is hereby granted, free of charge, to any person obtaining
* // a copy of this software and associated documentation files (the
* // "Software"), to deal in the Software without restriction, including
* // without limitation the rights to use, copy, modify, merge, publish,
* // distribute, sublicense, and/or sell copies of the Software, and to
* // permit persons to whom the Software is furnished to do so, subject to
* // the following conditions:
* //
* // The above copyright notice and this permission notice shall be included
* // in all copies or substantial portions of the Software.
* //
* // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*
* RTOS-SPECIFIC INFORMATION FOR XTENSA RTOS ASSEMBLER SOURCES
* (FreeRTOS Port)
*
* This header is the primary glue between generic Xtensa RTOS support
* sources and a specific RTOS port for Xtensa. It contains definitions
* and macros for use primarily by Xtensa assembly coded source files.
*
* Macros in this header map callouts from generic Xtensa files to specific
* RTOS functions. It may also be included in C source files.
*
* Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa
* architecture, using the Xtensa hardware abstraction layer (HAL) to deal
* with configuration specifics.
*
* Should be included by all Xtensa generic and RTOS port-specific sources.
*
*******************************************************************************/
#ifndef XTENSA_RTOS_H
#define XTENSA_RTOS_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#else
#include <xtensa/config/core.h>
#include <xtensa/config/core.h>
#endif
#include <xtensa/corebits.h>
#include <xtensa/config/system.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
#if configXT_SIMULATOR
#define XT_SIMULATOR 1 /* Simulator mode */
#endif
#if configXT_SIMULATOR
#define XT_SIMULATOR 1 /* Simulator mode */
#endif
#endif
#ifndef XT_BOARD
#if configXT_BOARD
#define XT_BOARD 1 /* Board mode */
#endif
#if configXT_BOARD
#define XT_BOARD 1 /* Board mode */
#endif
#endif
#ifndef XT_TIMER_INDEX
#if defined configXT_TIMER_INDEX
#define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */
#endif
#if defined configXT_TIMER_INDEX
#define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */
#endif
#endif
#ifndef XT_INTEXC_HOOKS
#if configXT_INTEXC_HOOKS
#define XT_INTEXC_HOOKS 1 /* Enables exception hooks */
#endif
#if configXT_INTEXC_HOOKS
#define XT_INTEXC_HOOKS 1 /* Enables exception hooks */
#endif
#endif
#if !defined(XT_SIMULATOR) && !defined(XT_BOARD)
#error Either XT_SIMULATOR or XT_BOARD must be defined.
#if !defined( XT_SIMULATOR ) && !defined( XT_BOARD )
#error Either XT_SIMULATOR or XT_BOARD must be defined.
#endif
/*
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
#error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)."
#error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)."
#endif
/*******************************************************************************
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.
*/
// void XT_RTOS_INT_ENTER(void)
#define XT_RTOS_INT_ENTER _frxt_int_enter
* 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) */
#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.
*/
// void XT_RTOS_INT_EXIT(void)
* 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) */
#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).
*/
// void XT_RTOS_TIMER_INT(void)
#define XT_RTOS_TIMER_INT _frxt_timer_int
#define XT_TICK_PER_SEC configTICK_RATE_HZ
* 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) */
#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).
*/
// void* XT_RTOS_CP_STATE(void)
* 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) */
#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)
#define XT_INTEXC_HOOK_NUM ( 1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI )
#ifndef __ASSEMBLER__
typedef unsigned (*XT_INTEXC_HOOK)(unsigned cause);
extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
typedef unsigned (* XT_INTEXC_HOOK)( unsigned cause );
extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[ XT_INTEXC_HOOK_NUM ];
#endif
/*******************************************************************************
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"
#ifdef XT_RTOS_TIMER_INT
#include "xtensa_timer.h"
#include "xtensa_timer.h"
#endif
/*******************************************************************************
Xtensa Port Version.
*
* Xtensa Port Version.
*
*******************************************************************************/
#define XTENSA_PORT_VERSION 1.4.2
#define XTENSA_PORT_VERSION_STRING "1.4.2"
#define XTENSA_PORT_VERSION 1.4 .2
#define XTENSA_PORT_VERSION_STRING "1.4.2"
#endif /* XTENSA_RTOS_H */

View file

@ -1,159 +1,158 @@
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY
This header contains definitions and macros for use primarily by Xtensa
RTOS assembly coded source files. It includes and uses the Xtensa hardware
abstraction layer (HAL) to deal with config specifics. It may also be
included in C source files.
User may edit to modify timer selection and to specify clock frequency and
tick duration to match timer interrupt to the real-time tick duration.
If the RTOS has no timer interrupt, then there is no tick timer and the
clock frequency is irrelevant, so all of these macros are left undefined
and the Xtensa core configuration need not have a timer.
* // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
* //
* // Permission is hereby granted, free of charge, to any person obtaining
* // a copy of this software and associated documentation files (the
* // "Software"), to deal in the Software without restriction, including
* // without limitation the rights to use, copy, modify, merge, publish,
* // distribute, sublicense, and/or sell copies of the Software, and to
* // permit persons to whom the Software is furnished to do so, subject to
* // the following conditions:
* //
* // The above copyright notice and this permission notice shall be included
* // in all copies or substantial portions of the Software.
* //
* // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*
* XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY
*
* This header contains definitions and macros for use primarily by Xtensa
* RTOS assembly coded source files. It includes and uses the Xtensa hardware
* abstraction layer (HAL) to deal with config specifics. It may also be
* included in C source files.
*
* User may edit to modify timer selection and to specify clock frequency and
* tick duration to match timer interrupt to the real-time tick duration.
*
* If the RTOS has no timer interrupt, then there is no tick timer and the
* clock frequency is irrelevant, so all of these macros are left undefined
* and the Xtensa core configuration need not have a timer.
*
*******************************************************************************/
#ifndef XTENSA_TIMER_H
#define XTENSA_TIMER_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#endif
#include <xtensa/corebits.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"
/*
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
#error "This Xtensa configuration is unsupported, it has no timers."
#error "This Xtensa configuration is unsupported, it has no timers."
#else
#ifndef XT_TIMER_INDEX
#if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 3
#ifndef XT_TIMER_INDEX
#if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER3_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 3
#endif
#endif
#if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER2_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 2
#endif
#endif
#if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER1_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#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
#if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 2
#endif
#endif
#if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#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
#error "There is no suitable timer in this Xtensa configuration."
#endif
#define XT_CCOMPARE (CCOMPARE + 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_INTEN (1 << XT_TIMER_INTNUM)
#define XT_CCOMPARE ( CCOMPARE + 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_INTEN ( 1 << XT_TIMER_INTNUM )
#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
#error "The timer selected by XT_TIMER_INDEX does not exist in this core."
#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
#error "The timer interrupt cannot be high priority (use medium or low)."
#endif
#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
#error "The timer selected by XT_TIMER_INDEX does not exist in this core."
#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
#error "The timer interrupt cannot be high priority (use medium or low)."
#endif
#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!).
*/
#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ)
#define XT_CLOCK_FREQ configCPU_CLOCK_HZ
* 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
#endif
#if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD)
#error "XT_CLOCK_FREQ must be defined for the target platform."
#if !defined( XT_CLOCK_FREQ ) && !defined( XT_BOARD )
#error "XT_CLOCK_FREQ must be defined for the target platform."
#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 */
#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)
#define XT_TICK_DIVISOR ( XT_CLOCK_FREQ / XT_TICK_PER_SEC )
#endif
#ifndef __ASSEMBLER__
extern unsigned _xt_tick_divisor;
extern void _xt_tick_divisor_init(void);
extern unsigned _xt_tick_divisor;
extern void _xt_tick_divisor_init( void );
#endif
#endif /* XTENSA_TIMER_H */
#endif /* XTENSA_TIMER_H */

View file

@ -1,94 +1,94 @@
/*
FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
*/
* FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
* All rights reserved
*
* VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
*
* This file is part of the FreeRTOS distribution.
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
***************************************************************************
* >>! NOTE: The modification to the GPL is included to allow you to !<<
* >>! distribute a combined work that includes FreeRTOS without being !<<
* >>! obliged to provide the source code for proprietary components !<<
* >>! outside of the FreeRTOS kernel. !<<
***************************************************************************
*
* FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. Full license text is available on the following
* link: http://www.freertos.org/a00114.html
*
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
*
* http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
* the FAQ page "My application does not run, what could be wrong?". Have you
* defined configASSERT()?
*
* http://www.FreeRTOS.org/support - In return for receiving this top quality
* embedded software for free we request you assist our global community by
* participating in the support forum.
*
* http://www.FreeRTOS.org/training - Investing in training allows your team to
* be as productive as possible as early as possible. Now you can receive
* FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
* Ltd, and the world's leading authority on the world's leading RTOS.
*
* http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
* including FreeRTOS+Trace - an indispensable productivity tool, a DOS
* compatible FAT file system, and our tiny thread aware UDP/IP stack.
*
* http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
* Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
*
* http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
* Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
* licenses offer ticketed support, indemnification and commercial middleware.
*
* http://www.SafeRTOS.com - High Integrity Systems also provide a safety
* engineered and independently SIL3 certified version for use in safety and
* mission critical applications that require provable dependability.
*
*/
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
*/
* // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
* //
* // Permission is hereby granted, free of charge, to any person obtaining
* // a copy of this software and associated documentation files (the
* // "Software"), to deal in the Software without restriction, including
* // without limitation the rights to use, copy, modify, merge, publish,
* // distribute, sublicense, and/or sell copies of the Software, and to
* // permit persons to whom the Software is furnished to do so, subject to
* // the following conditions:
* //
* // The above copyright notice and this permission notice shall be included
* // in all copies or substantial portions of the Software.
* //
* // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*/
#include <stdlib.h>
#include <xtensa/config/core.h>
@ -108,153 +108,166 @@
#include "esp_intr_alloc.h"
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);
extern void _frxt_tick_timer_init( void );
/* Defined in xtensa_context.S */
extern void _xt_coproc_init(void);
extern void _xt_coproc_init( void );
#if CONFIG_FREERTOS_CORETIMER_0
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#define SYSTICK_INTR_ID ( ETS_INTERNAL_TIMER0_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF )
#endif
#if CONFIG_FREERTOS_CORETIMER_1
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#define SYSTICK_INTR_ID ( ETS_INTERNAL_TIMER1_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF )
#endif
/*-----------------------------------------------------------*/
unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
unsigned port_xSchedulerRunning[ portNUM_PROCESSORS ] = { 0 }; /* Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting */
unsigned port_interruptNesting[ portNUM_PROCESSORS ] = { 0 }; /* Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit */
/*-----------------------------------------------------------*/
// User exception dispatcher when exiting
void _xt_user_exit(void);
/* 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, *tp;
XtExcFrame *frame;
#if XCHAL_CP_NUM > 0
uint32_t *p;
#endif
StackType_t * sp, * tp;
XtExcFrame * frame;
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = (StackType_t *) (((UBaseType_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
#if XCHAL_CP_NUM > 0
uint32_t * p;
#endif
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for (tp = sp; tp <= pxTopOfStack; ++tp)
*tp = 0;
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = ( StackType_t * ) ( ( ( UBaseType_t ) ( pxTopOfStack + 1 ) - XT_CP_SIZE - XT_STK_FRMSZ ) & ~0xf );
frame = (XtExcFrame *) sp;
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for( tp = sp; tp <= pxTopOfStack; ++tp )
{
*tp = 0;
}
/* Explicitly initialize certain saved registers */
frame->pc = (UBaseType_t) pxCode; /* task entrypoint */
frame->a0 = 0; /* to terminate GDB backtrace */
frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */
frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */
frame = ( XtExcFrame * ) sp;
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
/* Also set entry point argument parameter. */
#ifdef __XTENSA_CALL0_ABI__
frame->a2 = (UBaseType_t) pvParameters;
frame->ps = PS_UM | PS_EXCM;
#else
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
frame->a6 = (UBaseType_t) pvParameters;
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
#endif
/* Explicitly initialize certain saved registers */
frame->pc = ( UBaseType_t ) pxCode; /* task entrypoint */
frame->a0 = 0; /* to terminate GDB backtrace */
frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ; /* physical top of stack frame */
frame->exit = ( UBaseType_t ) _xt_user_exit; /* user exception exit dispatcher */
#ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */
frame->vpri = 0xFFFFFFFF;
#endif
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
/* Also set entry point argument parameter. */
#ifdef __XTENSA_CALL0_ABI__
frame->a2 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM;
#else
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
frame->a6 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );
#endif
#if XCHAL_CP_NUM > 0
/* Init the coprocessor save area (see xtensa_context.h) */
/* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
#ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */
frame->vpri = 0xFFFFFFFF;
#endif
#if XCHAL_CP_NUM > 0
/* Init the coprocessor save area (see xtensa_context.h) */
/* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
* //p = (uint32_t *) xMPUSettings->coproc_area;
*/
p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf);
p[0] = 0;
p[1] = 0;
p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN;
#endif
*/
p = ( uint32_t * ) ( ( ( uint32_t ) pxTopOfStack - XT_CP_SIZE ) & ~0xf );
p[ 0 ] = 0;
p[ 1 ] = 0;
p[ 2 ] = ( ( ( uint32_t ) p ) + 12 + XCHAL_TOTAL_SA_ALIGN - 1 ) & -XCHAL_TOTAL_SA_ALIGN;
#endif
return sp;
return sp;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* It is unlikely that the Xtensa port will get stopped. If required simply
disable the tick interrupt here. */
/* It is unlikely that the Xtensa port will get stopped. If required simply
* 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. */
_xt_coproc_init();
#endif
#if XCHAL_CP_NUM > 0
/* Initialize co-processor management for tasks. Leave CPENABLE alone. */
_xt_coproc_init();
#endif
/* Init the tick divisor value */
_xt_tick_divisor_init();
/* Init the tick divisor value */
_xt_tick_divisor_init();
/* Setup the hardware to generate the tick. */
_frxt_tick_timer_init();
/* Setup the hardware to generate the tick. */
_frxt_tick_timer_init();
port_xSchedulerRunning[xPortGetCoreID()] = 1;
port_xSchedulerRunning[ xPortGetCoreID() ] = 1;
// Cannot be directly called from C; never returns
__asm__ volatile ("call0 _frxt_dispatch\n");
/* Cannot be directly called from C; never returns */
__asm__ volatile ( "call0 _frxt_dispatch\n" );
/* Should not get here. */
return pdTRUE;
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
BaseType_t xPortSysTickHandler( void )
{
BaseType_t ret;
unsigned interruptMask;
BaseType_t ret;
unsigned interruptMask;
portbenchmarkIntLatency();
traceISR_ENTER(SYSTICK_INTR_ID);
portbenchmarkIntLatency();
traceISR_ENTER( SYSTICK_INTR_ID );
/* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be
* disabled before calling xTaskIncrementTick as it access the
* kernel lists. */
interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
ret = xTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );
/* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be
* disabled before calling xTaskIncrementTick as it access the
* kernel lists. */
interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
ret = xTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );
if( ret != pdFALSE )
{
portYIELD_FROM_ISR();
} else {
traceISR_EXIT();
}
return ret;
if( ret != pdFALSE )
{
portYIELD_FROM_ISR();
}
else
{
traceISR_EXIT();
}
return ret;
}
void vPortYieldOtherCore( BaseType_t coreid ) {
esp_crosscore_int_send_yield( coreid );
void vPortYieldOtherCore( BaseType_t coreid )
{
esp_crosscore_int_send_yield( coreid );
}
/*-----------------------------------------------------------*/
@ -263,25 +276,28 @@ void vPortYieldOtherCore( BaseType_t coreid ) {
* Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
*/
#if portUSING_MPU_WRAPPERS
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth )
{
#if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = (StackType_t*)((((uint32_t)(pxBottomOfStack + usStackDepth - 1)) - XT_CP_SIZE ) & ~0xf);
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t usStackDepth )
{
#if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( ( uint32_t ) ( pxBottomOfStack + usStackDepth - 1 ) ) - XT_CP_SIZE ) & ~0xf );
/* 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().
*/
#endif
}
/* 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().
*/
#endif
}
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings )
{
/* If task has live floating point registers somewhere, release them */
_xt_coproc_release( xMPUSettings->coproc_area );
}
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings )
{
/* If task has live floating point registers somewhere, release them */
_xt_coproc_release( xMPUSettings->coproc_area );
}
#endif
#endif /* if portUSING_MPU_WRAPPERS */
/*
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
@ -289,12 +305,13 @@ void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings )
*/
BaseType_t xPortInIsrContext()
{
unsigned int irqStatus;
BaseType_t ret;
irqStatus=portENTER_CRITICAL_NESTED();
ret=(port_interruptNesting[xPortGetCoreID()] != 0);
portEXIT_CRITICAL_NESTED(irqStatus);
return ret;
unsigned int irqStatus;
BaseType_t ret;
irqStatus = portENTER_CRITICAL_NESTED();
ret = ( port_interruptNesting[ xPortGetCoreID() ] != 0 );
portEXIT_CRITICAL_NESTED( irqStatus );
return ret;
}
/*
@ -303,29 +320,31 @@ BaseType_t xPortInIsrContext()
*/
BaseType_t IRAM_ATTR xPortInterruptedFromISRContext()
{
return (port_interruptNesting[xPortGetCoreID()] != 0);
return( port_interruptNesting[ xPortGetCoreID() ] != 0 );
}
void vPortAssertIfInISR()
{
if (xPortInIsrContext()) {
ets_printf("core=%d port_interruptNesting=%d\n\n", xPortGetCoreID(), port_interruptNesting[xPortGetCoreID()]);
}
configASSERT(!xPortInIsrContext());
if( xPortInIsrContext() )
{
ets_printf( "core=%d port_interruptNesting=%d\n\n", xPortGetCoreID(), port_interruptNesting[ xPortGetCoreID() ] );
}
configASSERT( !xPortInIsrContext() );
}
/*
* For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked.
*/
void vPortCPUInitializeMutex(portMUX_TYPE *mux) {
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
ets_printf("Initializing mux %p\n", mux);
mux->lastLockedFn="(never locked)";
mux->lastLockedLine=-1;
#endif
mux->owner=portMUX_FREE_VAL;
mux->count=0;
void vPortCPUInitializeMutex( portMUX_TYPE * mux )
{
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
ets_printf( "Initializing mux %p\n", mux );
mux->lastLockedFn = "(never locked)";
mux->lastLockedLine = -1;
#endif
mux->owner = portMUX_FREE_VAL;
mux->count = 0;
}
#include "portmux_impl.h"
@ -334,33 +353,47 @@ void vPortCPUInitializeMutex(portMUX_TYPE *mux) {
* For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long.
*/
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
void vPortCPUAcquireMutex(portMUX_TYPE *mux, const char *fnName, int line) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
vPortCPUAcquireMutexIntsDisabled(mux, portMUX_NO_TIMEOUT, fnName, line);
portEXIT_CRITICAL_NESTED(irqStatus);
}
void vPortCPUAcquireMutex( portMUX_TYPE * mux,
const char * fnName,
int line )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles, const char *fnName, int line) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
bool result = vPortCPUAcquireMutexIntsDisabled(mux, timeout_cycles, fnName, line);
portEXIT_CRITICAL_NESTED(irqStatus);
return result;
}
vPortCPUAcquireMutexIntsDisabled( mux, portMUX_NO_TIMEOUT, fnName, line );
portEXIT_CRITICAL_NESTED( irqStatus );
}
#else
void vPortCPUAcquireMutex(portMUX_TYPE *mux) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
vPortCPUAcquireMutexIntsDisabled(mux, portMUX_NO_TIMEOUT);
portEXIT_CRITICAL_NESTED(irqStatus);
}
bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,
int timeout_cycles,
const char * fnName,
int line )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
bool result = vPortCPUAcquireMutexIntsDisabled( mux, timeout_cycles, fnName, line );
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
bool result = vPortCPUAcquireMutexIntsDisabled(mux, timeout_cycles);
portEXIT_CRITICAL_NESTED(irqStatus);
return result;
}
#endif
portEXIT_CRITICAL_NESTED( irqStatus );
return result;
}
#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
void vPortCPUAcquireMutex( portMUX_TYPE * mux )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
vPortCPUAcquireMutexIntsDisabled( mux, portMUX_NO_TIMEOUT );
portEXIT_CRITICAL_NESTED( irqStatus );
}
bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,
int timeout_cycles )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
bool result = vPortCPUAcquireMutexIntsDisabled( mux, timeout_cycles );
portEXIT_CRITICAL_NESTED( irqStatus );
return result;
}
#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
/*
@ -369,59 +402,76 @@ bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles) {
* Mux must be already locked by this core
*/
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
void vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *fnName, int line) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
vPortCPUReleaseMutexIntsDisabled(mux, fnName, line);
portEXIT_CRITICAL_NESTED(irqStatus);
}
void vPortCPUReleaseMutex( portMUX_TYPE * mux,
const char * fnName,
int line )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
vPortCPUReleaseMutexIntsDisabled( mux, fnName, line );
portEXIT_CRITICAL_NESTED( irqStatus );
}
#else
void vPortCPUReleaseMutex(portMUX_TYPE *mux) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
vPortCPUReleaseMutexIntsDisabled(mux);
portEXIT_CRITICAL_NESTED(irqStatus);
}
#endif
void vPortCPUReleaseMutex( portMUX_TYPE * mux )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();
void vPortSetStackWatchpoint( void* pxStackStart ) {
//Set watchpoint 1 to watch the last 32 bytes of the stack.
//Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because
//the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32
//bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most
//28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes.
//This way, we make sure we trigger before/when the stack canary is corrupted, not after.
int addr=(int)pxStackStart;
addr=(addr+31)&(~31);
esp_set_watchpoint(1, (char*)addr, 32, ESP_WATCHPOINT_STORE);
vPortCPUReleaseMutexIntsDisabled( mux );
portEXIT_CRITICAL_NESTED( irqStatus );
}
#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
void vPortSetStackWatchpoint( void * pxStackStart )
{
/*Set watchpoint 1 to watch the last 32 bytes of the stack. */
/*Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because */
/*the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32 */
/*bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most */
/*28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes. */
/*This way, we make sure we trigger before/when the stack canary is corrupted, not after. */
int addr = ( int ) pxStackStart;
addr = ( addr + 31 ) & ( ~31 );
esp_set_watchpoint( 1, ( char * ) addr, 32, ESP_WATCHPOINT_STORE );
}
#if defined(CONFIG_SPIRAM_SUPPORT)
#if defined( CONFIG_SPIRAM_SUPPORT )
/*
* Compare & set (S32C1) does not work in external RAM. Instead, this routine uses a mux (in internal memory) to fake it.
*/
static portMUX_TYPE extram_mux = portMUX_INITIALIZER_UNLOCKED;
static portMUX_TYPE extram_mux = portMUX_INITIALIZER_UNLOCKED;
void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
uint32_t prev;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
vPortCPUAcquireMutexIntsDisabled(&extram_mux, portMUX_NO_TIMEOUT, __FUNCTION__, __LINE__);
#else
vPortCPUAcquireMutexIntsDisabled(&extram_mux, portMUX_NO_TIMEOUT);
#endif
prev=*addr;
if (prev==compare) {
*addr=*set;
}
*set=prev;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
vPortCPUReleaseMutexIntsDisabled(&extram_mux, __FUNCTION__, __LINE__);
#else
vPortCPUReleaseMutexIntsDisabled(&extram_mux);
#endif
}
void uxPortCompareSetExtram( volatile uint32_t * addr,
uint32_t compare,
uint32_t * set )
{
uint32_t prev;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
vPortCPUAcquireMutexIntsDisabled( &extram_mux, portMUX_NO_TIMEOUT, __FUNCTION__, __LINE__ );
#else
vPortCPUAcquireMutexIntsDisabled( &extram_mux, portMUX_NO_TIMEOUT );
#endif
prev = *addr;
if( prev == compare )
{
*addr = *set;
}
*set = prev;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
vPortCPUReleaseMutexIntsDisabled( &extram_mux, __FUNCTION__, __LINE__ );
#else
vPortCPUReleaseMutexIntsDisabled( &extram_mux );
#endif
}
#endif //defined(CONFIG_SPIRAM_SUPPORT)
uint32_t xPortGetTickRateHz(void) {
return (uint32_t)configTICK_RATE_HZ;
uint32_t xPortGetTickRateHz( void )
{
return ( uint32_t ) configTICK_RATE_HZ;
}

View file

@ -1,111 +1,113 @@
/*
Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
*/
* Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
* Copyright (C) 2015 Real Time Engineers Ltd.
*
* All rights reserved
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
***************************************************************************
* >>! NOTE: The modification to the GPL is included to allow you to !<<
* >>! distribute a combined work that includes FreeRTOS without being !<<
* >>! obliged to provide the source code for proprietary components !<<
* >>! outside of the FreeRTOS kernel. !<<
***************************************************************************
*
* FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. Full license text is available on the following
* link: http://www.freertos.org/a00114.html
*/
/* This header exists for performance reasons, in order to inline the
implementation of vPortCPUAcquireMutexIntsDisabled and
vPortCPUReleaseMutexIntsDisabled into the
vTaskEnterCritical/vTaskExitCritical functions in task.c as well as the
vPortCPUAcquireMutex/vPortCPUReleaseMutex implementations.
Normally this kind of performance hack is over the top, but
vTaskEnterCritical/vTaskExitCritical is called a great
deal by FreeRTOS internals.
It should be #included by freertos port.c or tasks.c, in esp-idf.
The way it works is that it essentially uses portmux_impl.inc.h as a
generator template of sorts. When no external memory is used, this
template is only used to generate the vPortCPUAcquireMutexIntsDisabledInternal
and vPortCPUReleaseMutexIntsDisabledInternal functions, which use S32C1 to
do an atomic compare & swap. When external memory is used the functions
vPortCPUAcquireMutexIntsDisabledExtram and vPortCPUReleaseMutexIntsDisabledExtram
are also generated, which use uxPortCompareSetExtram to fake the S32C1 instruction.
The wrapper functions vPortCPUAcquireMutexIntsDisabled and
vPortCPUReleaseMutexIntsDisabled will then use the appropriate function to do the
actual lock/unlock.
*/
* implementation of vPortCPUAcquireMutexIntsDisabled and
* vPortCPUReleaseMutexIntsDisabled into the
* vTaskEnterCritical/vTaskExitCritical functions in task.c as well as the
* vPortCPUAcquireMutex/vPortCPUReleaseMutex implementations.
*
* Normally this kind of performance hack is over the top, but
* vTaskEnterCritical/vTaskExitCritical is called a great
* deal by FreeRTOS internals.
*
* It should be #included by freertos port.c or tasks.c, in esp-idf.
*
* The way it works is that it essentially uses portmux_impl.inc.h as a
* generator template of sorts. When no external memory is used, this
* template is only used to generate the vPortCPUAcquireMutexIntsDisabledInternal
* and vPortCPUReleaseMutexIntsDisabledInternal functions, which use S32C1 to
* do an atomic compare & swap. When external memory is used the functions
* vPortCPUAcquireMutexIntsDisabledExtram and vPortCPUReleaseMutexIntsDisabledExtram
* are also generated, which use uxPortCompareSetExtram to fake the S32C1 instruction.
* The wrapper functions vPortCPUAcquireMutexIntsDisabled and
* vPortCPUReleaseMutexIntsDisabled will then use the appropriate function to do the
* actual lock/unlock.
*/
#include "soc/cpu.h"
#include "portable.h"
/* XOR one core ID with this value to get the other core ID */
#define CORE_ID_XOR_SWAP (CORE_ID_PRO ^ CORE_ID_APP)
#define CORE_ID_XOR_SWAP ( CORE_ID_PRO ^ CORE_ID_APP )
//Define the mux routines for use with muxes in internal RAM
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledInternal
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledInternal
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSet
/*Define the mux routines for use with muxes in internal RAM */
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledInternal
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledInternal
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSet
#include "portmux_impl.inc.h"
#undef PORTMUX_AQUIRE_MUX_FN_NAME
#undef PORTMUX_RELEASE_MUX_FN_NAME
#undef PORTMUX_COMPARE_SET_FN_NAME
#if defined(CONFIG_SPIRAM_SUPPORT)
#if defined( CONFIG_SPIRAM_SUPPORT )
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledExtram
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledExtram
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSetExtram
#include "portmux_impl.inc.h"
#undef PORTMUX_AQUIRE_MUX_FN_NAME
#undef PORTMUX_RELEASE_MUX_FN_NAME
#undef PORTMUX_COMPARE_SET_FN_NAME
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledExtram
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledExtram
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSetExtram
#include "portmux_impl.inc.h"
#undef PORTMUX_AQUIRE_MUX_FN_NAME
#undef PORTMUX_RELEASE_MUX_FN_NAME
#undef PORTMUX_COMPARE_SET_FN_NAME
#endif
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE *mux, int timeout_cycles, const char *fnName, int line
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE *mux, const char *fnName, int line
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(x) x, timeout_cycles, fnName, line
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS(x) x, fnName, line
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE * mux, int timeout_cycles, const char * fnName, int line
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE * mux, const char * fnName, int line
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( x ) x, timeout_cycles, fnName, line
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS( x ) x, fnName, line
#else
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE *mux, int timeout_cycles
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE *mux
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(x) x, timeout_cycles
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS(x) x
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE * mux, int timeout_cycles
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE * mux
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( x ) x, timeout_cycles
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS( x ) x
#endif
static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexIntsDisabled(PORTMUX_AQUIRE_MUX_FN_ARGS) {
#if defined(CONFIG_SPIRAM_SUPPORT)
if (esp_ptr_external_ram(mux)) {
return vPortCPUAcquireMutexIntsDisabledExtram(PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(mux));
}
#endif
return vPortCPUAcquireMutexIntsDisabledInternal(PORTMUX_AQUIRE_MUX_FN_CALL_ARGS(mux));
static inline bool __attribute__( ( always_inline ) ) vPortCPUAcquireMutexIntsDisabled( PORTMUX_AQUIRE_MUX_FN_ARGS )
{
#if defined( CONFIG_SPIRAM_SUPPORT )
if( esp_ptr_external_ram( mux ) )
{
return vPortCPUAcquireMutexIntsDisabledExtram( PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( mux ) );
}
#endif
return vPortCPUAcquireMutexIntsDisabledInternal( PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( mux ) );
}
static inline void vPortCPUReleaseMutexIntsDisabled(PORTMUX_RELEASE_MUX_FN_ARGS) {
#if defined(CONFIG_SPIRAM_SUPPORT)
if (esp_ptr_external_ram(mux)) {
vPortCPUReleaseMutexIntsDisabledExtram(PORTMUX_RELEASE_MUX_FN_CALL_ARGS(mux));
return;
}
#endif
vPortCPUReleaseMutexIntsDisabledInternal(PORTMUX_RELEASE_MUX_FN_CALL_ARGS(mux));
static inline void vPortCPUReleaseMutexIntsDisabled( PORTMUX_RELEASE_MUX_FN_ARGS )
{
#if defined( CONFIG_SPIRAM_SUPPORT )
if( esp_ptr_external_ram( mux ) )
{
vPortCPUReleaseMutexIntsDisabledExtram( PORTMUX_RELEASE_MUX_FN_CALL_ARGS( mux ) );
return;
}
#endif
vPortCPUReleaseMutexIntsDisabledInternal( PORTMUX_RELEASE_MUX_FN_CALL_ARGS( mux ) );
}

View file

@ -1,169 +1,200 @@
/*
Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
Copyright (C) 2015 Real Time Engineers Ltd.
All rights reserved
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
*/
* Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
* Copyright (C) 2015 Real Time Engineers Ltd.
*
* All rights reserved
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
***************************************************************************
* >>! NOTE: The modification to the GPL is included to allow you to !<<
* >>! distribute a combined work that includes FreeRTOS without being !<<
* >>! obliged to provide the source code for proprietary components !<<
* >>! outside of the FreeRTOS kernel. !<<
***************************************************************************
*
* FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. Full license text is available on the following
* link: http://www.freertos.org/a00114.html
*/
/*
Warning: funky preprocessor hackery ahead. Including these headers will generate two
functions, which names are defined by the preprocessor macros
PORTMUX_AQUIRE_MUX_FN_NAME and PORTMUX_RELEASE_MUX_FN_NAME. In order to do the compare
and exchange function, they will use whatever PORTMUX_COMPARE_SET_FN_NAME resolves to.
In some scenarios, this header is included *twice* in portmux_impl.h: one time
for the 'normal' mux code which uses a compare&exchange routine, another time
to generate code for a second set of these routines that use a second mux
(in internal ram) to fake a compare&exchange on a variable in external memory.
*/
* Warning: funky preprocessor hackery ahead. Including these headers will generate two
* functions, which names are defined by the preprocessor macros
* PORTMUX_AQUIRE_MUX_FN_NAME and PORTMUX_RELEASE_MUX_FN_NAME. In order to do the compare
* and exchange function, they will use whatever PORTMUX_COMPARE_SET_FN_NAME resolves to.
*
* In some scenarios, this header is included *twice* in portmux_impl.h: one time
* for the 'normal' mux code which uses a compare&exchange routine, another time
* to generate code for a second set of these routines that use a second mux
* (in internal ram) to fake a compare&exchange on a variable in external memory.
*/
static inline bool __attribute__((always_inline))
static inline bool __attribute__( ( always_inline ) )
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
PORTMUX_AQUIRE_MUX_FN_NAME(portMUX_TYPE *mux, int timeout_cycles, const char *fnName, int line) {
PORTMUX_AQUIRE_MUX_FN_NAME( portMUX_TYPE * mux,
int timeout_cycles,
const char * fnName,
int line )
{
#else
PORTMUX_AQUIRE_MUX_FN_NAME(portMUX_TYPE *mux, int timeout_cycles) {
#endif
PORTMUX_AQUIRE_MUX_FN_NAME( portMUX_TYPE * mux, int timeout_cycles )
{
#endif
#if !CONFIG_FREERTOS_UNICORE
uint32_t res;
portBASE_TYPE coreID, otherCoreID;
uint32_t ccount_start;
bool set_timeout = timeout_cycles > portMUX_NO_TIMEOUT;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if (!set_timeout) {
timeout_cycles = 10000; // Always set a timeout in debug mode
set_timeout = true;
}
#endif
if (set_timeout) { // Timeout
RSR(CCOUNT, ccount_start);
}
#if !CONFIG_FREERTOS_UNICORE
uint32_t res;
portBASE_TYPE coreID, otherCoreID;
uint32_t ccount_start;
bool set_timeout = timeout_cycles > portMUX_NO_TIMEOUT;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if( !set_timeout )
{
timeout_cycles = 10000; /* Always set a timeout in debug mode */
set_timeout = true;
}
#endif
if( set_timeout ) /* Timeout */
{
RSR( CCOUNT, ccount_start );
}
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
uint32_t owner = mux->owner;
if( ( owner != portMUX_FREE_VAL ) && ( owner != CORE_ID_PRO ) && ( owner != CORE_ID_APP ) )
{
ets_printf( "ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line );
mux->owner = portMUX_FREE_VAL;
}
#endif
/* Spin until we own the core */
RSR( PRID, coreID );
/* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP),
* not the 0/1 value returned by xPortGetCoreID()
*/
otherCoreID = CORE_ID_XOR_SWAP ^ coreID;
do
{
/* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO,
* CORE_ID_APP:
*
* - If portMUX_FREE_VAL, we want to atomically set to 'coreID'.
* - If "our" coreID, we can drop through immediately.
* - If "otherCoreID", we spin here.
*/
res = coreID;
PORTMUX_COMPARE_SET_FN_NAME( &mux->owner, portMUX_FREE_VAL, &res );
if( res != otherCoreID )
{
break; /* mux->owner is "our" coreID */
}
if( set_timeout )
{
uint32_t ccount_now;
RSR( CCOUNT, ccount_now );
if( ccount_now - ccount_start > ( unsigned ) timeout_cycles )
{
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
ets_printf( "Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line );
ets_printf( "Owner 0x%x count %d\n", mux->owner, mux->count );
#endif
return false;
}
}
} while( 1 );
assert( res == coreID || res == portMUX_FREE_VAL ); /* any other value implies memory corruption or uninitialized mux */
assert( ( res == portMUX_FREE_VAL ) == ( mux->count == 0 ) ); /* we're first to lock iff count is zero */
assert( mux->count < 0xFF ); /* Bad count value implies memory corruption */
/* now we own it, we can increment the refcount */
mux->count++;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if( res == portMUX_FREE_VAL ) /*initial lock */
{
mux->lastLockedFn = fnName;
mux->lastLockedLine = line;
}
else
{
ets_printf( "Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count - 1,
mux->lastLockedFn, mux->lastLockedLine, fnName, line );
}
#endif /* CONFIG_FREERTOS_PORTMUX_DEBUG */
#endif /* CONFIG_FREERTOS_UNICORE */
return true;
}
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
uint32_t owner = mux->owner;
if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) {
ets_printf("ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line);
mux->owner=portMUX_FREE_VAL;
}
#endif
/* Spin until we own the core */
RSR(PRID, coreID);
/* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP),
not the 0/1 value returned by xPortGetCoreID()
*/
otherCoreID = CORE_ID_XOR_SWAP ^ coreID;
do {
/* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO,
CORE_ID_APP:
- If portMUX_FREE_VAL, we want to atomically set to 'coreID'.
- If "our" coreID, we can drop through immediately.
- If "otherCoreID", we spin here.
*/
res = coreID;
PORTMUX_COMPARE_SET_FN_NAME(&mux->owner, portMUX_FREE_VAL, &res);
if (res != otherCoreID) {
break; // mux->owner is "our" coreID
}
if (set_timeout) {
uint32_t ccount_now;
RSR(CCOUNT, ccount_now);
if (ccount_now - ccount_start > (unsigned)timeout_cycles) {
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
ets_printf("Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line);
ets_printf("Owner 0x%x count %d\n", mux->owner, mux->count);
#endif
return false;
}
}
} while (1);
assert(res == coreID || res == portMUX_FREE_VAL); /* any other value implies memory corruption or uninitialized mux */
assert((res == portMUX_FREE_VAL) == (mux->count == 0)); /* we're first to lock iff count is zero */
assert(mux->count < 0xFF); /* Bad count value implies memory corruption */
/* now we own it, we can increment the refcount */
mux->count++;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if (res==portMUX_FREE_VAL) { //initial lock
mux->lastLockedFn=fnName;
mux->lastLockedLine=line;
} else {
ets_printf("Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count-1,
mux->lastLockedFn, mux->lastLockedLine, fnName, line);
}
#endif /* CONFIG_FREERTOS_PORTMUX_DEBUG */
#endif /* CONFIG_FREERTOS_UNICORE */
return true;
}
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
static inline void PORTMUX_RELEASE_MUX_FN_NAME(portMUX_TYPE *mux, const char *fnName, int line) {
static inline void PORTMUX_RELEASE_MUX_FN_NAME( portMUX_TYPE * mux,
const char * fnName,
int line )
{
#else
static inline void PORTMUX_RELEASE_MUX_FN_NAME(portMUX_TYPE *mux) {
#endif
static inline void PORTMUX_RELEASE_MUX_FN_NAME( portMUX_TYPE * mux )
{
#endif
#if !CONFIG_FREERTOS_UNICORE
portBASE_TYPE coreID;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char *lastLockedFn=mux->lastLockedFn;
int lastLockedLine=mux->lastLockedLine;
mux->lastLockedFn=fnName;
mux->lastLockedLine=line;
uint32_t owner = mux->owner;
if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) {
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner);
}
#endif
#if !CONFIG_FREERTOS_UNICORE
portBASE_TYPE coreID;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char * lastLockedFn = mux->lastLockedFn;
int lastLockedLine = mux->lastLockedLine;
mux->lastLockedFn = fnName;
mux->lastLockedLine = line;
uint32_t owner = mux->owner;
#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined(NDEBUG)
RSR(PRID, coreID);
#endif
if( ( owner != portMUX_FREE_VAL ) && ( owner != CORE_ID_PRO ) && ( owner != CORE_ID_APP ) )
{
ets_printf( "ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner );
}
#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if (coreID != mux->owner) {
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux);
ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line);
}
#endif
#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined( NDEBUG )
RSR( PRID, coreID );
#endif
assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if( coreID != mux->owner )
{
ets_printf( "ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux );
ets_printf( "Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line );
}
#endif
mux->count--;
if(mux->count == 0) {
mux->owner = portMUX_FREE_VAL;
} else {
assert(mux->count < 0x100); // Indicates memory corruption
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line);
#endif
}
#endif //!CONFIG_FREERTOS_UNICORE
}
assert( coreID == mux->owner ); /* This is a mutex we didn't lock, or it's corrupt */
mux->count--;
if( mux->count == 0 )
{
mux->owner = portMUX_FREE_VAL;
}
else
{
assert( mux->count < 0x100 ); /* Indicates memory corruption */
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
ets_printf( "Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line );
#endif
}
#endif //!CONFIG_FREERTOS_UNICORE
}

View file

@ -1,36 +1,36 @@
/*******************************************************************************
// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
XTENSA INITIALIZATION ROUTINES CODED IN C
This file contains miscellaneous Xtensa RTOS-generic initialization functions
that are implemented in C.
* // Copyright (c) 2003-2015 Cadence Design Systems, Inc.
* //
* // Permission is hereby granted, free of charge, to any person obtaining
* // a copy of this software and associated documentation files (the
* // "Software"), to deal in the Software without restriction, including
* // without limitation the rights to use, copy, modify, merge, publish,
* // distribute, sublicense, and/or sell copies of the Software, and to
* // permit persons to whom the Software is furnished to do so, subject to
* // the following conditions:
* //
* // The above copyright notice and this permission notice shall be included
* // in all copies or substantial portions of the Software.
* //
* // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* --------------------------------------------------------------------------------
*
* XTENSA INITIALIZATION ROUTINES CODED IN C
*
* This file contains miscellaneous Xtensa RTOS-generic initialization functions
* that are implemented in C.
*
*******************************************************************************/
#ifdef XT_BOARD
#include <xtensa/xtbsp.h>
#include <xtensa/xtbsp.h>
#endif
#include "xtensa_rtos.h"
@ -38,18 +38,17 @@ that are implemented in C.
#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 */
void _xt_tick_divisor_init(void)
{
_xt_tick_divisor = esp_clk_cpu_freq() / XT_TICK_PER_SEC;
}
void _xt_tick_divisor_init( void )
{
_xt_tick_divisor = esp_clk_cpu_freq() / XT_TICK_PER_SEC;
}
/* Deprecated, to be removed */
int xt_clock_freq(void)
{
return esp_clk_cpu_freq();
}
int xt_clock_freq( void )
{
return esp_clk_cpu_freq();
}
#endif /* XT_RTOS_TIMER_INT */

View file

@ -1,29 +1,29 @@
/*******************************************************************************
Copyright (c) 2006-2015 Cadence Design Systems Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
* Copyright (c) 2006-2015 Cadence Design Systems Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
/******************************************************************************
Xtensa-specific interrupt and exception functions for RTOS ports.
Also see xtensa_intr_asm.S.
* Xtensa-specific interrupt and exception functions for RTOS ports.
* Also see xtensa_intr_asm.S.
******************************************************************************/
#include <stdlib.h>
@ -40,119 +40,135 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Handler table is in xtensa_intr_asm.S */
extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM*portNUM_PROCESSORS];
extern xt_exc_handler _xt_exception_table[ XCHAL_EXCCAUSE_NUM * portNUM_PROCESSORS ];
/*
Default handler for unhandled exceptions.
CHANGED: We do this in panic.c now
*/
* Default handler for unhandled exceptions.
* CHANGED: We do this in panic.c now
*/
//void xt_unhandled_exception(XtExcFrame *frame)
//{
//exit(-1);
//}
extern void xt_unhandled_exception(XtExcFrame *frame);
/*void xt_unhandled_exception(XtExcFrame *frame) */
/*{ */
/*exit(-1); */
/*} */
extern void xt_unhandled_exception( XtExcFrame * frame );
/*
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 old;
* 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 old;
if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
return 0; /* invalid exception number */
if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) )
{
return 0; /* invalid exception number */
}
/* Convert exception number to _xt_exception_table name */
n = n * portNUM_PROCESSORS + xPortGetCoreID();
old = _xt_exception_table[n];
/* Convert exception number to _xt_exception_table name */
n = n * portNUM_PROCESSORS + xPortGetCoreID();
old = _xt_exception_table[ n ];
if (f) {
_xt_exception_table[n] = f;
}
else {
_xt_exception_table[n] = &xt_unhandled_exception;
if( f )
{
_xt_exception_table[ n ] = f;
}
else
{
_xt_exception_table[ n ] = &xt_unhandled_exception;
}
return( ( old == &xt_unhandled_exception ) ? 0 : old );
}
return ((old == &xt_unhandled_exception) ? 0 : old);
}
#endif
#endif /* if XCHAL_HAVE_EXCEPTIONS */
#if XCHAL_HAVE_INTERRUPTS
/* Handler table is in xtensa_intr_asm.S */
typedef struct xt_handler_table_entry {
void * handler;
void * arg;
} xt_handler_table_entry;
typedef struct xt_handler_table_entry
{
void * handler;
void * arg;
} xt_handler_table_entry;
extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS*portNUM_PROCESSORS];
extern xt_handler_table_entry _xt_interrupt_table[ XCHAL_NUM_INTERRUPTS * portNUM_PROCESSORS ];
/*
Default handler for unhandled interrupts.
*/
void xt_unhandled_interrupt(void * arg)
{
ets_printf("Unhandled interrupt %d on cpu %d!\n", (int)arg, xPortGetCoreID());
}
* Default handler for unhandled interrupts.
*/
void xt_unhandled_interrupt( void * arg )
{
ets_printf( "Unhandled interrupt %d on cpu %d!\n", ( int ) arg, xPortGetCoreID() );
}
/*
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_table_entry * entry;
xt_handler old;
* 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_table_entry * entry;
xt_handler old;
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 */
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
{
return 0; /* invalid interrupt number */
}
/* Convert exception number to _xt_exception_table name */
n = n * portNUM_PROCESSORS + xPortGetCoreID();
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;
/* Convert exception number to _xt_exception_table name */
n = n * portNUM_PROCESSORS + xPortGetCoreID();
if (f) {
entry->handler = f;
entry->arg = arg;
}
else {
entry->handler = &xt_unhandled_interrupt;
entry->arg = (void*)n;
entry = _xt_interrupt_table + n;
old = entry->handler;
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);
}
#if CONFIG_SYSVIEW_ENABLE
void * xt_get_interrupt_handler_arg( int n )
{
xt_handler_table_entry * entry;
#if CONFIG_SYSVIEW_ENABLE
void * xt_get_interrupt_handler_arg(int n)
{
xt_handler_table_entry * entry;
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
{
return 0; /* invalid interrupt number */
}
if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
return 0; /* invalid interrupt number */
/* Convert exception number to _xt_exception_table name */
n = n * portNUM_PROCESSORS + xPortGetCoreID();
/* Convert exception number to _xt_exception_table name */
n = n * portNUM_PROCESSORS + xPortGetCoreID();
entry = _xt_interrupt_table + n;
return entry->arg;
}
#endif
entry = _xt_interrupt_table + n;
return entry->arg;
}
#endif /* if CONFIG_SYSVIEW_ENABLE */
#endif /* XCHAL_HAVE_INTERRUPTS */

View file

@ -1,25 +1,25 @@
// xtensa_overlay_os_hook.c -- Overlay manager OS hooks for FreeRTOS.
/* xtensa_overlay_os_hook.c -- Overlay manager OS hooks for FreeRTOS. */
// Copyright (c) 2015-2015 Cadence Design Systems Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Copyright (c) 2015-2015 Cadence Design Systems Inc. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be included */
/* in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "FreeRTOS.h"
@ -30,7 +30,7 @@
/* Mutex object that controls access to the overlay. Currently only one
* 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
@ -38,30 +38,30 @@ static SemaphoreHandle_t xt_overlay_mutex;
* Typically this mutex would be set up with priority inheritance. See
* overlay manager documentation for more details.
*/
void xt_overlay_init_os(void)
{
/* Create the mutex for overlay access. Priority inheritance is
* required.
*/
xt_overlay_mutex = xSemaphoreCreateMutex();
}
void xt_overlay_init_os( void )
{
/* Create the mutex for overlay access. Priority inheritance is
* required.
*/
xt_overlay_mutex = xSemaphoreCreateMutex();
}
/* This function locks access to shared overlay resources, typically
* by acquiring a mutex.
*/
void xt_overlay_lock(void)
{
xSemaphoreTake(xt_overlay_mutex, 0);
}
void xt_overlay_lock( void )
{
xSemaphoreTake( xt_overlay_mutex, 0 );
}
/* This function releases access to shared overlay resources, typically
* by unlocking a mutex.
*/
void xt_overlay_unlock(void)
{
xSemaphoreGive(xt_overlay_mutex);
}
void xt_overlay_unlock( void )
{
xSemaphoreGive( xt_overlay_mutex );
}
#endif
#endif /* if configUSE_MUTEX */

View file

@ -1,4 +1,3 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -59,146 +58,155 @@
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);
extern void _frxt_tick_timer_init( void );
/* 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
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
void _xt_user_exit(void);
/* 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, *tp;
XtExcFrame *frame;
#if XCHAL_CP_NUM > 0
uint32_t *p;
#endif
StackType_t * sp, * tp;
XtExcFrame * frame;
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = (StackType_t *) (((UBaseType_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
#if XCHAL_CP_NUM > 0
uint32_t * p;
#endif
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for (tp = sp; tp <= pxTopOfStack; ++tp)
*tp = 0;
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = ( StackType_t * ) ( ( ( UBaseType_t ) ( pxTopOfStack + 1 ) - XT_CP_SIZE - XT_STK_FRMSZ ) & ~0xf );
frame = (XtExcFrame *) sp;
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for( tp = sp; tp <= pxTopOfStack; ++tp )
{
*tp = 0;
}
/* Explicitly initialize certain saved registers */
frame->pc = (UBaseType_t) pxCode; /* task entrypoint */
frame->a0 = 0; /* to terminate GDB backtrace */
frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */
frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */
frame = ( XtExcFrame * ) sp;
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
/* Also set entry point argument parameter. */
#ifdef __XTENSA_CALL0_ABI__
frame->a2 = (UBaseType_t) pvParameters;
frame->ps = PS_UM | PS_EXCM;
#else
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
frame->a6 = (UBaseType_t) pvParameters;
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
#endif
/* Explicitly initialize certain saved registers */
frame->pc = ( UBaseType_t ) pxCode; /* task entrypoint */
frame->a0 = 0; /* to terminate GDB backtrace */
frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ; /* physical top of stack frame */
frame->exit = ( UBaseType_t ) _xt_user_exit; /* user exception exit dispatcher */
#ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */
frame->vpri = 0xFFFFFFFF;
#endif
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
/* Also set entry point argument parameter. */
#ifdef __XTENSA_CALL0_ABI__
frame->a2 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM;
#else
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
frame->a6 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );
#endif
#if XCHAL_CP_NUM > 0
/* Init the coprocessor save area (see xtensa_context.h) */
/* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
#ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */
frame->vpri = 0xFFFFFFFF;
#endif
#if XCHAL_CP_NUM > 0
/* Init the coprocessor save area (see xtensa_context.h) */
/* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
* //p = (uint32_t *) xMPUSettings->coproc_area;
*/
p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf);
p[0] = 0;
p[1] = 0;
p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN;
#endif
*/
p = ( uint32_t * ) ( ( ( uint32_t ) pxTopOfStack - XT_CP_SIZE ) & ~0xf );
p[ 0 ] = 0;
p[ 1 ] = 0;
p[ 2 ] = ( ( ( uint32_t ) p ) + 12 + XCHAL_TOTAL_SA_ALIGN - 1 ) & -XCHAL_TOTAL_SA_ALIGN;
#endif
return sp;
return sp;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* It is unlikely that the Xtensa port will get stopped. If required simply
disable the tick interrupt here. */
/* It is unlikely that the Xtensa port will get stopped. If required simply
* 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. */
_xt_coproc_init();
#endif
#if XCHAL_CP_NUM > 0
/* Initialize co-processor management for tasks. Leave CPENABLE alone. */
_xt_coproc_init();
#endif
/* Init the tick divisor value */
_xt_tick_divisor_init();
/* Init the tick divisor value */
_xt_tick_divisor_init();
/* Setup the hardware to generate the tick. */
_frxt_tick_timer_init();
/* Setup the hardware to generate the tick. */
_frxt_tick_timer_init();
#if XT_USE_THREAD_SAFE_CLIB
// Init C library
vPortClibInit();
#endif
#if XT_USE_THREAD_SAFE_CLIB
/* Init C library */
vPortClibInit();
#endif
port_xSchedulerRunning = 1;
port_xSchedulerRunning = 1;
// Cannot be directly called from C; never returns
__asm__ volatile ("call0 _frxt_dispatch\n");
/* Cannot be directly called from C; never returns */
__asm__ volatile ( "call0 _frxt_dispatch\n" );
/* Should not get here. */
return pdTRUE;
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
BaseType_t xPortSysTickHandler( void )
{
BaseType_t ret;
uint32_t interruptMask;
BaseType_t ret;
uint32_t interruptMask;
portbenchmarkIntLatency();
portbenchmarkIntLatency();
/* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be
* disabled before calling xTaskIncrementTick as it access the
* kernel lists. */
interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
ret = xTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );
/* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be
* disabled before calling xTaskIncrementTick as it access the
* kernel lists. */
interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
ret = xTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );
portYIELD_FROM_ISR( ret );
portYIELD_FROM_ISR( ret );
return ret;
return ret;
}
/*-----------------------------------------------------------*/
@ -206,16 +214,18 @@ BaseType_t xPortSysTickHandler( void )
* Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
*/
#if portUSING_MPU_WRAPPERS
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
{
#if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = (StackType_t*)((((uint32_t)(pxBottomOfStack + ulStackDepth - 1)) - XT_CP_SIZE ) & ~0xf);
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth )
{
#if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( ( uint32_t ) ( pxBottomOfStack + ulStackDepth - 1 ) ) - XT_CP_SIZE ) & ~0xf );
/* 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().
*/
#endif
}
#endif
/* 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().
*/
#endif
}
#endif /* if portUSING_MPU_WRAPPERS */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -37,7 +36,7 @@
#endif
#define portbenchmarkINTERRUPT_DISABLE()
#define portbenchmarkINTERRUPT_RESTORE(newstate)
#define portbenchmarkINTERRUPT_RESTORE( newstate )
#define portbenchmarkIntLatency()
#define portbenchmarkIntWait()
#define portbenchmarkReset()

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -26,200 +25,204 @@
#if XT_USE_THREAD_SAFE_CLIB
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
#include <errno.h>
#include <sys/reent.h>
#include <errno.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.
//-----------------------------------------------------------------------------
int32_t _xclib_use_mt = 1;
/*----------------------------------------------------------------------------- */
/* Override this and set to nonzero to enable locking. */
/*----------------------------------------------------------------------------- */
int32_t _xclib_use_mt = 1;
//-----------------------------------------------------------------------------
// Init lock.
//-----------------------------------------------------------------------------
void
_Mtxinit(_Rmtx * mtx)
{
*mtx = xSemaphoreCreateRecursiveMutex();
}
/*----------------------------------------------------------------------------- */
/* Init lock. */
/*----------------------------------------------------------------------------- */
void _Mtxinit( _Rmtx * mtx )
{
*mtx = xSemaphoreCreateRecursiveMutex();
}
//-----------------------------------------------------------------------------
// Destroy lock.
//-----------------------------------------------------------------------------
void
_Mtxdst(_Rmtx * mtx)
{
if ((mtx != NULL) && (*mtx != NULL)) {
vSemaphoreDelete(*mtx);
}
}
/*----------------------------------------------------------------------------- */
/* Destroy lock. */
/*----------------------------------------------------------------------------- */
void _Mtxdst( _Rmtx * mtx )
{
if( ( mtx != NULL ) && ( *mtx != NULL ) )
{
vSemaphoreDelete( *mtx );
}
}
//-----------------------------------------------------------------------------
// Lock.
//-----------------------------------------------------------------------------
void
_Mtxlock(_Rmtx * mtx)
{
if ((mtx != NULL) && (*mtx != NULL)) {
xSemaphoreTakeRecursive(*mtx, portMAX_DELAY);
}
}
/*----------------------------------------------------------------------------- */
/* Lock. */
/*----------------------------------------------------------------------------- */
void _Mtxlock( _Rmtx * mtx )
{
if( ( mtx != NULL ) && ( *mtx != NULL ) )
{
xSemaphoreTakeRecursive( *mtx, portMAX_DELAY );
}
}
//-----------------------------------------------------------------------------
// Unlock.
//-----------------------------------------------------------------------------
void
_Mtxunlock(_Rmtx * mtx)
{
if ((mtx != NULL) && (*mtx != NULL)) {
xSemaphoreGiveRecursive(*mtx);
}
}
/*----------------------------------------------------------------------------- */
/* 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)
{
extern char _end;
extern char _heap_sentry;
static char * _heap_sentry_ptr = &_heap_sentry;
static char * heap_ptr;
char * base;
/*----------------------------------------------------------------------------- */
/* 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;
static char * _heap_sentry_ptr = &_heap_sentry;
static char * heap_ptr;
char * base;
if (!heap_ptr)
heap_ptr = (char *) &_end;
if( !heap_ptr )
{
heap_ptr = ( char * ) &_end;
}
base = heap_ptr;
if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
return (char *) -1;
}
base = heap_ptr;
heap_ptr += incr;
return base;
}
if( heap_ptr + incr >= _heap_sentry_ptr )
{
reent->_errno = ENOMEM;
return ( char * ) -1;
}
//-----------------------------------------------------------------------------
// Global initialization for C library.
//-----------------------------------------------------------------------------
void
vPortClibInit(void)
{
}
heap_ptr += incr;
return base;
}
//-----------------------------------------------------------------------------
// Per-thread cleanup stub provided for linking, does nothing.
//-----------------------------------------------------------------------------
void
_reclaim_reent(void * ptr)
{
}
/*----------------------------------------------------------------------------- */
/* Global initialization for C library. */
/*----------------------------------------------------------------------------- */
void vPortClibInit( void )
{
}
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
/*----------------------------------------------------------------------------- */
/* Per-thread cleanup stub provided for linking, does nothing. */
/*----------------------------------------------------------------------------- */
void _reclaim_reent( void * ptr )
{
}
#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#include "semphr.h"
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static SemaphoreHandle_t xClibMutex;
static uint32_t ulClibInitDone = 0;
#include "semphr.h"
//-----------------------------------------------------------------------------
// Get C library lock.
//-----------------------------------------------------------------------------
void
__malloc_lock(struct _reent * ptr)
{
if (!ulClibInitDone)
return;
static SemaphoreHandle_t xClibMutex;
static uint32_t ulClibInitDone = 0;
xSemaphoreTakeRecursive(xClibMutex, portMAX_DELAY);
}
/*----------------------------------------------------------------------------- */
/* Get C library lock. */
/*----------------------------------------------------------------------------- */
void __malloc_lock( struct _reent * ptr )
{
if( !ulClibInitDone )
{
return;
}
//-----------------------------------------------------------------------------
// Release C library lock.
//-----------------------------------------------------------------------------
void
__malloc_unlock(struct _reent * ptr)
{
if (!ulClibInitDone)
return;
xSemaphoreTakeRecursive( xClibMutex, portMAX_DELAY );
}
xSemaphoreGiveRecursive(xClibMutex);
}
/*----------------------------------------------------------------------------- */
/* Release C library lock. */
/*----------------------------------------------------------------------------- */
void __malloc_unlock( struct _reent * ptr )
{
if( !ulClibInitDone )
{
return;
}
//-----------------------------------------------------------------------------
// 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);
}
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 )
{
__malloc_lock( ptr );
}
//-----------------------------------------------------------------------------
// Unlock environment.
//-----------------------------------------------------------------------------
void
__env_unlock(struct _reent * ptr)
{
__malloc_unlock(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)
{
extern char _end;
extern char _heap_sentry;
static char * _heap_sentry_ptr = &_heap_sentry;
static char * heap_ptr;
char * base;
/*----------------------------------------------------------------------------- */
/* 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;
static char * _heap_sentry_ptr = &_heap_sentry;
static char * heap_ptr;
char * base;
if (!heap_ptr)
heap_ptr = (char *) &_end;
if( !heap_ptr )
{
heap_ptr = ( char * ) &_end;
}
base = heap_ptr;
if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
return (char *) -1;
}
base = heap_ptr;
heap_ptr += incr;
return base;
}
if( heap_ptr + incr >= _heap_sentry_ptr )
{
reent->_errno = ENOMEM;
return ( char * ) -1;
}
//-----------------------------------------------------------------------------
// Global initialization for C library.
//-----------------------------------------------------------------------------
void
vPortClibInit(void)
{
configASSERT(!ulClibInitDone);
heap_ptr += incr;
return base;
}
xClibMutex = xSemaphoreCreateRecursiveMutex();
ulClibInitDone = 1;
}
/*----------------------------------------------------------------------------- */
/* Global initialization for C library. */
/*----------------------------------------------------------------------------- */
void vPortClibInit( void )
{
configASSERT( !ulClibInitDone );
#endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
xClibMutex = xSemaphoreCreateRecursiveMutex();
ulClibInitDone = 1;
}
#endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
#endif /* XT_USE_THREAD_SAFE_CLIB */

View file

@ -1,4 +1,3 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -50,23 +49,23 @@
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __ASSEMBLER__
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <stdint.h>
#include <xtensa/tie/xt_core.h>
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h>
#include <xtensa/tie/xt_core.h>
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/xtruntime.h>
//#include "xtensa_context.h"
/*#include "xtensa_context.h" */
/*-----------------------------------------------------------
* Port specific definitions.
@ -80,156 +79,165 @@ extern "C" {
/* Type definitions. */
#define portCHAR int8_t
#define portFLOAT float
#define portDOUBLE double
#define portLONG int32_t
#define portSHORT int16_t
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE int
#define portCHAR int8_t
#define portFLOAT float
#define portDOUBLE double
#define portLONG int32_t
#define portSHORT int16_t
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE int
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned portBASE_TYPE UBaseType_t;
typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned portBASE_TYPE UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
#if ( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
/*-----------------------------------------------------------*/
// portbenchmark
#include "portbenchmark.h"
/* 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.
#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 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
void vTaskEnterCritical(void);
void vTaskExitCritical(void);
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()
/* 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; }
#define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0)
/* 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 );
// 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)
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 */
#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( state ) portEXIT_CRITICAL_NESTED( state )
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4
#define portNOP() XT_NOP()
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4
#define portNOP() XT_NOP()
/*-----------------------------------------------------------*/
/* Fine resolution time */
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
/* Kernel utilities. */
void vPortYield( void );
void _frxt_setup_switch( void );
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) \
if ( ( xHigherPriorityTaskWoken ) != 0 ) { \
_frxt_setup_switch(); \
}
void vPortYield( void );
void _frxt_setup_switch( void );
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) \
if( ( xHigherPriorityTaskWoken ) != 0 ) { \
_frxt_setup_switch(); \
}
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( 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 )
// 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
#endif
/* 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 */
#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 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;
#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
/* 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
/* 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
/* 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. */
/* 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);
#if ( XT_USE_THREAD_SAFE_CLIB > 0u ) && ( XSHAL_CLIB == XTHAL_CLIB_XCLIB )
extern void vPortClibInit( void );
// No cleanup necessary at this time.
#define portCLEAN_UP_TCB(pxTCB)
#endif // XCLIB support
/* No cleanup necessary at this time. */
#define portCLEAN_UP_TCB( pxTCB )
#endif // XCLIB support
#if (XT_USE_THREAD_SAFE_CLIB > 0u) && (XSHAL_CLIB == XTHAL_CLIB_NEWLIB)
extern void vPortClibInit(void);
#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
#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) {
fp->_close = NULL;
}
}
#endif // NEWLIB support
/* 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;
#endif // __ASSEMBLER__
for( i = 0; i < 3; ++i, ++fp )
{
fp->_close = NULL;
}
}
#endif // NEWLIB support
#ifdef __cplusplus
}
#endif
#endif // __ASSEMBLER__
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -26,7 +25,7 @@
* This utility helps tracing the entering and exiting from tasks.
* It maintains a circular buffer of tasks in the order they execute,
* and their execution time. To enable it, set configUSE_TRACE_FACILITY_2
* to 1 in FreeRTOSConfig.h. You will also need to download the
* to 1 in FreeRTOSConfig.h. You will also need to download the
* FreeRTOS_trace patch that contains porttrace.c and the complete version
* of porttrace.h.
*/
@ -38,7 +37,7 @@
#error "You need to download the FreeRTOS_trace patch that overwrites this file"
#endif
#define porttracePrint(nelements)
#define porttraceStamp(stamp, count_incr)
#define porttracePrint( nelements )
#define porttraceStamp( stamp, count_incr )
#endif /* PORTTRACE_H */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -35,89 +34,91 @@
/* 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 void (*xt_exc_handler)(XtExcFrame *);
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.
-------------------------------------------------------------------------------
*/
extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f);
* -------------------------------------------------------------------------------
* 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 );
/*
-------------------------------------------------------------------------------
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);
* -------------------------------------------------------------------------------
* 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 );
/*
-------------------------------------------------------------------------------
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 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.
-------------------------------------------------------------------------------
*/
extern unsigned int xt_ints_off(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.
* -------------------------------------------------------------------------------
*/
extern unsigned int xt_ints_off( unsigned int mask );
/*
-------------------------------------------------------------------------------
Call this function to set the specified (s/w) interrupt.
-------------------------------------------------------------------------------
*/
static inline void xt_set_intset(unsigned int arg)
* -------------------------------------------------------------------------------
* Call this function to set the specified (s/w) interrupt.
* -------------------------------------------------------------------------------
*/
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)
interrupt.
-------------------------------------------------------------------------------
*/
static inline void xt_set_intclear(unsigned int arg)
* -------------------------------------------------------------------------------
* Call this function to clear the specified (s/w or edge-triggered)
* interrupt.
* -------------------------------------------------------------------------------
*/
static inline void xt_set_intclear( unsigned int arg )
{
xthal_set_intclear(arg);
xthal_set_intclear( arg );
}
#endif /* __XTENSA_API_H__ */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -32,17 +31,17 @@
*/
#ifndef XTENSA_CONFIG_H
#define XTENSA_CONFIG_H
#define XTENSA_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#include <xtensa/config/system.h> /* required for XSHAL_CLIB */
#include "xtensa_context.h"
#include "xtensa_context.h"
/*-----------------------------------------------------------------------------
@ -60,26 +59,26 @@ extern "C" {
* If this is not true, i.e. one or more interrupt handlers make deep calls then
* 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.
*
* 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.
*
*
* 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.
*
* Usage:
*
*
* 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
* space to be allocated for tasks that use the C library
* reentrant functions. See below for more information.
*
*
* 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
* was chosen for your system.
*
*
* 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
* task. In case you want to use stacks smaller than this
@ -92,92 +91,91 @@ extern "C" {
*
* 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
#ifdef __XTENSA_CALL0_ABI__
#define STK_INTEXC_EXTRA 0x200
#else
#define STK_INTEXC_EXTRA 0x180
#endif
#else
#define STK_INTEXC_EXTRA 0
#endif
#ifdef XT_INTEXC_HOOKS
#ifdef __XTENSA_CALL0_ABI__
#define STK_INTEXC_EXTRA 0x200
#else
#define STK_INTEXC_EXTRA 0x180
#endif
#else
#define STK_INTEXC_EXTRA 0
#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. */
#if (XSHAL_CLIB == XTHAL_CLIB_NEWLIB) || (XSHAL_CLIB == XTHAL_CLIB_XCLIB)
#ifndef XT_USE_THREAD_SAFE_CLIB
#define XT_USE_THREAD_SAFE_CLIB 1
#endif
#else
#define XT_USE_THREAD_SAFE_CLIB 0
#endif
#if XT_USE_THREAD_SAFE_CLIB > 0u
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
#define XT_HAVE_THREAD_SAFE_CLIB 1
#if !defined __ASSEMBLER__
#include <sys/reent.h>
#define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16))
#define XT_CLIB_GLOBAL_PTR _reent_ptr
#define _REENT_INIT_PTR _init_reent
#define _impure_ptr _reent_ptr
void _reclaim_reent(void * ptr);
* 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
#endif
#else
#define XT_USE_THREAD_SAFE_CLIB 0
#endif
#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#define XT_HAVE_THREAD_SAFE_CLIB 1
#if !defined __ASSEMBLER__
#include <sys/reent.h>
#define XT_CLIB_CONTEXT_AREA_SIZE ((sizeof(struct _reent) + 15) + (-16))
#define XT_CLIB_GLOBAL_PTR _impure_ptr
#endif
#else
#define XT_HAVE_THREAD_SAFE_CLIB 0
#error The selected C runtime library is not thread safe.
#endif
#else
#define XT_CLIB_CONTEXT_AREA_SIZE 0
#endif
#if XT_USE_THREAD_SAFE_CLIB > 0u
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
#define XT_HAVE_THREAD_SAFE_CLIB 1
#if !defined __ASSEMBLER__
#include <sys/reent.h>
#define XT_CLIB_CONTEXT_AREA_SIZE ( ( sizeof( struct _reent ) + 15 ) + ( -16 ) )
#define XT_CLIB_GLOBAL_PTR _reent_ptr
#define _REENT_INIT_PTR _init_reent
#define _impure_ptr _reent_ptr
void _reclaim_reent( void * ptr );
#endif
#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#define XT_HAVE_THREAD_SAFE_CLIB 1
#if !defined __ASSEMBLER__
#include <sys/reent.h>
#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 */
#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 */
#define XT_CLIB_CONTEXT_AREA_SIZE 0
#endif /* if XT_USE_THREAD_SAFE_CLIB > 0u */
/*------------------------------------------------------------------------------
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
#define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE)
#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.
* ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE )
#else
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE )
#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.
------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else
#define XT_USER_SIZE 0x400
#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.
* ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else
#define XT_USER_SIZE 0x400
#endif
/* 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. */
#define XT_STACK_EXTRA (XT_XTRA_SIZE)
#define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE)
#define XT_STACK_EXTRA ( XT_XTRA_SIZE )
#define XT_STACK_EXTRA_CLIB ( XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE )
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* XTENSA_CONFIG_H */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -39,7 +38,7 @@
#define XTENSA_CONTEXT_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#endif
#include <xtensa/config/tie.h>
@ -48,304 +47,310 @@
/* 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.
-------------------------------------------------------------------------------
*/
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
* -------------------------------------------------------------------------------
* Macros that help define structures for both C and assembler.
* -------------------------------------------------------------------------------
*/
#if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ )
#define STRUCT_BEGIN .pushsection .text; .struct 0
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
#define STRUCT_END(sname) sname##Size:; .popsection
#define STRUCT_BEGIN .pushsection.text; .struct 0
#define STRUCT_FIELD( ctype, size, asname, name ) asname:.space size
#define STRUCT_AFIELD( ctype, size, asname, name, n ) asname:.space( size ) *( n )
#define STRUCT_END( sname ) sname ## Size:; .popsection
#else
#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_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;
#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.
* -------------------------------------------------------------------------------
*/
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_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)
STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
STRUCT_FIELD (long, 4, XT_STK_A2, a2)
STRUCT_FIELD (long, 4, XT_STK_A3, a3)
STRUCT_FIELD (long, 4, XT_STK_A4, a4)
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)
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 )
STRUCT_FIELD( long, 4, XT_STK_A1, a1 ) /* stack pointer before interrupt */
STRUCT_FIELD( long, 4, XT_STK_A2, a2 )
STRUCT_FIELD( long, 4, XT_STK_A3, a3 )
STRUCT_FIELD( long, 4, XT_STK_A4, a4 )
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
STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
STRUCT_FIELD( long, 4, XT_STK_LBEG, lbeg )
STRUCT_FIELD( long, 4, XT_STK_LEND, lend )
STRUCT_FIELD( long, 4, XT_STK_LCOUNT, lcount )
#endif
#ifndef __XTENSA_CALL0_ABI__
/* Temporary space for saving stuff during window spill */
STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
STRUCT_FIELD( long, 4, XT_STK_TMP0, tmp0 )
STRUCT_FIELD( long, 4, XT_STK_TMP1, tmp1 )
STRUCT_FIELD( long, 4, XT_STK_TMP2, tmp2 )
#endif
#ifdef XT_USE_SWPRI
/* Storage for virtual priority mask */
STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
STRUCT_FIELD( long, 4, XT_STK_VPRI, vpri )
#endif
#ifdef XT_USE_OVLY
/* Storage for overlay state */
STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
STRUCT_FIELD( long, 4, XT_STK_OVLY, ovly )
#endif
STRUCT_END(XtExcFrame)
STRUCT_END( XtExcFrame )
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
#define XT_STK_NEXT1 XtExcFrameSize
#if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ )
#define XT_STK_NEXT1 XtExcFrameSize
#else
#define XT_STK_NEXT1 sizeof(XtExcFrame)
#define XT_STK_NEXT1 sizeof( XtExcFrame )
#endif
/* Allocate extra storage if needed */
#if XCHAL_EXTRA_SA_SIZE != 0
#if XCHAL_EXTRA_SA_ALIGN <= 16
#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
#else
#if XCHAL_EXTRA_SA_ALIGN <= 16
#define XT_STK_EXTRA ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 )
#else
/* 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)
#endif
#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
#define XT_STK_EXTRA ( ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 ) + XCHAL_EXTRA_SA_ALIGN )
#endif
#define XT_STK_NEXT2 ( XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE )
#else
#define XT_STK_NEXT2 XT_STK_NEXT1
#define XT_STK_NEXT2 XT_STK_NEXT1
#endif
#endif /* if XCHAL_EXTRA_SA_SIZE != 0 */
/*
-------------------------------------------------------------------------------
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)
* -------------------------------------------------------------------------------
* 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
#ifdef __XTENSA_CALL0_ABI__
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
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_A13, a13)
STRUCT_FIELD (long, 4, XT_SOL_A14, a14)
STRUCT_FIELD (long, 4, XT_SOL_A15, a15)
#else
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
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_A1, a1)
STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
#endif
STRUCT_END(XtSolFrame)
STRUCT_FIELD( long,
4,
XT_SOL_EXIT,
exit )
STRUCT_FIELD( long, 4, XT_SOL_PC, pc )
STRUCT_FIELD( long, 4, XT_SOL_PS, ps )
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_A13, a13 )
STRUCT_FIELD( long, 4, XT_SOL_A14, a14 )
STRUCT_FIELD( long, 4, XT_SOL_A15, a15 )
#else /* ifdef __XTENSA_CALL0_ABI__ */
STRUCT_FIELD( long, 4, XT_SOL_EXIT, exit )
STRUCT_FIELD( long, 4, XT_SOL_PC, pc )
STRUCT_FIELD( long, 4, XT_SOL_PS, ps )
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_A1, a1 )
STRUCT_FIELD( long, 4, XT_SOL_A2, a2 )
STRUCT_FIELD( long, 4, XT_SOL_A3, a3 )
#endif /* ifdef __XTENSA_CALL0_ABI__ */
STRUCT_END( XtSolFrame )
/* 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
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
/* Offsets of each coprocessor save area within the 'aligned save area': */
#define XT_CP0_SA 0
#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_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_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_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_CP0_SA 0
#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_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_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_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 )
/* Offsets within the overall save area: */
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active 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_ASA 8 /* (4 bytes) ptr to aligned save area */
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active 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_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
#define XT_CP_SIZE 0
#endif
#define XT_CP_SIZE ( 12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN )
#else /* if XCHAL_CP_NUM > 0 */
#define XT_CP_SIZE 0
#endif /* if XCHAL_CP_NUM > 0 */
/*
-------------------------------------------------------------------------------
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__
#ifdef __XTENSA_CALL0_ABI__
/* Call0 */
#define ENTRY(sz) entry1 sz
.macro entry1 size=0x10
addi sp, sp, -\size
s32i a0, sp, 0
.endm
#define ENTRY0
#define RET(sz) ret1 sz
.macro ret1 size=0x10
l32i a0, sp, 0
addi sp, sp, \size
ret
.endm
#define RET0 ret
#else
/* Windowed */
#define ENTRY(sz) entry sp, sz
#define ENTRY0 entry sp, 0x10
#define RET(sz) retw
#define RET0 retw
#endif
#endif
#ifdef __XTENSA_CALL0_ABI__
/* Call0 */
#define ENTRY( sz ) entry1 sz
.macro entry1 size = 0x10
addi sp, sp, -\ size
s32i a0, sp, 0
.endm
#define ENTRY0
#define RET( sz ) ret1 sz
.macro ret1 size = 0x10
l32i a0, sp, 0
addi sp, sp, \ size
ret
.endm
#define RET0 ret
#else /* ifdef __XTENSA_CALL0_ABI__ */
/* 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 /* XTENSA_CONTEXT_H */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -31,36 +30,31 @@
#ifdef XT_BOARD
#include <xtensa/xtbsp.h>
#include <xtensa/xtbsp.h>
#endif
#include "xtensa_rtos.h"
#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
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 */
}
* 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 */
}
#endif /* XT_RTOS_TIMER_INT */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -38,96 +37,110 @@
/* 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.
*/
void xt_unhandled_exception(XtExcFrame *frame)
{
exit(-1);
}
* Default handler for unhandled exceptions.
*/
void xt_unhandled_exception( XtExcFrame * frame )
{
exit( -1 );
}
/*
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 old;
* 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 old;
if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
return 0; /* invalid exception number */
if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) )
{
return 0; /* invalid exception number */
}
old = _xt_exception_table[n];
old = _xt_exception_table[ n ];
if (f) {
_xt_exception_table[n] = f;
}
else {
_xt_exception_table[n] = &xt_unhandled_exception;
if( f )
{
_xt_exception_table[ n ] = f;
}
else
{
_xt_exception_table[ n ] = &xt_unhandled_exception;
}
return( ( old == &xt_unhandled_exception ) ? 0 : old );
}
return ((old == &xt_unhandled_exception) ? 0 : old);
}
#endif
#endif /* if XCHAL_HAVE_EXCEPTIONS */
#if XCHAL_HAVE_INTERRUPTS
/* Handler table is in xtensa_intr_asm.S */
typedef struct xt_handler_table_entry {
void * handler;
void * arg;
} xt_handler_table_entry;
typedef struct xt_handler_table_entry
{
void * handler;
void * arg;
} 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.
*/
void xt_unhandled_interrupt(void * arg)
{
exit(-1);
}
* Default handler for unhandled interrupts.
*/
void xt_unhandled_interrupt( void * arg )
{
exit( -1 );
}
/*
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_table_entry * entry;
xt_handler old;
* 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_table_entry * entry;
xt_handler old;
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 */
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
{
return 0; /* invalid interrupt number */
}
entry = _xt_interrupt_table + n;
old = entry->handler;
if( Xthal_intlevel[ n ] > XCHAL_EXCM_LEVEL )
{
return 0; /* priority level too high to safely handle in C */
}
if (f) {
entry->handler = f;
entry->arg = arg;
entry = _xt_interrupt_table + n;
old = entry->handler;
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 );
}
else {
entry->handler = &xt_unhandled_interrupt;
entry->arg = (void*)n;
}
return ((old == &xt_unhandled_interrupt) ? 0 : old);
}
#endif /* XCHAL_HAVE_INTERRUPTS */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -34,7 +33,7 @@
/* Mutex object that controls access to the overlay. Currently only one
* 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
@ -42,30 +41,30 @@ static SemaphoreHandle_t xt_overlay_mutex;
* Typically this mutex would be set up with priority inheritance. See
* overlay manager documentation for more details.
*/
void xt_overlay_init_os(void)
{
/* Create the mutex for overlay access. Priority inheritance is
* required.
*/
xt_overlay_mutex = xSemaphoreCreateMutex();
}
void xt_overlay_init_os( void )
{
/* Create the mutex for overlay access. Priority inheritance is
* required.
*/
xt_overlay_mutex = xSemaphoreCreateMutex();
}
/* This function locks access to shared overlay resources, typically
* by acquiring a mutex.
*/
void xt_overlay_lock(void)
{
xSemaphoreTake(xt_overlay_mutex, 0);
}
void xt_overlay_lock( void )
{
xSemaphoreTake( xt_overlay_mutex, 0 );
}
/* This function releases access to shared overlay resources, typically
* by unlocking a mutex.
*/
void xt_overlay_unlock(void)
{
xSemaphoreGive(xt_overlay_mutex);
}
void xt_overlay_unlock( void )
{
xSemaphoreGive( xt_overlay_mutex );
}
#endif
#endif /* if configUSE_MUTEX */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -33,10 +32,10 @@
* Macros in this header map callouts from generic Xtensa files to specific
* RTOS functions. It may also be included in C source files.
*
* Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa
* architecture, using the Xtensa hardware abstraction layer (HAL) to deal
* Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa
* architecture, using the Xtensa hardware abstraction layer (HAL) to deal
* with configuration specifics.
*
*
* Should be included by all Xtensa generic and RTOS port-specific sources.
*/
@ -44,9 +43,9 @@
#define XTENSA_RTOS_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#else
#include <xtensa/config/core.h>
#include <xtensa/config/core.h>
#endif
#include <xtensa/corebits.h>
@ -54,181 +53,180 @@
#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
#if configXT_SIMULATOR
#define XT_SIMULATOR 1 /* Simulator mode */
#endif
#if configXT_SIMULATOR
#define XT_SIMULATOR 1 /* Simulator mode */
#endif
#endif
#ifndef XT_BOARD
#if configXT_BOARD
#define XT_BOARD 1 /* Board mode */
#endif
#if configXT_BOARD
#define XT_BOARD 1 /* Board mode */
#endif
#endif
#ifndef XT_TIMER_INDEX
#if defined configXT_TIMER_INDEX
#define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */
#endif
#if defined configXT_TIMER_INDEX
#define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */
#endif
#endif
#ifndef XT_INTEXC_HOOKS
#if configXT_INTEXC_HOOKS
#define XT_INTEXC_HOOKS 1 /* Enables exception hooks */
#endif
#if configXT_INTEXC_HOOKS
#define XT_INTEXC_HOOKS 1 /* Enables exception hooks */
#endif
#endif
#if (!XT_SIMULATOR) && (!XT_BOARD)
#error Either XT_SIMULATOR or XT_BOARD must be defined.
#if ( !XT_SIMULATOR ) && ( !XT_BOARD )
#error Either XT_SIMULATOR or XT_BOARD must be defined.
#endif
/*
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
#error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)."
#error "FreeRTOS/Xtensa requires XEA2 (exception architecture 2)."
#endif
/*******************************************************************************
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.
*/
// void XT_RTOS_INT_ENTER(void)
#define XT_RTOS_INT_ENTER _frxt_int_enter
* 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) */
#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.
*/
// void XT_RTOS_INT_EXIT(void)
* 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) */
#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).
*/
// void XT_RTOS_TIMER_INT(void)
#define XT_RTOS_TIMER_INT _frxt_timer_int
#define XT_TICK_PER_SEC configTICK_RATE_HZ
* 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) */
#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).
*/
// void* XT_RTOS_CP_STATE(void)
* 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) */
#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)
#define XT_INTEXC_HOOK_NUM ( 1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI )
#ifndef __ASSEMBLER__
typedef unsigned (*XT_INTEXC_HOOK)(unsigned cause);
extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
typedef unsigned (* XT_INTEXC_HOOK)( unsigned cause );
extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[ XT_INTEXC_HOOK_NUM ];
#endif
/*******************************************************************************
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"
#ifdef XT_RTOS_TIMER_INT
#include "xtensa_timer.h"
#include "xtensa_timer.h"
#endif
/*******************************************************************************
Xtensa Port Version.
*
* Xtensa Port Version.
*
*******************************************************************************/
#define XTENSA_PORT_VERSION 1.7
#define XTENSA_PORT_VERSION_STRING "1.7"
#define XTENSA_PORT_VERSION 1.7
#define XTENSA_PORT_VERSION_STRING "1.7"
#endif /* XTENSA_RTOS_H */

View file

@ -1,4 +1,3 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -42,119 +41,118 @@
#define XTENSA_TIMER_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#endif
#include <xtensa/corebits.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>
/*
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
#error "This Xtensa configuration is unsupported, it has no timers."
#error "This Xtensa configuration is unsupported, it has no timers."
#else
#ifndef XT_TIMER_INDEX
#if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 3
#ifndef XT_TIMER_INDEX
#if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER3_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 3
#endif
#endif
#if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER2_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 2
#endif
#endif
#if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL( XCHAL_TIMER1_INTERRUPT ) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#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
#if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#define XT_TIMER_INDEX 2
#endif
#endif
#if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
#if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
#undef XT_TIMER_INDEX
#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
#error "There is no suitable timer in this Xtensa configuration."
#endif
#define XT_CCOMPARE (CCOMPARE + 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_INTEN (1 << XT_TIMER_INTNUM)
#define XT_CCOMPARE ( CCOMPARE + 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_INTEN ( 1 << XT_TIMER_INTNUM )
#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
#error "The timer selected by XT_TIMER_INDEX does not exist in this core."
#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
#error "The timer interrupt cannot be high priority (use medium or low)."
#endif
#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
#error "The timer selected by XT_TIMER_INDEX does not exist in this core."
#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
#error "The timer interrupt cannot be high priority (use medium or low)."
#endif
#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!).
*/
#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ)
#define XT_CLOCK_FREQ configCPU_CLOCK_HZ
* 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
#endif
#if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD)
#error "XT_CLOCK_FREQ must be defined for the target platform."
#if !defined( XT_CLOCK_FREQ ) && !defined( XT_BOARD )
#error "XT_CLOCK_FREQ must be defined for the target platform."
#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 */
#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)
#define XT_TICK_DIVISOR ( XT_CLOCK_FREQ / XT_TICK_PER_SEC )
#endif
#ifndef __ASSEMBLER__
extern unsigned _xt_tick_divisor;
extern void _xt_tick_divisor_init(void);
extern unsigned _xt_tick_divisor;
extern void _xt_tick_divisor_init( void );
#endif
#endif /* XTENSA_TIMER_H */
#endif /* XTENSA_TIMER_H */