mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-20 01:58:32 -04:00
Style: uncrusitfy
This commit is contained in:
parent
a5dbc2b1de
commit
718178c68a
406 changed files with 108795 additions and 106323 deletions
111
portable/ThirdParty/CDK/T-HEAD_CK802/port.c
vendored
111
portable/ThirdParty/CDK/T-HEAD_CK802/port.c
vendored
|
@ -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( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
186
portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h
vendored
186
portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h
vendored
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
312
portable/ThirdParty/GCC/ARC_EM_HS/freertos_tls.c
vendored
312
portable/ThirdParty/GCC/ARC_EM_HS/freertos_tls.c
vendored
|
@ -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__ */
|
||||
|
|
272
portable/ThirdParty/GCC/ARC_EM_HS/port.c
vendored
272
portable/ThirdParty/GCC/ARC_EM_HS/port.c
vendored
|
@ -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 */
|
||||
|
|
184
portable/ThirdParty/GCC/ARC_EM_HS/portmacro.h
vendored
184
portable/ThirdParty/GCC/ARC_EM_HS/portmacro.h
vendored
|
@ -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 */
|
||||
|
|
1021
portable/ThirdParty/GCC/ATmega/port.c
vendored
1021
portable/ThirdParty/GCC/ATmega/port.c
vendored
File diff suppressed because it is too large
Load diff
138
portable/ThirdParty/GCC/ATmega/portmacro.h
vendored
138
portable/ThirdParty/GCC/ATmega/portmacro.h
vendored
|
@ -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 */
|
||||
|
|
637
portable/ThirdParty/GCC/Posix/port.c
vendored
637
portable/ThirdParty/GCC/Posix/port.c
vendored
|
@ -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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
111
portable/ThirdParty/GCC/Posix/portmacro.h
vendored
111
portable/ThirdParty/GCC/Posix/portmacro.h
vendored
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
604
portable/ThirdParty/GCC/Xtensa_ESP32/port.c
vendored
604
portable/ThirdParty/GCC/Xtensa_ESP32/port.c
vendored
|
@ -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;
|
||||
}
|
||||
|
|
164
portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
vendored
164
portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
vendored
|
@ -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 ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
224
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
vendored
224
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
vendored
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
200
portable/ThirdParty/XCC/Xtensa/port.c
vendored
200
portable/ThirdParty/XCC/Xtensa/port.c
vendored
|
@ -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 */
|
||||
|
|
|
@ -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()
|
||||
|
|
327
portable/ThirdParty/XCC/Xtensa/portclib.c
vendored
327
portable/ThirdParty/XCC/Xtensa/portclib.c
vendored
|
@ -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 */
|
||||
|
|
258
portable/ThirdParty/XCC/Xtensa/portmacro.h
vendored
258
portable/ThirdParty/XCC/Xtensa/portmacro.h
vendored
|
@ -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 */
|
||||
|
||||
|
|
7
portable/ThirdParty/XCC/Xtensa/porttrace.h
vendored
7
portable/ThirdParty/XCC/Xtensa/porttrace.h
vendored
|
@ -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 */
|
||||
|
|
121
portable/ThirdParty/XCC/Xtensa/xtensa_api.h
vendored
121
portable/ThirdParty/XCC/Xtensa/xtensa_api.h
vendored
|
@ -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__ */
|
||||
|
||||
|
|
170
portable/ThirdParty/XCC/Xtensa/xtensa_config.h
vendored
170
portable/ThirdParty/XCC/Xtensa/xtensa_config.h
vendored
|
@ -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 */
|
||||
|
||||
|
|
483
portable/ThirdParty/XCC/Xtensa/xtensa_context.h
vendored
483
portable/ThirdParty/XCC/Xtensa/xtensa_context.h
vendored
|
@ -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 */
|
||||
|
||||
|
|
42
portable/ThirdParty/XCC/Xtensa/xtensa_init.c
vendored
42
portable/ThirdParty/XCC/Xtensa/xtensa_init.c
vendored
|
@ -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 */
|
||||
|
||||
|
|
141
portable/ThirdParty/XCC/Xtensa/xtensa_intr.c
vendored
141
portable/ThirdParty/XCC/Xtensa/xtensa_intr.c
vendored
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
238
portable/ThirdParty/XCC/Xtensa/xtensa_rtos.h
vendored
238
portable/ThirdParty/XCC/Xtensa/xtensa_rtos.h
vendored
|
@ -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 */
|
||||
|
||||
|
|
160
portable/ThirdParty/XCC/Xtensa/xtensa_timer.h
vendored
160
portable/ThirdParty/XCC/Xtensa/xtensa_timer.h
vendored
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue