Style: Revert uncrustify for portable directories (#122)

* Style: revert uncrustify portable directories

* Style: Uncrustify Some Portable files

Co-authored-by: Alfred Gedeon <gedeonag@amazon.com>
This commit is contained in:
alfred gedeon 2020-08-17 10:51:02 -07:00 committed by GitHub
parent a6da1cd0ce
commit 86653e2a1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
273 changed files with 64802 additions and 65931 deletions

View file

@ -25,41 +25,39 @@
#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;
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 ) = ( 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;
}
@ -82,25 +80,21 @@ 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();
@ -109,30 +103,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;
void xPortSysTickHandler( void )
{
portLONG ulDummy;
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
{
if (xTaskIncrementTick() != pdFALSE)
{
if( xTaskIncrementTick() != pdFALSE )
{
portYIELD_FROM_ISR( pdTRUE );
}
portYIELD_FROM_ISR(pdTRUE);
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
#endif /* if configUSE_PREEMPTION == 0 */
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
}
#endif
void vPortYieldHandler( void )
{
@ -145,17 +139,12 @@ void vPortYieldHandler( void )
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
}
__attribute__( ( weak ) ) void vApplicationStackOverflowHook( xTaskHandle * pxTask,
signed portCHAR * pcTaskName )
__attribute__((weak)) void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )
{
for( ; ; )
{
}
for(;;);
}
__attribute__( ( weak ) ) void vApplicationMallocFailedHook( void )
__attribute__((weak)) void vApplicationMallocFailedHook( void )
{
for( ; ; )
{
}
for(;;);
}

View file

@ -22,17 +22,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
/*-----------------------------------------------------------
@ -46,116 +46,114 @@
*/
/* 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();
static inline portLONG SaveLocalPSR (void)
{
portLONG flags = __get_PSR();
__disable_irq();
return flags;
}
__disable_irq();
return flags;
}
static inline void RestoreLocalPSR (portLONG newMask)
{
__asm__ __volatile__(
"mtcr %0, psr \n"
:
:"r" (newMask)
:"memory"
);
}
static inline void RestoreLocalPSR( portLONG newMask )
{
__asm__ __volatile__ (
"mtcr %0, psr \n"
:
: "r" ( newMask )
: "memory"
);
}
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern __attribute__((naked)) void cpu_yeild(void);
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern __attribute__( ( naked ) ) void cpu_yeild( void );
#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)
#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 )
#define portNOP() asm("nop")
#define portNOP() asm ( "nop" )
extern portLONG ulCriticalNesting;
extern portLONG pendsvflag;
extern portLONG ulCriticalNesting;
extern portLONG pendsvflag;
#define portYIELD() \
if( ulCriticalNesting == 0 ) \
{ \
vPortYield(); \
} \
else \
{ \
pendsvflag = 1; \
} \
portNOP(); portNOP()
#define portYIELD() if (ulCriticalNesting == 0) \
{ \
vPortYield(); \
} \
else \
{ \
pendsvflag = 1; \
} \
portNOP();portNOP()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
do { \
if( xSwitchRequired != pdFALSE ) \
{ \
portYIELD(); \
} \
} while( 0 )
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { \
if( xSwitchRequired != pdFALSE ) \
{ \
portYIELD(); \
} \
}while(0)
#define portYIELD_FROM_ISR( a ) vTaskSwitchContext()
#define portYIELD_FROM_ISR( a ) vTaskSwitchContext()
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -54,7 +54,8 @@
extern void __mw_run_tls_dtor();
extern void __mw_run_tls_ctor();
extern uint32_t exc_nest_count;
extern uint32_t exc_nest_count;
/*
* Linker generated symbols to mark .tls section addresses
* first byte .. last byte

View file

@ -41,6 +41,7 @@
volatile unsigned int ulCriticalNesting = 999UL;
volatile unsigned int context_switch_reqflg; /* task context switch request flag in exceptions and interrupts handling */
/**
* \var exc_nest_count
* \brief the counter for exc/int processing, =0 no int/exc

View file

@ -26,16 +26,18 @@
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* 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.
@ -48,78 +50,78 @@
*/
/* 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 Asm
#define Asm __asm__ volatile
#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 ( ( uint32_t ) 0 )
#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 ( ( uint32_t ) 0 )
#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" ); \
} \
#define portENABLE_INTERRUPTS() \
{ \
Asm( "" ::: "memory" ); \
Asm( "seti" ); \
} \
extern volatile unsigned int ulCriticalNesting;
extern volatile unsigned int ulCriticalNesting;
#define portENTER_CRITICAL() \
#define portENTER_CRITICAL() \
{ \
portDISABLE_INTERRUPTS() \
ulCriticalNesting++; \
}
#define portEXIT_CRITICAL() \
#define portEXIT_CRITICAL() \
{ \
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) \
{ \
@ -132,24 +134,26 @@
}
#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 )
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() do {} while( 0 ) /* we use the timer */
#define portALT_GET_RUN_TIME_COUNTER_VALUE( dest ) ( dest = xTickCount )
#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
#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
void vPortYield( void );
void vPortYieldFromIsr( void );
void vPortYield( void );
void vPortYieldFromIsr( void );
#ifdef __cplusplus
}
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

File diff suppressed because it is too large Load diff

View file

@ -23,14 +23,14 @@
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
@ -42,49 +42,47 @@
*-----------------------------------------------------------
*/
#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. */
@ -93,66 +91,66 @@
* Prefer to use the enhanced Watchdog Timer, but also Timer0 is ok.
*/
#if defined( WDIE ) && defined( WDIF ) /* If Enhanced WDT with interrupt capability is available */
#if defined(WDIE) && defined(WDIF) /* If Enhanced WDT with interrupt capability is available */
#define portUSE_WDTO WDTO_15MS /* use the Watchdog Timer for xTaskIncrementTick */
#define portUSE_WDTO WDTO_15MS /* use the Watchdog Timer for xTaskIncrementTick */
/* Watchdog period options: WDTO_15MS
* WDTO_30MS
* WDTO_60MS
* WDTO_120MS
* WDTO_250MS
* WDTO_500MS
* WDTO_1S
* WDTO_2S
*/
WDTO_30MS
WDTO_60MS
WDTO_120MS
WDTO_250MS
WDTO_500MS
WDTO_1S
WDTO_2S
*/
#else
#else
#define portUSE_TIMER0 /* use the 8-bit Timer0 for xTaskIncrementTick */
#define portUSE_TIMER0 /* use the 8-bit Timer0 for xTaskIncrementTick */
#endif
#endif
#define portSTACK_GROWTH ( -1 )
#define portSTACK_GROWTH ( -1 )
/* Timing for the scheduler.
* Watchdog Timer is 128kHz nominal,
* but 120 kHz at 5V DC and 25 degrees is actually more accurate,
* from data sheet.
*/
#if defined( portUSE_WDTO )
#define portTICK_PERIOD_MS ( ( TickType_t ) _BV( portUSE_WDTO + 4 ) )
#else
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#endif
#if defined( portUSE_WDTO )
#define portTICK_PERIOD_MS ( (TickType_t) _BV( portUSE_WDTO + 4 ) )
#else
#define portTICK_PERIOD_MS ( (TickType_t) 1000 / configTICK_RATE_HZ )
#endif
#define portBYTE_ALIGNMENT 1
#define portNOP() __asm__ __volatile__ ( "nop" );
#define portBYTE_ALIGNMENT 1
#define portNOP() __asm__ __volatile__ ( "nop" );
/*-----------------------------------------------------------*/
/* Kernel utilities. */
extern void vPortYield( void ) __attribute__( ( naked ) );
#define portYIELD() vPortYield()
extern void vPortYield( void ) __attribute__ ( ( naked ) );
#define portYIELD() vPortYield()
extern void vPortYieldFromISR( void ) __attribute__( ( naked ) );
#define portYIELD_FROM_ISR() vPortYieldFromISR()
extern void vPortYieldFromISR( void ) __attribute__ ( ( naked ) );
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
#if defined( __AVR_3_BYTE_PC__ )
#if defined(__AVR_3_BYTE_PC__)
/* Task function macros as described on the FreeRTOS.org WEB site. */
/* Add .lowtext tag from the avr linker script avr6.x for ATmega2560 and ATmega2561
* to make sure functions are loaded in low memory.
*/
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( section( ".lowtext" ) ) )
#else
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#endif
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__ ((section (".lowtext")))
#else
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#endif
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -26,31 +26,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>
@ -67,25 +67,25 @@
#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);
}
/*-----------------------------------------------------------*/
@ -94,7 +94,7 @@ 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_t hMainThread = ( pthread_t )NULL;
static volatile portBASE_TYPE uxCriticalNesting;
/*-----------------------------------------------------------*/
@ -103,9 +103,8 @@ 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 );
@ -132,117 +131,110 @@ 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 );
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
prvWaitForStart, thread );
if ( iRet )
{
prvFatalError( "pthread_create", iRet );
}
if( iRet )
{
prvFatalError( "pthread_create", iRet );
}
vPortExitCritical();
vPortExitCritical();
return pxTopOfStack;
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 );
}
/*-----------------------------------------------------------*/
@ -251,126 +243,125 @@ void vPortStartFirstTask( void )
*/
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;
}
/*-----------------------------------------------------------*/
@ -379,13 +370,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;
@ -397,228 +388,218 @@ 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 );
/* Initialise the structure with the current timer information. */
iRet = getitimer( ITIMER_REAL, &itimer );
if ( iRet )
{
prvFatalError( "getitimer", errno );
}
if( iRet )
{
prvFatalError( "getitimer", errno );
}
/* Set the interval between timer events. */
itimer.it_interval.tv_sec = 0;
itimer.it_interval.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 the current count-down. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS;
/* Set the current count-down. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS;
/* Set-up the timer interrupt. */
iRet = setitimer( ITIMER_REAL, &itimer, NULL );
if ( iRet )
{
prvFatalError( "setitimer", errno );
}
/* Set-up the timer interrupt. */
iRet = setitimer( ITIMER_REAL, &itimer, NULL );
if( iRet )
{
prvFatalError( "setitimer", errno );
}
prvStartTimeNs = prvGetTimeNs();
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 );
/* 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);
do
{
xTaskIncrementTick();
prvTickCount++;
} while( prvTickCount < xExpectedTicks );
#if ( configUSE_PREEMPTION == 1 )
/* Select Next Task. */
vTaskSwitchContext();
#if ( configUSE_PREEMPTION == 1 )
/* Select Next Task. */
vTaskSwitchContext();
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
prvSwitchThread(pxThreadToResume, pxThreadToSuspend);
#endif
prvSwitchThread( pxThreadToResume, pxThreadToSuspend );
#endif
uxCriticalNesting--;
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 );
prvResumeThread( pxThreadToResume->pthread );
if ( pxThreadToSuspend->xDying )
{
pthread_exit( NULL );
}
prvSuspendSelf();
if( pxThreadToSuspend->xDying )
{
pthread_exit( NULL );
}
prvSuspendSelf();
uxCriticalNesting = uxSavedCriticalNesting;
}
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 );
/* 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 );
/* Don't block SIGINT so this can be used to break into GDB while
* in a critical section. */
sigdelset( &xAllSignals, SIGINT );
/*
* 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 );
/*
* 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 );
/* 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 );
/* 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 );
sigtick.sa_flags = 0;
sigtick.sa_handler = vPortSystemTickHandler;
sigfillset( &sigtick.sa_mask );
sigtick.sa_flags = 0;
sigtick.sa_handler = vPortSystemTickHandler;
sigfillset( &sigtick.sa_mask );
iRet = sigaction( SIG_RESUME, &sigresume, 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 );
}
iRet = sigaction( SIGALRM, &sigtick, NULL );
if ( iRet )
{
prvFatalError( "sigaction", errno );
}
}
/*-----------------------------------------------------------*/
unsigned long ulPortGetRunTime( void )
{
struct tms xTimes;
struct tms xTimes;
times( &xTimes );
times( &xTimes );
return ( unsigned long ) xTimes.tms_utime;
return ( unsigned long ) xTimes.tms_utime;
}
/*-----------------------------------------------------------*/

View file

@ -27,13 +27,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.
@ -46,72 +46,71 @@
*/
/* 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 )
/*-----------------------------------------------------------*/
/*
@ -122,14 +121,14 @@
* Thus, only a compilier barrier is needed to prevent the compiler
* reordering.
*/
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
extern unsigned long ulPortGetRunTime( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime()
extern unsigned long ulPortGetRunTime( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime()
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -64,26 +64,28 @@
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
#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" */
@ -99,84 +101,84 @@
/* 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"
#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;
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;
/* 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
#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, \
#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 \
#else
#define portMUX_INITIALIZER_UNLOCKED \
{ \
.owner = portMUX_FREE_VAL, \
.count = 0, \
.lastLockedFn = "(never locked)", \
.lastLockedLine = -1 \
}
#endif /* ifndef CONFIG_FREERTOS_PORTMUX_DEBUG */
#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.
@ -204,17 +206,17 @@
* 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 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
*
@ -224,35 +226,35 @@
*
* @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 ); \
} \
#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 ); \
} \
#define portEXIT_CRITICAL_SAFE( mux ) \
do { \
if( xPortInIsrContext() ) { \
portEXIT_CRITICAL_ISR( mux ); \
} \
else { \
portEXIT_CRITICAL( mux ); \
} \
} while( 0 )
@ -260,37 +262,37 @@
/* 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 )
#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 );
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 )
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 )
#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( state ) portEXIT_CRITICAL_NESTED( state )
/*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 )
#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
#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
@ -301,118 +303,118 @@
* *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 )
{
#if ( XCHAL_HAVE_S32C1I > 0 )
__asm__ __volatile__ (
"WSR %2,SCOMPARE1 \n"
"S32C1I %0, %1, 0 \n"
: "=r" ( *set )
: "r" ( addr ), "r" ( compare ), "0" ( *set )
);
#else
/* No S32C1I, so do this by disabling and re-enabling interrupts (slower) */
uint32_t intlevel, old_value;
__asm__ __volatile__ ( "rsil %0, " XTSTR( XCHAL_EXCM_LEVEL ) "\n"
: "=r" ( intlevel ) );
static inline void uxPortCompareSet( volatile uint32_t * addr,
uint32_t compare,
uint32_t * set )
{
#if ( XCHAL_HAVE_S32C1I > 0 )
__asm__ __volatile__ (
"WSR %2,SCOMPARE1 \n"
"S32C1I %0, %1, 0 \n"
: "=r" ( *set )
: "r" ( addr ), "r" ( compare ), "0" ( *set )
);
#else
/* No S32C1I, so do this by disabling and re-enabling interrupts (slower) */
uint32_t intlevel, old_value;
__asm__ __volatile__ ( "rsil %0, " XTSTR( XCHAL_EXCM_LEVEL ) "\n"
: "=r" ( intlevel ) );
old_value = *addr;
old_value = *addr;
if( old_value == compare )
{
*addr = *set;
}
if( old_value == compare )
{
*addr = *set;
}
__asm__ __volatile__ ( "memw \n"
"wsr %0, ps\n"
: : "r" ( intlevel ) );
__asm__ __volatile__ ( "memw \n"
"wsr %0, ps\n"
: : "r" ( intlevel ) );
*set = old_value;
#endif /* if ( XCHAL_HAVE_S32C1I > 0 ) */
}
*set = old_value;
#endif /* if ( XCHAL_HAVE_S32C1I > 0 ) */
}
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()
#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount()
/*ccount or esp_timer are initialized elsewhere */
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#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
#if portUSING_MPU_WRAPPERS
/* Define here mpu_settings, which is port dependent */
int mpu_setting; /* Just a dummy example here; MPU not ported to Xtensa yet */
#endif
#if configUSE_TRACE_FACILITY_2
struct
{
/* Cf. porttraceStamp() */
int taskstamp; /* Stamp from inside task to see where we are */
int taskstampcount; /* A counter usually incremented when we restart the task's loop */
} porttrace;
#endif
} xMPU_SETTINGS;
/* Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) */
#if ( XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2 ) && !portUSING_MPU_WRAPPERS /* If MPU wrappers not used, we still need to allocate coproc area */
#undef portUSING_MPU_WRAPPERS
#define portUSING_MPU_WRAPPERS 1 /* Enable it to allocate coproc area */
#define MPU_WRAPPERS_H /* Override mpu_wrapper.h to disable unwanted code */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA
typedef struct
{
#if XCHAL_CP_NUM > 0
volatile StackType_t * coproc_area; /* Pointer to coprocessor save area; MUST BE FIRST */
#endif
bool vApplicationSleep( TickType_t xExpectedIdleTime );
#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
#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime )
#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
bool vApplicationSleep( TickType_t xExpectedIdleTime );
#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 );
/*
@ -422,29 +424,29 @@
* 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
/*
* 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
@ -453,46 +455,48 @@
* 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
/* 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;
}
/* Get tick rate per second */
uint32_t xPortGetTickRateHz( void );
/* 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
#endif // __ASSEMBLER__
#ifdef __cplusplus
}
#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;
}
/* Get tick rate per second */
uint32_t xPortGetTickRateHz( void );
/* 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
#endif // __ASSEMBLER__
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */

View file

@ -154,6 +154,7 @@ void _xt_user_exit( void );
/*
* Stack initialization
*/
/* *INDENT-OFF* */
#if portUSING_MPU_WRAPPERS
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
@ -164,6 +165,7 @@ void _xt_user_exit( void );
TaskFunction_t pxCode,
void * pvParameters )
#endif
/* *INDENT-ON* */
{
StackType_t * sp, * tp;
XtExcFrame * frame;
@ -409,7 +411,7 @@ void vPortCPUInitializeMutex( portMUX_TYPE * mux )
return result;
}
#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
void vPortCPUAcquireMutex( portMUX_TYPE * mux )
{
unsigned int irqStatus = portENTER_CRITICAL_NESTED();

View file

@ -35,9 +35,9 @@
#include "xtensa_rtos.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#include "esp32/clk.h"
#endif
#ifdef XT_RTOS_TIMER_INT

View file

@ -35,9 +35,9 @@
#include "freertos/portable.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/ets_sys.h"
#endif
#if XCHAL_HAVE_EXCEPTIONS

View file

@ -1,3 +1,4 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -59,155 +60,146 @@
/* 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;
StackType_t *sp, *tp;
XtExcFrame *frame;
#if XCHAL_CP_NUM > 0
uint32_t *p;
#endif
#if XCHAL_CP_NUM > 0
uint32_t * p;
#endif
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = (StackType_t *) (((UBaseType_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = ( StackType_t * ) ( ( ( UBaseType_t ) ( pxTopOfStack + 1 ) - XT_CP_SIZE - XT_STK_FRMSZ ) & ~0xf );
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for (tp = sp; tp <= pxTopOfStack; ++tp)
*tp = 0;
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for( tp = sp; tp <= pxTopOfStack; ++tp )
{
*tp = 0;
}
frame = (XtExcFrame *) sp;
frame = ( XtExcFrame * ) sp;
/* 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 */
/* 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 */
/* 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
/* 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
#ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */
frame->vpri = 0xFFFFFFFF;
#endif
#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.
#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;
}
/*-----------------------------------------------------------*/
@ -215,18 +207,16 @@ 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 /* if portUSING_MPU_WRAPPERS */
/* 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

View file

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

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -25,204 +26,200 @@
#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;
base = heap_ptr;
if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
return (char *) -1;
}
if( heap_ptr + incr >= _heap_sentry_ptr )
{
reent->_errno = ENOMEM;
return ( char * ) -1;
}
heap_ptr += incr;
return base;
}
heap_ptr += incr;
return base;
}
//-----------------------------------------------------------------------------
// Global initialization for C library.
//-----------------------------------------------------------------------------
void
vPortClibInit(void)
{
}
/*----------------------------------------------------------------------------- */
/* Global initialization for C library. */
/*----------------------------------------------------------------------------- */
void vPortClibInit( void )
{
}
//-----------------------------------------------------------------------------
// Per-thread cleanup stub provided for linking, does nothing.
//-----------------------------------------------------------------------------
void
_reclaim_reent(void * ptr)
{
}
/*----------------------------------------------------------------------------- */
/* Per-thread cleanup stub provided for linking, does nothing. */
/*----------------------------------------------------------------------------- */
void _reclaim_reent( void * ptr )
{
}
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "semphr.h"
#include "semphr.h"
static SemaphoreHandle_t xClibMutex;
static uint32_t ulClibInitDone = 0;
static SemaphoreHandle_t xClibMutex;
static uint32_t ulClibInitDone = 0;
//-----------------------------------------------------------------------------
// Get C library lock.
//-----------------------------------------------------------------------------
void
__malloc_lock(struct _reent * ptr)
{
if (!ulClibInitDone)
return;
/*----------------------------------------------------------------------------- */
/* Get C library lock. */
/*----------------------------------------------------------------------------- */
void __malloc_lock( struct _reent * ptr )
{
if( !ulClibInitDone )
{
return;
}
xSemaphoreTakeRecursive(xClibMutex, portMAX_DELAY);
}
xSemaphoreTakeRecursive( xClibMutex, portMAX_DELAY );
}
//-----------------------------------------------------------------------------
// Release C library lock.
//-----------------------------------------------------------------------------
void
__malloc_unlock(struct _reent * ptr)
{
if (!ulClibInitDone)
return;
/*----------------------------------------------------------------------------- */
/* Release C library lock. */
/*----------------------------------------------------------------------------- */
void __malloc_unlock( struct _reent * ptr )
{
if( !ulClibInitDone )
{
return;
}
xSemaphoreGiveRecursive(xClibMutex);
}
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 );
}
//-----------------------------------------------------------------------------
// 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;
base = heap_ptr;
if (heap_ptr + incr >= _heap_sentry_ptr) {
reent->_errno = ENOMEM;
return (char *) -1;
}
if( heap_ptr + incr >= _heap_sentry_ptr )
{
reent->_errno = ENOMEM;
return ( char * ) -1;
}
heap_ptr += incr;
return base;
}
heap_ptr += incr;
return base;
}
//-----------------------------------------------------------------------------
// Global initialization for C library.
//-----------------------------------------------------------------------------
void
vPortClibInit(void)
{
configASSERT(!ulClibInitDone);
/*----------------------------------------------------------------------------- */
/* Global initialization for C library. */
/*----------------------------------------------------------------------------- */
void vPortClibInit( void )
{
configASSERT( !ulClibInitDone );
xClibMutex = xSemaphoreCreateRecursiveMutex();
ulClibInitDone = 1;
}
xClibMutex = xSemaphoreCreateRecursiveMutex();
ulClibInitDone = 1;
}
#endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
#endif /* XSHAL_CLIB == XTHAL_CLIB_NEWLIB */
#endif /* XT_USE_THREAD_SAFE_CLIB */

View file

@ -1,3 +1,4 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@ -50,23 +51,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,165 +81,156 @@
/* 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 );
// 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)
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 )
// 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;
// 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
for( i = 0; i < 3; ++i, ++fp )
{
fp->_close = NULL;
}
}
#endif // NEWLIB support
#endif // __ASSEMBLER__
#endif // __ASSEMBLER__
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -25,7 +26,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.
*/
@ -37,7 +38,7 @@
#error "You need to download the FreeRTOS_trace patch that overwrites this file"
#endif
#define porttracePrint( nelements )
#define porttraceStamp( stamp, count_incr )
#define porttracePrint(nelements)
#define porttraceStamp(stamp, count_incr)
#endif /* PORTTRACE_H */

View file

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

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -31,151 +32,152 @@
*/
#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"
/*-----------------------------------------------------------------------------
* STACK REQUIREMENTS
*
* This section defines the minimum stack size, and the extra space required to
* be allocated for saving coprocessor state and/or C library state information
* (if thread safety is enabled for the C library). The sizes are in bytes.
*
* Stack sizes for individual tasks should be derived from these minima based on
* the maximum call depth of the task and the maximum level of interrupt nesting.
* A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based
* on the requirement for a task that calls nothing else but can be interrupted.
* This assumes that interrupt handlers do not call more than a few levels deep.
* 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
* 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
* size, you must verify that the smaller size(s) will work
* under all operating conditions.
*
* XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task
* that does not make C library reentrant calls. Add this
* to the amount of stack space required by the task itself.
*
* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state.
*
* -----------------------------------------------------------------------------*/
* STACK REQUIREMENTS
*
* This section defines the minimum stack size, and the extra space required to
* be allocated for saving coprocessor state and/or C library state information
* (if thread safety is enabled for the C library). The sizes are in bytes.
*
* Stack sizes for individual tasks should be derived from these minima based on
* the maximum call depth of the task and the maximum level of interrupt nesting.
* A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based
* on the requirement for a task that calls nothing else but can be interrupted.
* This assumes that interrupt handlers do not call more than a few levels deep.
* 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
* 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
* size, you must verify that the smaller size(s) will work
* under all operating conditions.
*
* XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task
* that does not make C library reentrant calls. Add this
* to the amount of stack space required by the task itself.
*
* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state.
*
-----------------------------------------------------------------------------*/
/* 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
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);
#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 */
#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
/*------------------------------------------------------------------------------
* Extra size -- interrupt frame plus coprocessor save area plus hook space.
* NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks.
* ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE )
#else
#define XT_XTRA_SIZE ( XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE )
#endif
Extra size -- interrupt frame plus coprocessor save area plus hook space.
NOTE: Make sure XT_INTEXC_HOOKS is undefined unless you really need the hooks.
------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x10 + XT_CP_SIZE)
#else
#define XT_XTRA_SIZE (XT_STK_FRMSZ + STK_INTEXC_EXTRA + 0x20 + XT_CP_SIZE)
#endif
/*------------------------------------------------------------------------------
* Space allocated for user code -- function calls and local variables.
* NOTE: This number can be adjusted to suit your needs. You must verify that the
* amount of space you reserve is adequate for the worst-case conditions in your
* application.
* NOTE: The windowed ABI requires more stack, since space has to be reserved
* for spilling register windows.
* ------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else
#define XT_USER_SIZE 0x400
#endif
Space allocated for user code -- function calls and local variables.
NOTE: This number can be adjusted to suit your needs. You must verify that the
amount of space you reserve is adequate for the worst-case conditions in your
application.
NOTE: The windowed ABI requires more stack, since space has to be reserved
for spilling register windows.
------------------------------------------------------------------------------*/
#ifdef __XTENSA_CALL0_ABI__
#define XT_USER_SIZE 0x200
#else
#define XT_USER_SIZE 0x400
#endif
/* Minimum recommended stack size. */
#define XT_STACK_MIN_SIZE ( ( XT_XTRA_SIZE + XT_USER_SIZE ) / sizeof( unsigned char ) )
#define XT_STACK_MIN_SIZE ((XT_XTRA_SIZE + XT_USER_SIZE) / sizeof(unsigned char))
/* OS overhead with and without C library thread context. */
#define XT_STACK_EXTRA ( XT_XTRA_SIZE )
#define XT_STACK_EXTRA_CLIB ( XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE )
#define XT_STACK_EXTRA (XT_XTRA_SIZE)
#define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE)
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* XTENSA_CONFIG_H */

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -38,7 +39,7 @@
#define XTENSA_CONTEXT_H
#ifdef __ASSEMBLER__
#include <xtensa/coreasm.h>
#include <xtensa/coreasm.h>
#endif
#include <xtensa/config/tie.h>
@ -47,310 +48,304 @@
/* 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
*
* A stack frame of this structure is allocated for any interrupt or exception.
* It goes on the current stack. If the RTOS has a system stack for handling
* interrupts, every thread stack must allow space for just one interrupt stack
* frame, then nested interrupt stack frames go on the system stack.
*
* The frame includes basic registers (explicit) and "extra" registers introduced
* by user TIE or the use of the MAC16 option in the user's Xtensa config.
* The frame size is minimized by omitting regs not applicable to user's config.
*
* For Windowed ABI, this stack frame includes the interruptee's base save area,
* another base save area to manage gcc nested functions, and a little temporary
* space to help manage the spilling of the register windows.
* -------------------------------------------------------------------------------
*/
-------------------------------------------------------------------------------
INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
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 )
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)
#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 /* if XCHAL_EXTRA_SA_SIZE != 0 */
#endif
/*
* -------------------------------------------------------------------------------
* This is the frame size. Add space for 4 registers (interruptee's base save
* area) and some space for gcc nested functions if any.
* -------------------------------------------------------------------------------
*/
#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 /* 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 )
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)
/* 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 /* if XCHAL_CP_NUM > 0 */
#define XT_CP_SIZE 0
#endif /* if XCHAL_CP_NUM > 0 */
#define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)
#else
#define XT_CP_SIZE 0
#endif
/*
* -------------------------------------------------------------------------------
* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
*
* Convenient where the frame size requirements are the same for both ABIs.
* ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
* ENTRY0, RET0 are for frameless functions (no locals, no calls).
*
* where size = size of stack frame in bytes (must be >0 and aligned to 16).
* For framed functions the frame is created and the return address saved at
* base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
* For frameless functions, there is no frame and return address remains in a0.
* Note: Because CPP macros expand to a single line, macros requiring multi-line
* expansions are implemented as assembler macros.
* -------------------------------------------------------------------------------
*/
-------------------------------------------------------------------------------
MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
Convenient where the frame size requirements are the same for both ABIs.
ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
ENTRY0, RET0 are for frameless functions (no locals, no calls).
where size = size of stack frame in bytes (must be >0 and aligned to 16).
For framed functions the frame is created and the return address saved at
base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
For frameless functions, there is no frame and return address remains in a0.
Note: Because CPP macros expand to a single line, macros requiring multi-line
expansions are implemented as assembler macros.
-------------------------------------------------------------------------------
*/
#ifdef __ASSEMBLER__
#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__ */
#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
#endif /* XTENSA_CONTEXT_H */

View file

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

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -37,110 +38,96 @@
/* 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;
}
return( ( old == &xt_unhandled_exception ) ? 0 : old );
if (f) {
_xt_exception_table[n] = f;
}
else {
_xt_exception_table[n] = &xt_unhandled_exception;
}
#endif /* if XCHAL_HAVE_EXCEPTIONS */
return ((old == &xt_unhandled_exception) ? 0 : old);
}
#endif
#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( 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( 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;
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 );
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);
}
#endif /* XCHAL_HAVE_INTERRUPTS */

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -33,7 +34,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
@ -41,30 +42,30 @@
* 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 /* if configUSE_MUTEX */
#endif

View file

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

View file

@ -1,3 +1,4 @@
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
@ -41,118 +42,119 @@
#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
#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."
#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
#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 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)
#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 */