+#include "sys/reent.h"
/*
* If stdint.h cannot be located then:
@@ -739,6 +740,20 @@ extern "C" {
#define portTICK_TYPE_IS_ATOMIC 0
#endif
+#ifndef configSUPPORT_STATIC_ALLOCATION
+ /* Defaults to 0 for backward compatibility. */
+ #define configSUPPORT_STATIC_ALLOCATION 0
+#endif
+
+#ifndef configSUPPORT_DYNAMIC_ALLOCATION
+ /* Defaults to 1 for backward compatibility. */
+ #define configSUPPORT_DYNAMIC_ALLOCATION 1
+#endif
+
+#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
+ #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1.
+#endif
+
#if( portTICK_TYPE_IS_ATOMIC == 0 )
/* Either variables of tick type cannot be read atomically, or
portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
@@ -791,6 +806,153 @@ V8 if desired. */
#define configESP32_PER_TASK_DATA 1
#endif
+/*
+ * In line with software engineering best practice, FreeRTOS implements a strict
+ * data hiding policy, so the real structures used by FreeRTOS to maintain the
+ * state of tasks, queues, semaphores, etc. are not accessible to the application
+ * code. However, if the application writer wants to statically allocate such
+ * an object then the size of the object needs to be know. Dummy structures
+ * that are guaranteed to have the same size and alignment requirements of the
+ * real objects are used for this purpose. The dummy list and list item
+ * structures below are used for inclusion in such a dummy structure.
+ */
+struct xSTATIC_LIST_ITEM
+{
+ TickType_t xDummy1;
+ void *pvDummy2[ 4 ];
+};
+typedef struct xSTATIC_LIST_ITEM StaticListItem_t;
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+struct xSTATIC_MINI_LIST_ITEM
+{
+ TickType_t xDummy1;
+ void *pvDummy2[ 2 ];
+};
+typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t;
+
+/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
+typedef struct xSTATIC_LIST
+{
+ UBaseType_t uxDummy1;
+ void *pvDummy2;
+ StaticMiniListItem_t xDummy3;
+} StaticList_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the Task structure used internally by
+ * FreeRTOS is not accessible to application code. However, if the application
+ * writer wants to statically allocate the memory required to create a task then
+ * the size of the task object needs to be know. The StaticTask_t structure
+ * below is provided for this purpose. Its sizes and alignment requirements are
+ * guaranteed to match those of the genuine structure, no matter which
+ * architecture is being used, and no matter how the values in FreeRTOSConfig.h
+ * are set. Its contents are somewhat obfuscated in the hope users will
+ * recognise that it would be unwise to make direct use of the structure members.
+ */
+typedef struct xSTATIC_TCB
+{
+ void *pxDummy1;
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ xMPU_SETTINGS xDummy2;
+ #endif
+ StaticListItem_t xDummy3[ 2 ];
+ UBaseType_t uxDummy5;
+ void *pxDummy6;
+ uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ];
+ UBaseType_t uxDummyCoreId;
+ #if ( portSTACK_GROWTH > 0 )
+ void *pxDummy8;
+ #endif
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ UBaseType_t uxDummy9;
+ uint32_t OldInterruptState;
+ #endif
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy10[ 2 ];
+ #endif
+ #if ( configUSE_MUTEXES == 1 )
+ UBaseType_t uxDummy12[ 2 ];
+ #endif
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ void *pxDummy14;
+ #endif
+ #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
+ void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+ #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
+ void *pvDummyLocalStorageCallBack[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+ #endif
+ #endif
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ uint32_t ulDummy16;
+ #endif
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ struct _reent xDummy17;
+ #endif
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ uint32_t ulDummy18;
+ uint32_t ucDummy19;
+ #endif
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t uxDummy20;
+ #endif
+
+} StaticTask_t;
+
+/*
+ * In line with software engineering best practice, especially when supplying a
+ * library that is likely to change in future versions, FreeRTOS implements a
+ * strict data hiding policy. This means the Queue structure used internally by
+ * FreeRTOS is not accessible to application code. However, if the application
+ * writer wants to statically allocate the memory required to create a queue
+ * then the size of the queue object needs to be know. The StaticQueue_t
+ * structure below is provided for this purpose. Its sizes and alignment
+ * requirements are guaranteed to match those of the genuine structure, no
+ * matter which architecture is being used, and no matter how the values in
+ * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope
+ * users will recognise that it would be unwise to make direct use of the
+ * structure members.
+ */
+typedef struct xSTATIC_QUEUE
+{
+ void *pvDummy1[ 3 ];
+
+ union
+ {
+ void *pvDummy2;
+ UBaseType_t uxDummy2;
+ } u;
+
+ StaticList_t xDummy3[ 2 ];
+ UBaseType_t uxDummy4[ 3 ];
+ BaseType_t ucDummy5[ 2 ];
+
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucDummy6;
+ #endif
+
+ #if ( configUSE_QUEUE_SETS == 1 )
+ void *pvDummy7;
+ #endif
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxDummy8;
+ uint8_t ucDummy9;
+ #endif
+
+ struct {
+ volatile uint32_t mux;
+ #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+ const char *lastLockedFn;
+ int lastLockedLine;
+ #endif
+ } mux;
+
+} StaticQueue_t;
+typedef StaticQueue_t StaticSemaphore_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h
index d1958e770..224857c86 100644
--- a/components/freertos/include/freertos/FreeRTOSConfig.h
+++ b/components/freertos/include/freertos/FreeRTOSConfig.h
@@ -152,9 +152,9 @@
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
-#define configUSE_IDLE_HOOK 0
+#define configUSE_IDLE_HOOK ( CONFIG_TASK_WDT_CHECK_IDLE_TASK )
-#define configUSE_TICK_HOOK 0
+#define configUSE_TICK_HOOK ( CONFIG_INT_WDT )
#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ )
@@ -180,7 +180,7 @@
/* The Xtensa port uses a separate interrupt stack. Adjust the stack size */
/* to suit the needs of your specific application. */
#ifndef configISR_STACK_SIZE
-#define configISR_STACK_SIZE 1024//2048
+#define configISR_STACK_SIZE CONFIG_FREERTOS_ISR_STACKSIZE
#endif
/* Minimal heap size to make sure examples can run on memory limited
@@ -231,6 +231,7 @@
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
+#define INCLUDE_pcTaskGetTaskName 1
#if CONFIG_ENABLE_MEMORY_DEBUG
#define configENABLE_MEMORY_DEBUG 1
@@ -251,6 +252,8 @@
#define configUSE_NEWLIB_REENTRANT 1
+#define configSUPPORT_DYNAMIC_ALLOCATION 1
+
/* Test FreeRTOS timers (with timer task) and more. */
/* Some files don't compile if this flag is disabled */
#define configUSE_TIMERS 1
diff --git a/components/freertos/include/freertos/panic.h b/components/freertos/include/freertos/panic.h
deleted file mode 100644
index 9e902ed20..000000000
--- a/components/freertos/include/freertos/panic.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PANIC_H
-#define PANIC_H
-
-void setBreakpointIfJtag(void *fn);
-
-
-#endif
\ No newline at end of file
diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h
index 4030ca0c0..9ed378a8a 100644
--- a/components/freertos/include/freertos/portable.h
+++ b/components/freertos/include/freertos/portable.h
@@ -179,6 +179,14 @@ BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
*/
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
+
+/*
+ * Send an interrupt to another core in order to make the task running
+ * on it yield for a higher-priority task.
+ */
+
+void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
+
/*
* The structures and methods of manipulating the MPU are contained within the
* port layer.
@@ -192,8 +200,14 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
#endif
/* Multi-core: get current core ID */
-int xPortGetCoreID( void );
-
+static inline uint32_t xPortGetCoreID() {
+ int id;
+ asm volatile(
+ "rsr.prid %0\n"
+ " extui %0,%0,13,1"
+ :"=r"(id));
+ return id;
+}
#ifdef __cplusplus
}
diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h
index ab83b0e05..f20a4a1e2 100644
--- a/components/freertos/include/freertos/portmacro.h
+++ b/components/freertos/include/freertos/portmacro.h
@@ -225,6 +225,26 @@ static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_I
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state)
+/*
+ * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
+ * *mux to compare, and if it's the same, will set *mux to set. It will return the old value
+ * of *addr in *set.
+ *
+ * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
+ * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
+ * ESP32, though. (Would show up directly if it did because the magic wouldn't match.)
+ */
+static inline void uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
+ __asm__ __volatile__(
+ "WSR %2,SCOMPARE1 \n"
+ "ISYNC \n"
+ "S32C1I %0, %1, 0 \n"
+ :"=r"(*set)
+ :"r"(addr), "r"(compare), "0"(*set)
+ );
+}
+
+
/*-----------------------------------------------------------*/
/* Architecture specifics. */
diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h
index 2095c59b0..876f1a1b3 100644
--- a/components/freertos/include/freertos/queue.h
+++ b/components/freertos/include/freertos/queue.h
@@ -170,7 +170,95 @@ typedef void * QueueSetMemberHandle_t;
* \defgroup xQueueCreate xQueueCreate
* \ingroup QueueManagement
*/
-#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
+#endif
+
+/**
+ * queue. h
+ *
+ QueueHandle_t xQueueCreateStatic(
+ UBaseType_t uxQueueLength,
+ UBaseType_t uxItemSize,
+ uint8_t *pucQueueStorageBuffer,
+ StaticQueue_t *pxQueueBuffer
+ );
+ *
+ *
+ * Creates a new queue instance, and returns a handle by which the new queue
+ * can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, queues use two blocks of
+ * memory. The first block is used to hold the queue's data structures. The
+ * second block is used to hold items placed into the queue. If a queue is
+ * created using xQueueCreate() then both blocks of memory are automatically
+ * dynamically allocated inside the xQueueCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a queue is created using
+ * xQueueCreateStatic() then the application writer must provide the memory that
+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to
+ * be created without using any dynamic memory allocation.
+ *
+ * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html
+ *
+ * @param uxQueueLength The maximum number of items that the queue can contain.
+ *
+ * @param uxItemSize The number of bytes each item in the queue will require.
+ * Items are queued by copy, not by reference, so this is the number of bytes
+ * that will be copied for each posted item. Each item on the queue must be
+ * the same size.
+ *
+ * @param pucQueueStorageBuffer If uxItemSize is not zero then
+ * pucQueueStorageBuffer must point to a uint8_t array that is at least large
+ * enough to hold the maximum number of items that can be in the queue at any
+ * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is
+ * zero then pucQueueStorageBuffer can be NULL.
+ *
+ * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
+ * will be used to hold the queue's data structure.
+ *
+ * @return If the queue is created then a handle to the created queue is
+ * returned. If pxQueueBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+
+ struct AMessage
+ {
+ char ucMessageID;
+ char ucData[ 20 ];
+ };
+
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+
+ // xQueueBuffer will hold the queue structure.
+ StaticQueue_t xQueueBuffer;
+
+ // ucQueueStorage will hold the items posted to the queue. Must be at least
+ // [(queue length) * ( queue item size)] bytes long.
+ uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1;
+
+ // Create a queue capable of containing 10 uint32_t values.
+ xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+ ITEM_SIZE // The size of each item in the queue
+ &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+ &xQueueBuffer ); // The buffer that will hold the queue structure.
+
+ // The queue is guaranteed to be created successfully as no dynamic memory
+ // allocation is used. Therefore xQueue1 is now a handle to a valid queue.
+
+ // ... Rest of task code.
+ }
+
+ * \defgroup xQueueCreateStatic xQueueCreateStatic
+ * \ingroup QueueManagement
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* queue. h
@@ -1479,7 +1567,9 @@ BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTi
* these functions directly.
*/
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
+QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
/*
@@ -1538,10 +1628,22 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
#endif
/*
- * Generic version of the queue creation function, which is in turn called by
- * any queue, semaphore or mutex creation function or macro.
+ * Generic version of the function used to creaet a queue using dynamic memory
+ * allocation. This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
*/
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Generic version of the function used to creaet a queue using dynamic memory
+ * allocation. This is called by other functions and macros that create other
+ * RTOS objects that use the queue structure as their base.
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
+#endif
/*
* Queue sets provide a mechanism to allow a task to block (pend) on a read
diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h
index 5866ab1ec..6343d0190 100644
--- a/components/freertos/include/freertos/semphr.h
+++ b/components/freertos/include/freertos/semphr.h
@@ -128,19 +128,37 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
-#define vSemaphoreCreateBinary( xSemaphore ) \
- { \
- ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
- if( ( xSemaphore ) != NULL ) \
- { \
- ( void ) xSemaphoreGive( ( xSemaphore ) ); \
- } \
- }
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define vSemaphoreCreateBinary( xSemaphore ) \
+ { \
+ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
+ if( ( xSemaphore ) != NULL ) \
+ { \
+ ( void ) xSemaphoreGive( ( xSemaphore ) ); \
+ } \
+ }
+#endif
/**
* semphr. h
* SemaphoreHandle_t xSemaphoreCreateBinary( void )
*
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored. If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function. (see http://www.freertos.org/a00111.html). If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
* The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
@@ -182,7 +200,68 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
-#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif
+
+/**
+ * semphr. h
+ * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
+ *
+ * Creates a new binary semaphore instance, and returns a handle by which the
+ * new semaphore can be referenced.
+ *
+ * NOTE: In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a binary semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, binary semaphores use a block
+ * of memory, in which the semaphore structure is stored. If a binary semaphore
+ * is created using xSemaphoreCreateBinary() then the required memory is
+ * automatically dynamically allocated inside the xSemaphoreCreateBinary()
+ * function. (see http://www.freertos.org/a00111.html). If a binary semaphore
+ * is created using xSemaphoreCreateBinaryStatic() then the application writer
+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
+ * binary semaphore to be created without using any dynamic memory allocation.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task. The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore. For this reason this type of
+ * semaphore does not use a priority inheritance mechanism. For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the semaphore is created then a handle to the created semaphore is
+ * returned. If pxSemaphoreBuffer is NULL then NULL is returned.
+ *
+ * Example usage:
+
+ SemaphoreHandle_t xSemaphore = NULL;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+ // The semaphore's data structures will be placed in the xSemaphoreBuffer
+ // variable, the address of which is passed into the function. The
+ // function's parameter is not NULL, so the function will not attempt any
+ // dynamic memory allocation, and therefore the function will not return
+ // return NULL.
+ xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
+
+ // Rest of task code goes here.
+ }
+
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
@@ -652,9 +731,18 @@ typedef QueueHandle_t SemaphoreHandle_t;
* Macro that implements a mutex semaphore by using the existing queue
* mechanism.
*
- * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored. If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
* and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
- * xSemaphoreGiveRecursive() macros should not be used.
+ * xSemaphoreGiveRecursive() macros must not be used.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
@@ -667,8 +755,9 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
*
- * @return xSemaphore Handle to the created mutex semaphore. Should be of type
- * SemaphoreHandle_t.
+ * @return If the mutex was successfully created then a handle to the created
+ * semaphore is returned. If there was not enough heap to allocate the mutex
+ * data structures then NULL is returned.
*
* Example usage:
@@ -690,19 +779,93 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
* \ingroup Semaphores
*/
-#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ *
+ * Creates a new mutex type semaphore instance, and returns a handle by which
+ * the new mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block
+ * of memory, in which the mutex structure is stored. If a mutex is created
+ * using xSemaphoreCreateMutex() then the required memory is automatically
+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a mutex is created using
+ * xSemaphoreCreateMutexStatic() then the application writer must provided the
+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
+ * without using any dynamic memory allocation.
+ *
+ * Mutexes created using this function can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros must not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will be used to hold the mutex's data structure, removing the need for
+ * the memory to be allocated dynamically.
+ *
+ * @return If the mutex was successfully created then a handle to the created
+ * mutex is returned. If pxMutexBuffer was NULL then NULL is returned.
+ *
+ * Example usage:
+
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ // A mutex cannot be used before it has been created. xMutexBuffer is
+ // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
+ // attempted.
+ xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
+
+ // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+ // so there is no need to check it.
+ }
+
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
+ * \ingroup Semaphores
+ */
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
*
- * Macro that implements a recursive mutex by using the existing queue
- * mechanism.
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block
+ * of memory, in which the mutex structure is stored. If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
*
* Mutexes created using this macro can be accessed using the
* xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
- * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
*
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called
@@ -745,14 +908,104 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
* \ingroup Semaphores
*/
-#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
+#endif
+
+/**
+ * semphr. h
+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ *
+ * Creates a new recursive mutex type semaphore instance, and returns a handle
+ * by which the new recursive mutex can be referenced.
+ *
+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block
+ * of memory, in which the mutex structure is stored. If a recursive mutex is
+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is
+ * automatically dynamically allocated inside the
+ * xSemaphoreCreateRecursiveMutex() function. (see
+ * http://www.freertos.org/a00111.html). If a recursive mutex is created using
+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must
+ * provide the memory that will get used by the mutex.
+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
+ * be created without using any dynamic memory allocation.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also 'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the recursive mutex's data structure,
+ * removing the need for the memory to be allocated dynamically.
+ *
+ * @return If the recursive mutex was successfully created then a handle to the
+ * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is
+ * returned.
+ *
+ * Example usage:
+
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ // A recursive semaphore cannot be used before it is created. Here a
+ // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
+ // The address of xMutexBuffer is passed into the function, and will hold
+ // the mutexes data structures - so no dynamic memory allocation will be
+ // attempted.
+ xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
+
+ // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+ // so there is no need to check it.
+ }
+
+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic
+ * \ingroup Semaphores
+ */
+#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
+ #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
*
- * Macro that creates a counting semaphore by using the existing
- * queue mechanism.
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored. If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function. (see
+ * http://www.freertos.org/a00111.html). If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer can
+ * instead optionally provide the memory that will get used by the counting
+ * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting
+ * semaphore to be created without using any dynamic memory allocation.
*
* Counting semaphores are typically used for two things:
*
@@ -808,7 +1061,94 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
* \ingroup Semaphores
*/
-#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
+#endif
+
+/**
+ * semphr. h
+ * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )
+ *
+ * Creates a new counting semaphore instance, and returns a handle by which the
+ * new counting semaphore can be referenced.
+ *
+ * In many usage scenarios it is faster and more memory efficient to use a
+ * direct to task notification in place of a counting semaphore!
+ * http://www.freertos.org/RTOS-task-notifications.html
+ *
+ * Internally, within the FreeRTOS implementation, counting semaphores use a
+ * block of memory, in which the counting semaphore structure is stored. If a
+ * counting semaphore is created using xSemaphoreCreateCounting() then the
+ * required memory is automatically dynamically allocated inside the
+ * xSemaphoreCreateCounting() function. (see
+ * http://www.freertos.org/a00111.html). If a counting semaphore is created
+ * using xSemaphoreCreateCountingStatic() then the application writer must
+ * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a
+ * counting semaphore to be created without using any dynamic memory allocation.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ * In this usage scenario an event handler will 'give' a semaphore each time
+ * an event occurs (incrementing the semaphore count value), and a handler
+ * task will 'take' a semaphore each time it processes an event
+ * (decrementing the semaphore count value). The count value is therefore
+ * the difference between the number of events that have occurred and the
+ * number that have been processed. In this case it is desirable for the
+ * initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ * In this usage scenario the count value indicates the number of resources
+ * available. To obtain control of a resource a task must first obtain a
+ * semaphore - decrementing the semaphore count value. When the count value
+ * reaches zero there are no free resources. When a task finishes with the
+ * resource it 'gives' the semaphore back - incrementing the semaphore count
+ * value. In this case it is desirable for the initial count value to be
+ * equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached. When the
+ * semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ * created.
+ *
+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
+ * which will then be used to hold the semaphore's data structure, removing the
+ * need for the memory to be allocated dynamically.
+ *
+ * @return If the counting semaphore was successfully created then a handle to
+ * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL
+ * then NULL is returned.
+ *
+ * Example usage:
+
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Counting semaphore cannot be used before they have been created. Create
+ // a counting semaphore using xSemaphoreCreateCountingStatic(). The max
+ // value to which the semaphore can count is 10, and the initial value
+ // assigned to the count will be 0. The address of xSemaphoreBuffer is
+ // passed in and will be used to hold the semaphore structure, so no dynamic
+ // memory allocation will be used.
+ xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
+
+ // No memory allocation was attempted so xSemaphore cannot be NULL, so there
+ // is no need to check its value.
+ }
+
+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic
+ * \ingroup Semaphores
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h
index 9f3f3d659..f7b9181fc 100644
--- a/components/freertos/include/freertos/task.h
+++ b/components/freertos/include/freertos/task.h
@@ -177,6 +177,7 @@ typedef struct xTASK_STATUS
UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
+ StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */
uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
} TaskStatus_t;
@@ -281,8 +282,19 @@ is used in assert() statements. */
);
*
* Create a new task and add it to the list of tasks that are ready to run.
- * On multicore environments, this will give no specific affinity to the task.
- * Use xTaskCreatePinnedToCore to give affinity.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory. xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * See xTaskCreateStatic() for a version that does not use any dynamic memory
+ * allocation.
*
* xTaskCreate() can only be used to create a task that has unrestricted
* access to the entire microcontroller memory map. Systems that include MPU
@@ -350,8 +362,139 @@ is used in assert() statements. */
* \defgroup xTaskCreate xTaskCreate
* \ingroup Tasks
*/
-#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), tskNO_AFFINITY )
-#define xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), xCoreID )
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint16_t usStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask,
+ const BaseType_t xCoreID);
+
+#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskCreatePinnedToCore( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), tskNO_AFFINITY )
+#endif
+
+/**
+ * task. h
+ *
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
+ const char * const pcName,
+ uint32_t ulStackDepth,
+ void *pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t *pxStackBuffer,
+ StaticTask_t *pxTaskBuffer,
+ const BaseType_t xCoreID );
+
+ *
+ * Create a new task and add it to the list of tasks that are ready to run.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreate() then both blocks of memory are automatically dynamically
+ * allocated inside the xTaskCreate() function. (see
+ * http://www.freertos.org/a00111.html). If a task is created using
+ * xTaskCreateStatic() then the application writer must provide the required
+ * memory. xTaskCreateStatic() therefore allows a task to be created without
+ * using any dynamic memory allocation.
+ *
+ * @param pvTaskCode Pointer to the task entry function. Tasks
+ * must be implemented to never return (i.e. continuous loop).
+ *
+ * @param pcName A descriptive name for the task. This is mainly used to
+ * facilitate debugging. The maximum length of the string is defined by
+ * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
+ *
+ * @param ulStackDepth The size of the task stack specified as the number of
+ * variables the stack can hold - not the number of bytes. For example, if
+ * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes
+ * will be allocated for stack storage.
+ *
+ * @param pvParameters Pointer that will be used as the parameter for the task
+ * being created.
+ *
+ * @param uxPriority The priority at which the task will run.
+ *
+ * @param pxStackBuffer Must point to a StackType_t array that has at least
+ * ulStackDepth indexes - the array will then be used as the task's stack,
+ * removing the need for the stack to be allocated dynamically.
+ *
+ * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
+ * then be used to hold the task's data structures, removing the need for the
+ * memory to be allocated dynamically.
+ *
+ * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
+ * be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer
+ * are NULL then the task will not be created and
+ * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
+ *
+ * Example usage:
+
+
+ // Dimensions the buffer that the task being created will use as its stack.
+ // NOTE: This is the number of words the stack will hold, not the number of
+ // bytes. For example, if each stack item is 32-bits, and this is set to 100,
+ // then 400 bytes (100 * 32-bits) will be allocated.
+ #define STACK_SIZE 200
+
+ // Structure that will hold the TCB of the task being created.
+ StaticTask_t xTaskBuffer;
+
+ // Buffer that the task being created will use as its stack. Note this is
+ // an array of StackType_t variables. The size of StackType_t is dependent on
+ // the RTOS port.
+ StackType_t xStack[ STACK_SIZE ];
+
+ // Function that implements the task being created.
+ void vTaskCode( void * pvParameters )
+ {
+ // The parameter value is expected to be 1 as 1 is passed in the
+ // pvParameters value in the call to xTaskCreateStatic().
+ configASSERT( ( uint32_t ) pvParameters == 1UL );
+
+ for( ;; )
+ {
+ // Task code goes here.
+ }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ TaskHandle_t xHandle = NULL;
+
+ // Create the task without using any dynamic memory allocation.
+ xHandle = xTaskCreateStatic(
+ vTaskCode, // Function that implements the task.
+ "NAME", // Text name for the task.
+ STACK_SIZE, // Stack size in words, not bytes.
+ ( void * ) 1, // Parameter passed into the task.
+ tskIDLE_PRIORITY,// Priority at which the task is created.
+ xStack, // Array to use as the task's stack.
+ &xTaskBuffer ); // Variable to hold the task's data structure.
+
+ // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
+ // been created, and xHandle will be the task's handle. Use the handle
+ // to suspend the task.
+ vTaskSuspend( xHandle );
+ }
+
+ * \defgroup xTaskCreateStatic xTaskCreateStatic
+ * \ingroup Tasks
+ */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t * const puxStackBuffer,
+ StaticTask_t * const pxTaskBuffer,
+ const BaseType_t xCoreID );
+
+#define xTaskCreateStatic( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxStackBuffer, pxTaskBuffer ) xTaskCreateStaticPinnedToCore( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxStackBuffer ), ( pxTaskBuffer ), tskNO_AFFINITY )
+#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* task. h
@@ -420,7 +563,9 @@ TaskHandle_t xHandle;
* \defgroup xTaskCreateRestricted xTaskCreateRestricted
* \ingroup Tasks
*/
-#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) )
+#if( portUSING_MPU_WRAPPERS == 1 )
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
/**
* task. h
@@ -1933,6 +2078,17 @@ TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
*/
TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
+
+
+/*
+ * Return the handle of the task running on a certain CPU. Because of
+ * the nature of SMP processing, there is no guarantee that this
+ * value will still be valid on return and should only be used for
+ * debugging purposes.
+ */
+TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid );
+
+
/*
* Capture the current time status for future reference.
*/
@@ -1968,12 +2124,6 @@ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTIO
*/
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
-/*
- * Generic version of the task creation function which is in turn called by the
- * xTaskCreate() and xTaskCreateRestricted() macros.
- */
-BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-
/*
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
*/
diff --git a/components/freertos/include/freertos/xtensa_context.h b/components/freertos/include/freertos/xtensa_context.h
index 3167c8472..b748a0d1a 100644
--- a/components/freertos/include/freertos/xtensa_context.h
+++ b/components/freertos/include/freertos/xtensa_context.h
@@ -322,12 +322,7 @@ STRUCT_END(XtSolFrame)
#ifdef __ASSEMBLER__
.macro getcoreid reg
rsr.prid \reg
- bbci \reg,1,1f
- movi \reg,1
- j 2f
-1:
- movi \reg,0
-2:
+ extui \reg,\reg,13,1
.endm
#endif
diff --git a/components/freertos/port.c b/components/freertos/port.c
index 6117a2804..25480ed47 100644
--- a/components/freertos/port.c
+++ b/components/freertos/port.c
@@ -101,7 +101,9 @@
#include "FreeRTOS.h"
#include "task.h"
-#include "panic.h"
+#include "esp_panic.h"
+
+#include "esp_crosscore_int.h"
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);
@@ -228,6 +230,12 @@ BaseType_t xPortSysTickHandler( void )
return ret;
}
+
+
+void vPortYieldOtherCore( BaseType_t coreid ) {
+ esp_crosscore_int_send_yield( coreid );
+}
+
/*-----------------------------------------------------------*/
/*
@@ -253,28 +261,6 @@ void vPortAssertIfInISR()
configASSERT(port_interruptNesting[xPortGetCoreID()]==0)
}
-
-/*
- * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
- * *mux to compare, and if it's the same, will set *mux to set. It will return the old value
- * of *addr.
- *
- * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
- * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
- * ESP32, though. (Would show up directly if it did because the magic wouldn't match.)
- */
-uint32_t uxPortCompareSet(volatile uint32_t *mux, uint32_t compare, uint32_t set)
-{
- __asm__ __volatile__ (
- "WSR %2,SCOMPARE1 \n" //initialize SCOMPARE1
- "ISYNC \n" //wait sync
- "S32C1I %0, %1, 0 \n" //store id into the lock, if the lock is the same as comparel. Otherwise, no write-access
- :"=r"(set) \
- :"r"(mux), "r"(compare), "0"(set) \
- );
- return set;
-}
-
/*
* For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked.
*/
@@ -310,7 +296,8 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux) {
irqStatus=portENTER_CRITICAL_NESTED();
do {
//Lock mux if it's currently unlocked
- res=uxPortCompareSet(&mux->mux, portMUX_FREE_VAL, (xPortGetCoreID()<mux, portMUX_FREE_VAL, &res);
//If it wasn't free and we're the owner of the lock, we are locking recursively.
if ( (res != portMUX_FREE_VAL) && (((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT) == xPortGetCoreID()) ) {
//Mux was already locked by us. Just bump the recurse count by one.
@@ -362,29 +349,33 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux) {
if ( (mux->mux & portMUX_MAGIC_MASK) != portMUX_MAGIC_VAL ) ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is uninitialized (0x%X)!\n", mux, mux->mux);
#endif
//Unlock mux if it's currently locked with a recurse count of 0
- res=uxPortCompareSet(&mux->mux, (xPortGetCoreID()<mux, (xPortGetCoreID()<>portMUX_VAL_SHIFT) == xPortGetCoreID() ) {
+ //Lock is valid, we can return safely. Just need to check if it's a recursive lock; if so we need to decrease the refcount.
+ if ( ((res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT)!=0) {
+ //We locked this, but the reccount isn't zero. Decrease refcount and continue.
+ recCnt=(res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT;
+ recCnt--;
+#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
+ ets_printf("Recursive unlock: recCnt=%d last locked %s line %d, curr %s line %d\n", recCnt, lastLockedFn, lastLockedLine, fnName, line);
+#endif
+ mux->mux=portMUX_MAGIC_VAL|(recCnt<>portMUX_VAL_SHIFT) != xPortGetCoreID() ) {
+ } else {
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p wasn't locked by this core (%d) but by core %d (ret=%x, mux=%x).\n", mux, xPortGetCoreID(), ((res&portMUX_VAL_MASK)>>portMUX_VAL_SHIFT), res, mux->mux);
ets_printf("Last non-recursive lock %s line %d\n", lastLockedFn, lastLockedLine);
ets_printf("Called by %s line %d\n", fnName, line);
#endif
ret=pdFALSE;
- } else if ( ((res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT)!=0) {
- //We locked this, but the reccount isn't zero. Decrease refcount and continue.
- recCnt=(res&portMUX_CNT_MASK)>>portMUX_CNT_SHIFT;
- recCnt--;
-#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
- ets_printf("Recursive unlock: recCnt=%d last locked %s line %d, curr %s line %d\n", recCnt, lastLockedFn, lastLockedLine, fnName, line);
-#endif
- mux->mux=portMUX_MAGIC_VAL|(recCnt<pxTopOfStack = SP */
movi a1, port_IntStackTop /* a1 = top of intr stack */
movi a2, configISR_STACK_SIZE
- getcoreid a3
- mull a2, a3, a2
+ mull a2, a4, a2
add a1, a1, a2 /* for current proc */
.Lnested:
@@ -177,12 +162,11 @@ _frxt_int_enter:
.align 4
_frxt_int_exit:
- getcoreid a3
- slli a4, a3, 2 /* a4 is core * 4 */
+ getcoreid a4
movi a2, port_xSchedulerRunning
- add a2, a2, a4
+ addx4 a2, a4, a2
movi a3, port_interruptNesting
- add a3, a3, a4
+ addx4 a3, a4, a3
rsil a0, XCHAL_EXCM_LEVEL /* lock out interrupts */
l32i a2, a2, 0 /* a2 = port_xSchedulerRunning */
beqz a2, .Lnoswitch /* scheduler not running, no tasks */
@@ -192,13 +176,13 @@ _frxt_int_exit:
bnez a2, .Lnesting /* !=0 after decr so still nested */
movi a2, pxCurrentTCB
- add a2, a2, a4
+ addx4 a2, a4, a2
l32i a2, a2, 0 /* a2 = current TCB */
beqz a2, 1f /* no task ? go to dispatcher */
l32i a1, a2, TOPOFSTACK_OFFS /* SP = pxCurrentTCB->pxTopOfStack */
movi a2, port_switch_flag /* address of switch flag */
- add a2, a2, a4 /* point to flag for this cpu */
+ addx4 a2, a4, a2 /* point to flag for this cpu */
l32i a3, a2, 0 /* a3 = port_switch_flag */
beqz a3, .Lnoswitch /* flag = 0 means no switch reqd */
movi a3, 0
@@ -404,14 +388,12 @@ _frxt_dispatch:
call0 vTaskSwitchContext // Get next TCB to resume
movi a2, pxCurrentTCB
getcoreid a3
- slli a3, a3, 2
- add a2, a2, a3
+ addx4 a2, a3, a2
#else
call4 vTaskSwitchContext // Get next TCB to resume
movi a2, pxCurrentTCB
getcoreid a3
- slli a3, a3, 2
- add a2, a2, a3
+ addx4 a2, a3, a2
#endif
l32i a3, a2, 0
l32i sp, a3, TOPOFSTACK_OFFS /* SP = next_TCB->pxTopOfStack; */
@@ -451,8 +433,7 @@ _frxt_dispatch:
/* Restore CPENABLE from task's co-processor save area. */
movi a3, pxCurrentTCB /* cp_state = */
getcoreid a2
- slli a2, a2, 2
- add a3, a2, a3
+ addx4 a3, a2, a3
l32i a3, a3, 0
l32i a2, a3, CP_TOPOFSTACK_OFFS /* StackType_t *pxStack; */
l16ui a3, a2, XT_CPENABLE /* CPENABLE = cp_state->cpenable; */
@@ -541,8 +522,7 @@ vPortYield:
movi a2, pxCurrentTCB
getcoreid a3
- slli a3, a3, 2
- add a2, a2, a3
+ addx4 a2, a3, a2
l32i a2, a2, 0 /* a2 = pxCurrentTCB */
movi a3, 0
s32i a3, sp, XT_SOL_EXIT /* 0 to flag as solicited frame */
@@ -593,8 +573,7 @@ vPortYieldFromInt:
/* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */
movi a3, pxCurrentTCB /* cp_state = */
getcoreid a2
- slli a2, a2, 2
- add a3, a2, a3
+ addx4 a3, a2, a3
l32i a3, a3, 0
l32i a2, a3, CP_TOPOFSTACK_OFFS
@@ -637,18 +616,17 @@ _frxt_task_coproc_state:
/* We can use a3 as a scratchpad, the instances of code calling XT_RTOS_CP_STATE don't seem to need it saved. */
getcoreid a3
- slli a3, a3, 2 /* a3=coreid*4 */
movi a15, port_xSchedulerRunning /* if (port_xSchedulerRunning */
- add a15, a15, a3
+ addx4 a15, a3,a15
l32i a15, a15, 0
beqz a15, 1f
movi a15, port_interruptNesting /* && port_interruptNesting == 0 */
- add a15, a15, a3
+ addx4 a15, a3, a15
l32i a15, a15, 0
bnez a15, 1f
movi a15, pxCurrentTCB
- add a15, a3, a15
+ addx4 a15, a3, a15
l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */
diff --git a/components/freertos/queue.c b/components/freertos/queue.c
index 168f09f1a..f404a243e 100644
--- a/components/freertos/queue.c
+++ b/components/freertos/queue.c
@@ -158,15 +158,19 @@ typedef struct QueueDefinition
UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */
- #if ( configUSE_TRACE_FACILITY == 1 )
- UBaseType_t uxQueueNumber;
- uint8_t ucQueueType;
+ #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
#endif
#if ( configUSE_QUEUE_SETS == 1 )
struct QueueDefinition *pxQueueSetContainer;
#endif
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ UBaseType_t uxQueueNumber;
+ uint8_t ucQueueType;
+ #endif
+
portMUX_TYPE mux;
} xQUEUE;
@@ -238,6 +242,21 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
#endif
+/*
+ * Called after a Queue_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
+
+/*
+ * Mutexes are a special type of queue. When a mutex is created, first the
+ * queue is created, then prvInitialiseMutex() is called to configure the queue
+ * as a mutex.
+ */
+#if( configUSE_MUTEXES == 1 )
+ static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
+#endif
+
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
{
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
@@ -293,132 +312,165 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
}
/*-----------------------------------------------------------*/
-QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
-{
-Queue_t *pxNewQueue;
-size_t xQueueSizeInBytes;
-QueueHandle_t xReturn = NULL;
-int8_t *pcAllocatedBuffer;
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType )
+ {
+ Queue_t *pxNewQueue;
+
+ configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
+
+ /* The StaticQueue_t structure and the queue storage area must be
+ supplied. */
+ configASSERT( pxStaticQueue != NULL );
+
+ /* A queue storage area should be provided if the item size is not 0, and
+ should not be provided if the item size is 0. */
+ configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );
+ configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );
+
+ #if( configASSERT_DEFINED == 1 )
+ {
+ /* Sanity check that the size of the structure used to declare a
+ variable of type StaticQueue_t or StaticSemaphore_t equals the size of
+ the real queue and semaphore structures. */
+ volatile size_t xSize = sizeof( StaticQueue_t );
+ configASSERT( xSize == sizeof( Queue_t ) );
+ }
+ #endif /* configASSERT_DEFINED */
+
+ /* The address of a statically allocated queue was passed in, use it.
+ The address of a statically allocated storage area was also passed in
+ but is already set. */
+ pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+
+ if( pxNewQueue != NULL )
+ {
+ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ {
+ /* Queues can be allocated wither statically or dynamically, so
+ note this queue was allocated statically in case the queue is
+ later deleted. */
+ pxNewQueue->ucStaticallyAllocated = pdTRUE;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
+ }
+
+ return pxNewQueue;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
+ {
+ Queue_t *pxNewQueue;
+ size_t xQueueSizeInBytes;
+ uint8_t *pucQueueStorage;
+
+ configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
+
+ if( uxItemSize == ( UBaseType_t ) 0 )
+ {
+ /* There is not going to be a queue storage area. */
+ xQueueSizeInBytes = ( size_t ) 0;
+ }
+ else
+ {
+ /* Allocate enough space to hold the maximum number of items that
+ can be in the queue at any time. */
+ xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ }
+
+ pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
+
+ if( pxNewQueue != NULL )
+ {
+ /* Jump past the queue structure to find the location of the queue
+ storage area. */
+ pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );
+
+ #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ {
+ /* Queues can be created either statically or dynamically, so
+ note this task was created dynamically in case it is later
+ deleted. */
+ pxNewQueue->ucStaticallyAllocated = pdFALSE;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
+
+ prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
+ }
+
+ return pxNewQueue;
+ }
+
+#endif /* configSUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )
+{
/* Remove compiler warnings about unused parameters should
configUSE_TRACE_FACILITY not be set to 1. */
( void ) ucQueueType;
- configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
-
if( uxItemSize == ( UBaseType_t ) 0 )
{
- /* There is not going to be a queue storage area. */
- xQueueSizeInBytes = ( size_t ) 0;
+ /* No RAM was allocated for the queue storage area, but PC head cannot
+ be set to NULL because NULL is used as a key to say the queue is used as
+ a mutex. Therefore just set pcHead to point to the queue as a benign
+ value that is known to be within the memory map. */
+ pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
}
else
{
- /* The queue is one byte longer than asked for to make wrap checking
- easier/faster. */
- xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ /* Set the head to the start of the queue storage area. */
+ pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
}
- /* Allocate the new queue structure and storage area. */
- pcAllocatedBuffer = ( int8_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
+ /* Initialise the queue members as described where the queue type is
+ defined. */
+ pxNewQueue->uxLength = uxQueueLength;
+ pxNewQueue->uxItemSize = uxItemSize;
+ ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
- if( pcAllocatedBuffer != NULL )
+ #if ( configUSE_TRACE_FACILITY == 1 )
{
- pxNewQueue = ( Queue_t * ) pcAllocatedBuffer; /*lint !e826 MISRA The buffer cannot be to small because it was dimensioned by sizeof( Queue_t ) + xQueueSizeInBytes. */
-
- if( uxItemSize == ( UBaseType_t ) 0 )
- {
- /* No RAM was allocated for the queue storage area, but PC head
- cannot be set to NULL because NULL is used as a key to say the queue
- is used as a mutex. Therefore just set pcHead to point to the queue
- as a benign value that is known to be within the memory map. */
- pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
- }
- else
- {
- /* Jump past the queue structure to find the location of the queue
- storage area - adding the padding bytes to get a better alignment. */
- pxNewQueue->pcHead = pcAllocatedBuffer + sizeof( Queue_t );
- }
-
- /* Initialise the queue members as described above where the queue type
- is defined. */
- pxNewQueue->uxLength = uxQueueLength;
- pxNewQueue->uxItemSize = uxItemSize;
- ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
-
- #if ( configUSE_TRACE_FACILITY == 1 )
- {
- pxNewQueue->ucQueueType = ucQueueType;
- }
- #endif /* configUSE_TRACE_FACILITY */
-
- #if( configUSE_QUEUE_SETS == 1 )
- {
- pxNewQueue->pxQueueSetContainer = NULL;
- }
- #endif /* configUSE_QUEUE_SETS */
-
- traceQUEUE_CREATE( pxNewQueue );
- xReturn = pxNewQueue;
+ pxNewQueue->ucQueueType = ucQueueType;
}
- else
+ #endif /* configUSE_TRACE_FACILITY */
+
+ #if( configUSE_QUEUE_SETS == 1 )
{
- mtCOVERAGE_TEST_MARKER();
+ pxNewQueue->pxQueueSetContainer = NULL;
}
+ #endif /* configUSE_QUEUE_SETS */
- configASSERT( xReturn );
-
- return xReturn;
+ traceQUEUE_CREATE( pxNewQueue );
}
/*-----------------------------------------------------------*/
-#if ( configUSE_MUTEXES == 1 )
+#if( configUSE_MUTEXES == 1 )
- QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+ static void prvInitialiseMutex( Queue_t *pxNewQueue )
{
- Queue_t *pxNewQueue;
-
- /* Prevent compiler warnings about unused parameters if
- configUSE_TRACE_FACILITY does not equal 1. */
- ( void ) ucQueueType;
-
- /* Allocate the new queue structure. */
- pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
if( pxNewQueue != NULL )
{
- /* Information required for priority inheritance. */
+ /* The queue create function will set all the queue structure members
+ correctly for a generic queue, but this function is creating a
+ mutex. Overwrite those members that need to be set differently -
+ in particular the information required for priority inheritance. */
pxNewQueue->pxMutexHolder = NULL;
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
- /* Queues used as a mutex no data is actually copied into or out
- of the queue. */
- pxNewQueue->pcWriteTo = NULL;
- pxNewQueue->u.pcReadFrom = NULL;
+ /* In case this is a recursive mutex. */
+ pxNewQueue->u.uxRecursiveCallCount = 0;
- /* Each mutex has a length of 1 (like a binary semaphore) and
- an item size of 0 as nothing is actually copied into or out
- of the mutex. */
- pxNewQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
- pxNewQueue->uxLength = ( UBaseType_t ) 1U;
- pxNewQueue->uxItemSize = ( UBaseType_t ) 0U;
-
- #if ( configUSE_TRACE_FACILITY == 1 )
- {
- pxNewQueue->ucQueueType = ucQueueType;
- }
- #endif
-
- #if ( configUSE_QUEUE_SETS == 1 )
- {
- pxNewQueue->pxQueueSetContainer = NULL;
- }
- #endif
-
- /* Ensure the event queues start with the correct state. */
- vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
- vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
-
- vPortCPUInitializeMutex(&pxNewQueue->mux);
+ vPortCPUInitializeMutex(&pxNewQueue->mux);
traceCREATE_MUTEX( pxNewQueue );
@@ -429,8 +481,41 @@ int8_t *pcAllocatedBuffer;
{
traceCREATE_MUTEX_FAILED();
}
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
+ {
+ Queue_t *pxNewQueue;
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+ pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
+ prvInitialiseMutex( pxNewQueue );
+
+ return pxNewQueue;
+ }
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue )
+ {
+ Queue_t *pxNewQueue;
+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
+
+ /* Prevent compiler warnings about unused parameters if
+ configUSE_TRACE_FACILITY does not equal 1. */
+ ( void ) ucQueueType;
+
+ pxNewQueue = ( Queue_t * ) xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );
+ prvInitialiseMutex( pxNewQueue );
- configASSERT( pxNewQueue );
return pxNewQueue;
}
@@ -565,7 +650,35 @@ int8_t *pcAllocatedBuffer;
#endif /* configUSE_RECURSIVE_MUTEXES */
/*-----------------------------------------------------------*/
-#if ( configUSE_COUNTING_SEMAPHORES == 1 )
+#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue )
+ {
+ QueueHandle_t xHandle;
+
+ configASSERT( uxMaxCount != 0 );
+ configASSERT( uxInitialCount <= uxMaxCount );
+
+ xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
+
+ if( xHandle != NULL )
+ {
+ ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;
+
+ traceCREATE_COUNTING_SEMAPHORE();
+ }
+ else
+ {
+ traceCREATE_COUNTING_SEMAPHORE_FAILED();
+ }
+
+ return xHandle;
+ }
+
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
+/*-----------------------------------------------------------*/
+
+#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
{
@@ -591,7 +704,7 @@ int8_t *pcAllocatedBuffer;
return xHandle;
}
-#endif /* configUSE_COUNTING_SEMAPHORES */
+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
/*-----------------------------------------------------------*/
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
@@ -1685,7 +1798,33 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
vQueueUnregisterQueue( pxQueue );
}
#endif
- vPortFree( pxQueue );
+
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
+ {
+ /* The queue can only have been allocated dynamically - free it
+ again. */
+ vPortFree( pxQueue );
+ }
+ #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ {
+ /* The queue could have been allocated statically or dynamically, so
+ check before attempting to free the memory. */
+ if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
+ {
+ vPortFree( pxQueue );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #else
+ {
+ /* The queue must have been statically allocated, so is not going to be
+ deleted. Avoid compiler warnings about the unused parameter. */
+ ( void ) pxQueue;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
/*-----------------------------------------------------------*/
@@ -2263,7 +2402,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
#endif /* configUSE_TIMERS */
/*-----------------------------------------------------------*/
-#if ( configUSE_QUEUE_SETS == 1 )
+#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
{
diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c
index 3cde3bf13..b79d3a98b 100644
--- a/components/freertos/tasks.c
+++ b/components/freertos/tasks.c
@@ -77,6 +77,7 @@ task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "rom/ets_sys.h"
+#include "esp_newlib.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
@@ -85,7 +86,6 @@ task.h is included from an application file. */
#include "StackMacros.h"
#include "portmacro.h"
#include "semphr.h"
-#include "sys/reent.h"
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
@@ -140,6 +140,26 @@ typedef enum
eNotified
} eNotifyValue;
+/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
+dynamically allocated RAM, in which case when any task is deleted it is known
+that both the task's stack and TCB need to be freed. Sometimes the
+FreeRTOSConfig.h settings only allow a task to be created using statically
+allocated RAM, in which case when any task is deleted it is known that neither
+the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
+settings allow a task to be created using either statically or dynamically
+allocated RAM, in which case a member of the TCB is used to record whether the
+stack and/or TCB were allocated statically or dynamically, so when a task is
+deleted the RAM that was allocated dynamically is freed again and no attempt is
+made to free the RAM that was allocated statically.
+tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
+task to be created using either statically or dynamically allocated RAM. Note
+that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
+a statically allocated stack and a dynamically allocated TCB. */
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
+#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
+#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
+#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
+
/*
* Task control block. A task control block (TCB) is allocated for each task,
* and stores task state information, including a pointer to the task's context
@@ -151,7 +171,6 @@ typedef struct tskTaskControlBlock
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
- BaseType_t xUsingStaticallyAllocatedStack; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */
#endif
ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
@@ -211,6 +230,12 @@ typedef struct tskTaskControlBlock
volatile eNotifyValue eNotifyState;
#endif
+ /* See the comments above the definition of
+ tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
+ #endif
+
} tskTCB;
/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
@@ -236,7 +261,7 @@ PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
-PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
+PRIVILEGED_DATA static List_t xPendingReadyList[ portNUM_PROCESSORS ]; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
#if ( INCLUDE_vTaskDelete == 1 )
@@ -263,7 +288,7 @@ PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
+PRIVILEGED_DATA static volatile BaseType_t xYieldPending[portNUM_PROCESSORS] = {pdFALSE};
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY;
@@ -417,6 +442,9 @@ count overflows. */
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
/*-----------------------------------------------------------*/
+
+#define tskCAN_RUN_HERE( cpuid ) ( cpuid==xPortGetCoreID() || cpuid==tskNO_AFFINITY )
+
/*
* Several functions take an TaskHandle_t parameter that can optionally be NULL,
* where NULL is used to indicate that the handle of the currently executing
@@ -456,12 +484,6 @@ to its original value when it is released. */
/* File private functions. --------------------------------*/
-/*
- * Utility to ready a TCB for a given task. Mainly just copies the parameters
- * into the TCB structure.
- */
-static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth, const BaseType_t xCoreID ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-
/**
* Utility task that simply returns pdTRUE if the task referenced by xTask is
* currently in the Suspended state, or pdFALSE if the task referenced by xTask
@@ -516,12 +538,6 @@ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
*/
static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
-/*
- * Allocates memory from the heap for a TCB and associated stack. Checks the
- * allocation was successful.
- */
-static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
-
/*
* Fills an TaskStatus_t structure with information on each task that is
* referenced from the pxList list (which may be a ready list, a delayed list,
@@ -578,120 +594,481 @@ static void prvResetNextTaskUnblockTime( void );
#endif
+/*
+ * Called after a Task_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask,
+ TCB_t *pxNewTCB,
+ const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+
+/*
+ * Called after a new task has been created and initialised to place the task
+ * under the control of the scheduler.
+ */
+static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, const BaseType_t xCoreID ) PRIVILEGED_FUNCTION;
+
+
/*-----------------------------------------------------------*/
-BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+/*
+ * This routine tries to send an interrupt to another core if needed to make it execute a task
+ * of higher priority. We try to figure out if needed first by inspecting the pxTCB of the
+ * other CPU first. Specifically for Xtensa, we can do this because pxTCB is an atomic pointer. It
+ * is possible that it is inaccurate because the other CPU just did a task switch, but in that case
+ * at most a superfluous interrupt is generated.
+*/
+void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority )
{
-BaseType_t xReturn;
-TCB_t * pxNewTCB;
-StackType_t *pxTopOfStack;
-BaseType_t i;
- configASSERT( pxTaskCode );
- configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
- configASSERT( (xCoreID>=0 && xCoreIDuxPriority < uxPriority ) {
+ vPortYieldOtherCore( xCoreID );
+ }
+ }
+ else
{
- #if( portUSING_MPU_WRAPPERS == 1 )
- /* Should the task be created in privileged mode? */
- BaseType_t xRunPrivileged;
- if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
+ /* The task has no affinity. See if we can find a CPU to put it on.*/
+ for (i=0; iuxPriority < uxPriority)
{
- xRunPrivileged = pdTRUE;
+ vPortYieldOtherCore( i );
+ break;
}
- else
- {
- xRunPrivileged = pdFALSE;
- }
- uxPriority &= ~portPRIVILEGE_BIT;
+ }
+ }
+}
- if( puxStackBuffer != NULL )
- {
- /* The application provided its own stack. Note this so no
- attempt is made to delete the stack should that task be
- deleted. */
- pxNewTCB->xUsingStaticallyAllocatedStack = pdTRUE;
- }
- else
- {
- /* The stack was allocated dynamically. Note this so it can be
- deleted again if the task is deleted. */
- pxNewTCB->xUsingStaticallyAllocatedStack = pdFALSE;
- }
- #endif /* portUSING_MPU_WRAPPERS == 1 */
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
- /* Calculate the top of stack address. This depends on whether the
- stack grows from high memory to low (as per the 80x86) or vice versa.
- portSTACK_GROWTH is used to make the result positive or negative as
- required by the port. */
- #if( portSTACK_GROWTH < 0 )
+ TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ StackType_t * const puxStackBuffer,
+ StaticTask_t * const pxTaskBuffer,
+ const BaseType_t xCoreID )
+ {
+ TCB_t *pxNewTCB;
+ TaskHandle_t xReturn;
+
+ configASSERT( puxStackBuffer != NULL );
+ configASSERT( pxTaskBuffer != NULL );
+ configASSERT( (xCoreID>=0 && xCoreIDpxStack + ( usStackDepth - ( uint16_t ) 1 );
- pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
+ /* The memory used for the task's TCB and stack are passed into this
+ function - use them. */
+ pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+ pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
- /* Check the alignment of the calculated top of stack is correct. */
- configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ task was created statically in case the task is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID );
+ prvAddNewTaskToReadyList( pxNewTCB, pxTaskCode, xCoreID );
+ }
+ else
+ {
+ xReturn = NULL;
+ }
+
+ return xReturn;
+ }
+
+#endif /* SUPPORT_STATIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( portUSING_MPU_WRAPPERS == 1 )
+
+ BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+ {
+ TCB_t *pxNewTCB;
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+ configASSERT( pxTaskDefinition->puxStackBuffer );
+
+ if( pxTaskDefinition->puxStackBuffer != NULL )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends
+ on the implementation of the port malloc function and whether or
+ not static allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+ if( pxNewTCB != NULL )
+ {
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+ /* Tasks can be created statically or dynamically, so note
+ this task had a statically allocated stack in case it is
+ later deleted. The TCB was allocated dynamically. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
+
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
+ pxTaskDefinition->pcName,
+ ( uint32_t ) pxTaskDefinition->usStackDepth,
+ pxTaskDefinition->pvParameters,
+ pxTaskDefinition->uxPriority,
+ pxCreatedTask, pxNewTCB,
+ pxTaskDefinition->xRegions,
+ tskNO_AFFINITY );
+
+ prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY );
+ xReturn = pdPASS;
+ }
+ }
+
+ return xReturn;
+ }
+
+#endif /* portUSING_MPU_WRAPPERS */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
+ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint16_t usStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask,
+ const BaseType_t xCoreID )
+ {
+ TCB_t *pxNewTCB;
+ BaseType_t xReturn;
+
+ /* If the stack grows down then allocate the stack then the TCB so the stack
+ does not grow into the TCB. Likewise if the stack grows up then allocate
+ the TCB then the stack. */
+ #if( portSTACK_GROWTH > 0 )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends on
+ the implementation of the port malloc function and whether or not static
+ allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+ if( pxNewTCB != NULL )
+ {
+ /* Allocate space for the stack used by the task being created.
+ The base of the stack memory stored in the TCB so the task can
+ be deleted later if required. */
+ pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+ if( pxNewTCB->pxStack == NULL )
+ {
+ /* Could not allocate the stack. Delete the allocated TCB. */
+ vPortFree( pxNewTCB );
+ pxNewTCB = NULL;
+ }
+ }
}
#else /* portSTACK_GROWTH */
{
- pxTopOfStack = pxNewTCB->pxStack;
+ StackType_t *pxStack;
- /* Check the alignment of the stack buffer is correct. */
- configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ /* Allocate space for the stack used by the task being created. */
+ pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
- /* If we want to use stack checking on architectures that use
- a positive stack growth direction then we also need to store the
- other extreme of the stack space. */
- pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
+ if( pxStack != NULL )
+ {
+ /* Allocate space for the TCB. */
+ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
+
+ if( pxNewTCB != NULL )
+ {
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxStack;
+ }
+ else
+ {
+ /* The stack cannot be used as the TCB was not created. Free
+ it again. */
+ vPortFree( pxStack );
+ }
+ }
+ else
+ {
+ pxNewTCB = NULL;
+ }
}
#endif /* portSTACK_GROWTH */
- /* Setup the newly allocated TCB with the initial state of the task. */
- prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth, xCoreID );
+ if( pxNewTCB != NULL )
+ {
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ task was created dynamically in case it is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* configSUPPORT_STATIC_ALLOCATION */
- /* Initialize the TCB stack to look as if the task was already running,
- but had been interrupted by the scheduler. The return address is set
- to the start of the task function. Once the stack has been initialised
- the top of stack variable is updated. */
- #if( portUSING_MPU_WRAPPERS == 1 )
- {
- pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL, xCoreID );
+ prvAddNewTaskToReadyList( pxNewTCB, pxTaskCode, xCoreID );
+ xReturn = pdPASS;
}
- #else /* portUSING_MPU_WRAPPERS */
+ else
{
- pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
- #endif /* portUSING_MPU_WRAPPERS */
- if( ( void * ) pxCreatedTask != NULL )
+ return xReturn;
+ }
+
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+ const char * const pcName,
+ const uint32_t ulStackDepth,
+ void * const pvParameters,
+ UBaseType_t uxPriority,
+ TaskHandle_t * const pxCreatedTask,
+ TCB_t *pxNewTCB,
+ const MemoryRegion_t * const xRegions, const BaseType_t xCoreID ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+{
+StackType_t *pxTopOfStack;
+UBaseType_t x;
+
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ /* Should the task be created in privileged mode? */
+ BaseType_t xRunPrivileged;
+ if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
{
- /* Pass the TCB out - in an anonymous way. The calling function/
- task can use this as a handle to delete the task later if
- required.*/
- *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
+ xRunPrivileged = pdTRUE;
+ }
+ else
+ {
+ xRunPrivileged = pdFALSE;
+ }
+ uxPriority &= ~portPRIVILEGE_BIT;
+ #endif /* portUSING_MPU_WRAPPERS == 1 */
+
+ /* Avoid dependency on memset() if it is not required. */
+ #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+ {
+ /* Fill the stack with a known value to assist debugging. */
+ ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
+ }
+ #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
+
+ /* Calculate the top of stack address. This depends on whether the stack
+ grows from high memory to low (as per the 80x86) or vice versa.
+ portSTACK_GROWTH is used to make the result positive or negative as required
+ by the port. */
+ #if( portSTACK_GROWTH < 0 )
+ {
+ pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
+ pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
+
+ /* Check the alignment of the calculated top of stack is correct. */
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+ }
+ #else /* portSTACK_GROWTH */
+ {
+ pxTopOfStack = pxNewTCB->pxStack;
+
+ /* Check the alignment of the stack buffer is correct. */
+ configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+
+ /* The other extreme of the stack space is required if stack checking is
+ performed. */
+ pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
+ }
+ #endif /* portSTACK_GROWTH */
+
+ /* Store the task name in the TCB. */
+ for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
+ {
+ pxNewTCB->pcTaskName[ x ] = pcName[ x ];
+
+ /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
+ configMAX_TASK_NAME_LEN characters just in case the memory after the
+ string is not accessible (extremely unlikely). */
+ if( pcName[ x ] == 0x00 )
+ {
+ break;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
+ }
- /* Ensure interrupts don't access the task lists while they are being
- updated. */
- taskENTER_CRITICAL(&xTaskQueueMutex);
+ /* Ensure the name string is terminated in the case that the string length
+ was greater or equal to configMAX_TASK_NAME_LEN. */
+ pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
+
+ /* This is used as an array index so must ensure it's not too large. First
+ remove the privilege bit if one is present. */
+ if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
+ {
+ uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+
+ pxNewTCB->uxPriority = uxPriority;
+ pxNewTCB->xCoreID = xCoreID;
+ #if ( configUSE_MUTEXES == 1 )
+ {
+ pxNewTCB->uxBasePriority = uxPriority;
+ pxNewTCB->uxMutexesHeld = 0;
+ }
+ #endif /* configUSE_MUTEXES */
+
+ vListInitialiseItem( &( pxNewTCB->xGenericListItem ) );
+ vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
+
+ /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
+ back to the containing TCB from a generic item in a list. */
+ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xGenericListItem ), pxNewTCB );
+
+ /* Event lists are always in priority order. */
+ listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+ listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
+
+ #if ( portCRITICAL_NESTING_IN_TCB == 1 )
+ {
+ pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
+ }
+ #endif /* portCRITICAL_NESTING_IN_TCB */
+
+ #if ( configUSE_APPLICATION_TASK_TAG == 1 )
+ {
+ pxNewTCB->pxTaskTag = NULL;
+ }
+ #endif /* configUSE_APPLICATION_TASK_TAG */
+
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
+ {
+ pxNewTCB->ulRunTimeCounter = 0UL;
+ }
+ #endif /* configGENERATE_RUN_TIME_STATS */
+
+ #if ( portUSING_MPU_WRAPPERS == 1 )
+ {
+ vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
+ }
+ #else
+ {
+ /* Avoid compiler warning about unreferenced parameter. */
+ ( void ) xRegions;
+ }
+ #endif
+
+ #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
+ {
+ for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
{
- uxCurrentNumberOfTasks++;
+ pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
+ #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1)
+ pxNewTCB->pvThreadLocalStoragePointersDelCallback[ x ] = NULL;
+ #endif
+ }
+ }
+ #endif
+
+ #if ( configUSE_TASK_NOTIFICATIONS == 1 )
+ {
+ pxNewTCB->ulNotifiedValue = 0;
+ pxNewTCB->eNotifyState = eNotWaitingNotification;
+ }
+ #endif
+
+ #if ( configUSE_NEWLIB_REENTRANT == 1 )
+ {
+ /* Initialise this task's Newlib reent structure. */
+ esp_reent_init(&pxNewTCB->xNewLib_reent);
+ }
+ #endif
+
+ #if( INCLUDE_xTaskAbortDelay == 1 )
+ {
+ pxNewTCB->ucDelayAborted = pdFALSE;
+ }
+ #endif
+
+ /* Initialize the TCB stack to look as if the task was already running,
+ but had been interrupted by the scheduler. The return address is set
+ to the start of the task function. Once the stack has been initialised
+ the top of stack variable is updated. */
+ #if( portUSING_MPU_WRAPPERS == 1 )
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
+ }
+ #else /* portUSING_MPU_WRAPPERS */
+ {
+ pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
+ }
+ #endif /* portUSING_MPU_WRAPPERS */
+
+ if( ( void * ) pxCreatedTask != NULL )
+ {
+ /* Pass the handle out in an anonymous way. The handle can be used to
+ change the created task's priority, delete the created task, etc.*/
+ *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, const BaseType_t xCoreID )
+{
+ BaseType_t i;
+
+ /* Ensure interrupts don't access the task lists while the lists are being
+ updated. */
+ taskENTER_CRITICAL(&xTaskQueueMutex);
+ {
+ uxCurrentNumberOfTasks++;
+ if( pxCurrentTCB[ xPortGetCoreID() ] == NULL )
+ {
+ /* There are no other tasks, or all the other tasks are in
+ the suspended state - make this the current task. */
+ pxCurrentTCB[ xPortGetCoreID() ] = pxNewTCB;
+
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
+#if portFIRST_TASK_HOOK
+ if ( xPortGetCoreID() == 0 ) {
+ vPortFirstTaskHook(pxTaskCode);
+ }
+#endif /* configFIRST_TASK_HOOK */
/* This is the first task to be created so do the preliminary
initialisation required. We will not recover if this call
fails, but we will report the failure. */
prvInitialiseTaskLists();
}
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ else
+ {
+ /* If the scheduler is not already running, make this task the
+ current task if it is the highest priority task to be created
+ so far. */
if( xSchedulerRunning == pdFALSE )
{
/* Scheduler isn't running yet. We need to determine on which CPU to run this task. */
@@ -701,14 +1078,8 @@ BaseType_t i;
if (xCoreID == tskNO_AFFINITY || xCoreID == i)
{
/* Schedule if nothing is scheduled yet, or overwrite a task of lower prio. */
- if ( pxCurrentTCB[i] == NULL || pxCurrentTCB[i]->uxPriority <= uxPriority )
+ if ( pxCurrentTCB[i] == NULL || pxCurrentTCB[i]->uxPriority <= pxNewTCB->uxPriority )
{
-#if portFIRST_TASK_HOOK
- if ( i == 0) {
- vPortFirstTaskHook(pxTaskCode);
- }
-#endif /* configFIRST_TASK_HOOK */
-
pxCurrentTCB[i] = pxNewTCB;
break;
}
@@ -719,44 +1090,45 @@ BaseType_t i;
{
mtCOVERAGE_TEST_MARKER();
}
-
- uxTaskNumber++;
-
- #if ( configUSE_TRACE_FACILITY == 1 )
- {
- /* Add a counter into the TCB for tracing only. */
- pxNewTCB->uxTCBNumber = uxTaskNumber;
- }
- #endif /* configUSE_TRACE_FACILITY */
- traceTASK_CREATE( pxNewTCB );
-
- prvAddTaskToReadyList( pxNewTCB );
-
- xReturn = pdPASS;
- portSETUP_TCB( pxNewTCB );
}
- taskEXIT_CRITICAL(&xTaskQueueMutex);
- }
- else
- {
- xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
- traceTASK_CREATE_FAILED();
- }
- if( xReturn == pdPASS )
+ uxTaskNumber++;
+
+ #if ( configUSE_TRACE_FACILITY == 1 )
+ {
+ /* Add a counter into the TCB for tracing only. */
+ pxNewTCB->uxTCBNumber = uxTaskNumber;
+ }
+ #endif /* configUSE_TRACE_FACILITY */
+ traceTASK_CREATE( pxNewTCB );
+
+ prvAddTaskToReadyList( pxNewTCB );
+
+ portSETUP_TCB( pxNewTCB );
+ }
+ taskEXIT_CRITICAL(&xTaskQueueMutex);
+
+ if( xSchedulerRunning != pdFALSE )
{
- if( xSchedulerRunning != pdFALSE )
+ /* Scheduler is running. If the created task is of a higher priority than an executing task
+ then it should run now.
+ ToDo: This only works for the current core. If a task is scheduled on an other processor,
+ the other processor will keep running the task it's working on, and only switch to the newer
+ task on a timer interrupt. */
+ //No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
+ if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < pxNewTCB->uxPriority )
{
/* Scheduler is running. If the created task is of a higher priority than an executing task
then it should run now.
- ToDo: This only works for the current core. If a task is scheduled on an other processor,
- the other processor will keep running the task it's working on, and only switch to the newer
- task on a timer interrupt. */
- //No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
- if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < uxPriority )
+ No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
+ */
+ if( tskCAN_RUN_HERE( xCoreID ) && pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < pxNewTCB->uxPriority )
{
taskYIELD_IF_USING_PREEMPTION();
}
+ else if( xCoreID != xPortGetCoreID() ) {
+ taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority);
+ }
else
{
mtCOVERAGE_TEST_MARKER();
@@ -767,8 +1139,10 @@ BaseType_t i;
mtCOVERAGE_TEST_MARKER();
}
}
-
- return xReturn;
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
}
/*-----------------------------------------------------------*/
@@ -834,7 +1208,7 @@ BaseType_t i;
after which it is not possible to yield away from this task -
hence xYieldPending is used to latch that a context switch is
required. */
- portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
+ portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending[xPortGetCoreID()] );
portYIELD_WITHIN_API();
}
else
@@ -1188,10 +1562,14 @@ BaseType_t i;
/* The priority of a task other than the currently
running task is being raised. Is the priority being
raised above that of the running task? */
- if( uxNewPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if ( tskCAN_RUN_HERE(pxTCB->xCoreID) && uxNewPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
xYieldRequired = pdTRUE;
}
+ else if ( pxTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxTCB->xCoreID, uxNewPriority );
+ }
else
{
mtCOVERAGE_TEST_MARKER();
@@ -1413,7 +1791,7 @@ BaseType_t i;
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
- if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
+ if( listIS_CONTAINED_WITHIN( &xPendingReadyList[ xPortGetCoreID() ], &( pxTCB->xEventListItem ) ) == pdFALSE )
{
/* Is it in the suspended list because it is in the Suspended
state, or because is is blocked with no timeout? */
@@ -1470,13 +1848,17 @@ BaseType_t i;
prvAddTaskToReadyList( pxTCB );
/* We may have just resumed a higher priority task. */
- if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
/* This yield may not cause the task just resumed to run,
but will leave the lists in the correct state for the
next yield. */
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex);
}
+ else if( pxTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority );
+ }
else
{
mtCOVERAGE_TEST_MARKER();
@@ -1501,7 +1883,6 @@ BaseType_t i;
#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
-/* ToDo: Make this multicore-compatible. */
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
{
BaseType_t xYieldRequired = pdFALSE;
@@ -1521,24 +1902,28 @@ BaseType_t i;
{
/* Ready lists can be accessed so move the task from the
suspended list to the ready list directly. */
- if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
+ prvAddTaskToReadyList( pxTCB );
+
+ if( tskCAN_RUN_HERE( pxTCB->xCoreID ) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
xYieldRequired = pdTRUE;
}
+ else if ( pxTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority);
+ }
else
{
mtCOVERAGE_TEST_MARKER();
}
-
- ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
- prvAddTaskToReadyList( pxTCB );
}
else
{
/* The delayed or ready lists cannot be accessed so the task
is held in the pending ready list until the scheduler is
unsuspended. */
- vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ vListInsertEnd( &( xPendingReadyList[ xPortGetCoreID() ] ), &( pxTCB->xEventListItem ) );
}
}
else
@@ -1723,18 +2108,19 @@ BaseType_t xAlreadyYielded = pdFALSE;
{
/* Move any readied tasks from the pending list into the
appropriate ready list. */
- while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
+ while( listLIST_IS_EMPTY( &xPendingReadyList[ xPortGetCoreID() ] ) == pdFALSE )
{
- pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
+ pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList[ xPortGetCoreID() ] ) );
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxTCB );
/* If the moved task has a priority higher than the current
task then a yield must be performed. */
- if( pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if ( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
- xYieldPending = pdTRUE;
+ /* We can schedule the awoken task on this CPU. */
+ xYieldPending[xPortGetCoreID()] = pdTRUE;
break;
}
else
@@ -1753,7 +2139,7 @@ BaseType_t xAlreadyYielded = pdFALSE;
{
if( xTaskIncrementTick() != pdFALSE )
{
- xYieldPending = pdTRUE;
+ xYieldPending[ xPortGetCoreID() ] = pdTRUE;
}
else
{
@@ -1767,7 +2153,7 @@ BaseType_t xAlreadyYielded = pdFALSE;
mtCOVERAGE_TEST_MARKER();
}
- if( xYieldPending == pdTRUE )
+ if( xYieldPending[ xPortGetCoreID() ] == pdTRUE )
{
#if( configUSE_PREEMPTION != 0 )
{
@@ -1832,7 +2218,6 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
/*-----------------------------------------------------------*/
#if ( INCLUDE_pcTaskGetTaskName == 1 )
-
char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{
TCB_t *pxTCB;
@@ -1975,6 +2360,23 @@ BaseType_t xSwitchRequired = pdFALSE;
We can't really calculate what we need, that's done on core 0... just assume we need a switch.
ToDo: Make this more intelligent? -- JD
*/
+ //We do need the tick hook to satisfy the int watchdog.
+ #if ( configUSE_TICK_HOOK == 1 )
+ {
+ /* Guard against the tick hook being called when the pended tick
+ count is being unwound (when the scheduler is being unlocked). */
+ if( ( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) || uxPendedTicks == ( UBaseType_t ) 0U )
+ {
+ vApplicationTickHook();
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ }
+ #endif /* configUSE_TICK_HOOK */
+
+
return pdTRUE;
}
@@ -2135,7 +2537,7 @@ BaseType_t xSwitchRequired = pdFALSE;
#if ( configUSE_PREEMPTION == 1 )
{
- if( xYieldPending != pdFALSE )
+ if( xYieldPending [ xPortGetCoreID() ] != pdFALSE )
{
xSwitchRequired = pdTRUE;
}
@@ -2251,11 +2653,11 @@ void vTaskSwitchContext( void )
{
/* The scheduler is currently suspended - do not allow a context
switch. */
- xYieldPending = pdTRUE;
+ xYieldPending[ xPortGetCoreID() ] = pdTRUE;
}
else
{
- xYieldPending = pdFALSE;
+ xYieldPending[ xPortGetCoreID() ] = pdFALSE;
traceTASK_SWITCHED_OUT();
#if ( configGENERATE_RUN_TIME_STATS == 1 )
@@ -2606,11 +3008,11 @@ BaseType_t xReturn;
/* The delayed and ready lists cannot be accessed, so hold this task
pending until the scheduler is resumed. */
taskENTER_CRITICAL(&xTaskQueueMutex);
- vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
+ vListInsertEnd( &( xPendingReadyList[ xPortGetCoreID() ] ), &( pxUnblockedTCB->xEventListItem ) );
taskEXIT_CRITICAL(&xTaskQueueMutex);
}
- if( pxUnblockedTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
/* Return true if the task removed from the event list has a higher
priority than the calling task. This allows the calling task to know if
@@ -2619,7 +3021,12 @@ BaseType_t xReturn;
/* Mark that a yield is pending in case the user is not using the
"xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
- xYieldPending = pdTRUE;
+ xYieldPending[ xPortGetCoreID() ] = pdTRUE;
+ }
+ else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxUnblockedTCB->xCoreID, pxUnblockedTCB->uxPriority );
+ xReturn = pdFALSE;
}
else
{
@@ -2670,7 +3077,7 @@ BaseType_t xReturn;
( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
prvAddTaskToReadyList( pxUnblockedTCB );
- if( pxUnblockedTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
/* Return true if the task removed from the event list has
a higher priority than the calling task. This allows
@@ -2680,7 +3087,12 @@ BaseType_t xReturn;
/* Mark that a yield is pending in case the user is not using the
"xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
- xYieldPending = pdTRUE;
+ xYieldPending[ xPortGetCoreID() ] = pdTRUE;
+ }
+ else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxUnblockedTCB->xCoreID, pxUnblockedTCB->uxPriority );
+ xReturn = pdFALSE;
}
else
{
@@ -2751,7 +3163,7 @@ BaseType_t xReturn;
void vTaskMissedYield( void )
{
- xYieldPending = pdTRUE;
+ xYieldPending[ xPortGetCoreID() ] = pdTRUE;
}
/*-----------------------------------------------------------*/
@@ -2916,12 +3328,12 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
eSleepModeStatus eReturn = eStandardSleep;
taskENTER_CRITICAL(&xTaskQueueMutex);
- if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
+ if( listCURRENT_LIST_LENGTH( &xPendingReadyList[ xPortGetCoreID() ] ) != 0 )
{
/* A task was made ready while the scheduler was suspended. */
eReturn = eAbortSleep;
}
- else if( xYieldPending != pdFALSE )
+ else if( xYieldPending[ xPortGetCoreID() ] != pdFALSE )
{
/* A yield was pended while the scheduler was suspended. */
eReturn = eAbortSleep;
@@ -2955,120 +3367,6 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
-static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth, const BaseType_t xCoreID ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-{
-UBaseType_t x;
-
- /* Store the task name in the TCB. */
- for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
- {
- pxTCB->pcTaskName[ x ] = pcName[ x ];
-
- /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
- configMAX_TASK_NAME_LEN characters just in case the memory after the
- string is not accessible (extremely unlikely). */
- if( pcName[ x ] == 0x00 )
- {
- break;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- }
-
- /* Ensure the name string is terminated in the case that the string length
- was greater or equal to configMAX_TASK_NAME_LEN. */
- pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
-
- /* This is used as an array index so must ensure it's not too large. First
- remove the privilege bit if one is present. */
- if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
- {
- uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
-
- pxTCB->uxPriority = uxPriority;
- pxTCB->xCoreID = xCoreID;
- #if ( configUSE_MUTEXES == 1 )
- {
- pxTCB->uxBasePriority = uxPriority;
- pxTCB->uxMutexesHeld = 0;
- }
- #endif /* configUSE_MUTEXES */
-
- vListInitialiseItem( &( pxTCB->xGenericListItem ) );
- vListInitialiseItem( &( pxTCB->xEventListItem ) );
-
- /* Set the pxTCB as a link back from the ListItem_t. This is so we can get
- back to the containing TCB from a generic item in a list. */
- listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
-
- /* Event lists are always in priority order. */
- listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
- listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
-
- #if ( portCRITICAL_NESTING_IN_TCB == 1 )
- {
- pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
- }
- #endif /* portCRITICAL_NESTING_IN_TCB */
-
- #if ( configUSE_APPLICATION_TASK_TAG == 1 )
- {
- pxTCB->pxTaskTag = NULL;
- }
- #endif /* configUSE_APPLICATION_TASK_TAG */
-
- #if ( configGENERATE_RUN_TIME_STATS == 1 )
- {
- pxTCB->ulRunTimeCounter = 0UL;
- }
- #endif /* configGENERATE_RUN_TIME_STATS */
-
- #if ( portUSING_MPU_WRAPPERS == 1 )
- {
- vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
- }
- #else /* portUSING_MPU_WRAPPERS */
- {
- ( void ) xRegions;
- ( void ) usStackDepth;
- }
- #endif /* portUSING_MPU_WRAPPERS */
-
- #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
- {
- for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
- {
- pxTCB->pvThreadLocalStoragePointers[ x ] = NULL;
- #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
- pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] = (TlsDeleteCallbackFunction_t)NULL;
- #endif
- }
- }
- #endif
-
-
- #if ( configUSE_TASK_NOTIFICATIONS == 1 )
- {
- pxTCB->ulNotifiedValue = 0;
- pxTCB->eNotifyState = eNotWaitingNotification;
- }
- #endif
-
- #if ( configUSE_NEWLIB_REENTRANT == 1 )
- {
- /* Initialise this task's Newlib reent structure. */
- _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
- }
- #endif /* configUSE_NEWLIB_REENTRANT */
-}
-/*-----------------------------------------------------------*/
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
@@ -3159,7 +3457,7 @@ UBaseType_t uxPriority;
vListInitialise( &xDelayedTaskList1 );
vListInitialise( &xDelayedTaskList2 );
- vListInitialise( &xPendingReadyList );
+ vListInitialise( &xPendingReadyList[ xPortGetCoreID() ] );
#if ( INCLUDE_vTaskDelete == 1 )
{
@@ -3264,81 +3562,6 @@ static void prvAddCurrentTaskToDelayedList( const BaseType_t xCoreID, const Tick
}
/*-----------------------------------------------------------*/
-static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
-{
-TCB_t *pxNewTCB;
-
- /* If the stack grows down then allocate the stack then the TCB so the stack
- does not grow into the TCB. Likewise if the stack grows up then allocate
- the TCB then the stack. */
- #if( portSTACK_GROWTH > 0 )
- {
- /* Allocate space for the TCB. Where the memory comes from depends on
- the implementation of the port malloc function. */
- pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
-
- if( pxNewTCB != NULL )
- {
- /* Allocate space for the stack used by the task being created.
- The base of the stack memory stored in the TCB so the task can
- be deleted later if required. */
- pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
-
- if( pxNewTCB->pxStack == NULL )
- {
- /* Could not allocate the stack. Delete the allocated TCB. */
- vPortFree( pxNewTCB );
- pxNewTCB = NULL;
- }
- }
- }
- #else /* portSTACK_GROWTH */
- {
- StackType_t *pxStack;
-
- /* Allocate space for the stack used by the task being created. */
- pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
-
- if( pxStack != NULL )
- {
- /* Allocate space for the TCB. Where the memory comes from depends
- on the implementation of the port malloc function. */
- pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
-
- if( pxNewTCB != NULL )
- {
- /* Store the stack location in the TCB. */
- pxNewTCB->pxStack = pxStack;
- }
- else
- {
- /* The stack cannot be used as the TCB was not created. Free it
- again. */
- vPortFree( pxStack );
- }
- }
- else
- {
- pxNewTCB = NULL;
- }
- }
- #endif /* portSTACK_GROWTH */
-
- if( pxNewTCB != NULL )
- {
- /* Avoid dependency on memset() if it is not required. */
- #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
- {
- /* Just to help debugging. */
- ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
- }
- #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
- }
-
- return pxNewTCB;
-}
-/*-----------------------------------------------------------*/
-
BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
{
TCB_t *pxTCB;
@@ -3487,8 +3710,6 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
#if ( INCLUDE_vTaskDelete == 1 )
- // TODO: move this to newlib component and provide a header file
- extern void _extra_cleanup_r(struct _reent* r);
static void prvDeleteTCB( TCB_t *pxTCB )
{
@@ -3501,27 +3722,44 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
to the task to free any memory allocated at the application level. */
#if ( configUSE_NEWLIB_REENTRANT == 1 )
{
- pxTCB->xNewLib_reent.__cleanup = &_extra_cleanup_r;
_reclaim_reent( &( pxTCB->xNewLib_reent ) );
}
#endif /* configUSE_NEWLIB_REENTRANT */
- #if( portUSING_MPU_WRAPPERS == 1 )
+ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
{
- /* Only free the stack if it was allocated dynamically in the first
- place. */
- if( pxTCB->xUsingStaticallyAllocatedStack == pdFALSE )
+ /* The task can only have been allocated dynamically - free both
+ the stack and TCB. */
+ vPortFreeAligned( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+ #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
+ {
+ /* The task could have been allocated statically or dynamically, so
+ check what was statically allocated before trying to free the
+ memory. */
+ if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
{
+ /* Both the stack and TCB were allocated dynamically, so both
+ must be freed. */
vPortFreeAligned( pxTCB->pxStack );
+ vPortFree( pxTCB );
+ }
+ else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
+ {
+ /* Only the stack was statically allocated, so the TCB is the
+ only memory that must be freed. */
+ vPortFree( pxTCB );
+ }
+ else
+ {
+ /* Neither the stack nor the TCB were allocated dynamically, so
+ nothing needs to be freed. */
+ configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
+ mtCOVERAGE_TEST_MARKER();
}
}
- #else
- {
- vPortFreeAligned( pxTCB->pxStack );
- }
- #endif
-
- vPortFree( pxTCB );
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
#endif /* INCLUDE_vTaskDelete */
@@ -3566,6 +3804,19 @@ TCB_t *pxTCB;
return xReturn;
}
+ TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid )
+ {
+ TaskHandle_t xReturn=NULL;
+
+ //Xtensa-specific: the pxCurrentPCB pointer is atomic so we shouldn't need a lock.
+ if (cpuid < portNUM_PROCESSORS) {
+ xReturn = pxCurrentTCB[ cpuid ];
+ }
+
+ return xReturn;
+ }
+
+
#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
/*-----------------------------------------------------------*/
@@ -3597,12 +3848,6 @@ TCB_t *pxTCB;
#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
/*-----------------------------------------------------------*/
-/*
-ToDo: Mutexes haven't been tested or adapted to multicore at all.
-
-In fact, nothing below this line has/is.
-*/
-
#if ( configUSE_MUTEXES == 1 )
void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
@@ -3755,9 +4000,8 @@ In fact, nothing below this line has/is.
/* Gotcha (which seems to be deliberate in FreeRTOS, according to
http://www.freertos.org/FreeRTOS_Support_Forum_Archive/December_2012/freertos_PIC32_Bug_-_vTaskEnterCritical_6400806.html
-) is that calling vTaskEnterCritical followed by vTaskExitCritical will leave the interrupts DISABLED! Re-enabling the
-scheduler will re-enable the interrupts instead. */
-
+) is that calling vTaskEnterCritical followed by vTaskExitCritical will leave the interrupts DISABLED when the scheduler
+is not running. Re-enabling the scheduler will re-enable the interrupts instead. */
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
@@ -3930,7 +4174,9 @@ scheduler will re-enable the interrupts instead. */
function is executing. */
uxArraySize = uxCurrentNumberOfTasks;
- /* Allocate an array index for each task. */
+ /* Allocate an array index for each task. NOTE! if
+ configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
+ equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL )
@@ -3970,7 +4216,8 @@ scheduler will re-enable the interrupts instead. */
pcWriteBuffer += strlen( pcWriteBuffer );
}
- /* Free the array again. */
+ /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
+ is 0 then vPortFree() will be #defined to nothing. */
vPortFree( pxTaskStatusArray );
}
else
@@ -4029,7 +4276,9 @@ scheduler will re-enable the interrupts instead. */
function is executing. */
uxArraySize = uxCurrentNumberOfTasks;
- /* Allocate an array index for each task. */
+ /* Allocate an array index for each task. NOTE! If
+ configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
+ equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL )
@@ -4095,7 +4344,8 @@ scheduler will re-enable the interrupts instead. */
mtCOVERAGE_TEST_MARKER();
}
- /* Free the array again. */
+ /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
+ is 0 then vPortFree() will be #defined to nothing. */
vPortFree( pxTaskStatusArray );
}
else
@@ -4435,12 +4685,16 @@ TickType_t uxReturn;
/* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
- if( pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
/* The notified task has a priority above the currently
executing task so a yield is required. */
portYIELD_WITHIN_API();
}
+ else if ( pxTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE(pxTCB->xCoreID, pxTCB->uxPriority);
+ }
else
{
mtCOVERAGE_TEST_MARKER();
@@ -4528,10 +4782,10 @@ TickType_t uxReturn;
{
/* The delayed and ready lists cannot be accessed, so hold
this task pending until the scheduler is resumed. */
- vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ vListInsertEnd( &( xPendingReadyList[ xPortGetCoreID() ] ), &( pxTCB->xEventListItem ) );
}
- if( pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+ if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
/* The notified task has a priority above the currently
executing task so a yield is required. */
@@ -4540,6 +4794,10 @@ TickType_t uxReturn;
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
+ else if ( pxTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority );
+ }
else
{
mtCOVERAGE_TEST_MARKER();
@@ -4592,10 +4850,10 @@ TickType_t uxReturn;
{
/* The delayed and ready lists cannot be accessed, so hold
this task pending until the scheduler is resumed. */
- vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
+ vListInsertEnd( &( xPendingReadyList[ xPortGetCoreID() ] ), &( pxTCB->xEventListItem ) );
}
-
- if( pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
+
+ if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
/* The notified task has a priority above the currently
executing task so a yield is required. */
@@ -4604,6 +4862,10 @@ TickType_t uxReturn;
*pxHigherPriorityTaskWoken = pdTRUE;
}
}
+ else if ( pxTCB->xCoreID != xPortGetCoreID() )
+ {
+ taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority );
+ }
else
{
mtCOVERAGE_TEST_MARKER();
diff --git a/components/freertos/xtensa_vectors.S b/components/freertos/xtensa_vectors.S
index f0d874a59..7cf70f003 100644
--- a/components/freertos/xtensa_vectors.S
+++ b/components/freertos/xtensa_vectors.S
@@ -91,12 +91,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#include "xtensa_rtos.h"
-
+#include "esp_panic.h"
+#include "sdkconfig.h"
/*
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
Please change this when the tcb structure is changed
*/
-#define TASKTCB_XCOREID_OFFSET (0x3C+configMAX_TASK_NAME_LEN+3)&~3
+#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
.extern pxCurrentTCB
/* Enable stack backtrace across exception/interrupt - see below */
@@ -302,12 +303,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
.section .iram1,"ax"
- .global panicHandler
+ .global panicHandler
.global _xt_panic
.type _xt_panic,@function
.align 4
- .literal_position
+ .literal_position
.align 4
_xt_panic:
@@ -339,45 +340,45 @@ _xt_panic:
rsr a0, EXCSAVE_1 /* save interruptee's a0 */
s32i a0, sp, XT_STK_A0
- /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
+ /* Set up PS for C, disable all interrupts, and clear EXCM. */
+ movi a0, PS_INTLEVEL(7) | PS_UM | PS_WOE
wsr a0, PS
- //Call panic handler
- mov a2,sp
- call4 panicHandler
+ //Call panic handler
+ mov a6,sp
+ call4 panicHandler
1: j 1b /* loop infinitely */
- retw
+ retw
- .align 4
+ .align 4
//Call using call0. Prints the hex char in a2. Kills a3, a4, a5
panic_print_hex:
- movi a3,0x60000000
- movi a4,8
+ movi a3,0x60000000
+ movi a4,8
panic_print_hex_loop:
- l32i a5, a3, 0x1c
- extui a5, a5, 16, 8
- bgei a5,64,panic_print_hex_loop
+ l32i a5, a3, 0x1c
+ extui a5, a5, 16, 8
+ bgei a5,64,panic_print_hex_loop
- srli a5,a2,28
- bgei a5,10,panic_print_hex_a
- addi a5,a5,'0'
- j panic_print_hex_ok
+ srli a5,a2,28
+ bgei a5,10,panic_print_hex_a
+ addi a5,a5,'0'
+ j panic_print_hex_ok
panic_print_hex_a:
- addi a5,a5,'A'-10
+ addi a5,a5,'A'-10
panic_print_hex_ok:
- s32i a5,a3,0
- slli a2,a2,4
-
- addi a4,a4,-1
- bnei a4,0,panic_print_hex_loop
- movi a5,' '
- s32i a5,a3,0
+ s32i a5,a3,0
+ slli a2,a2,4
+
+ addi a4,a4,-1
+ bnei a4,0,panic_print_hex_loop
+ movi a5,' '
+ s32i a5,a3,0
- ret
+ ret
@@ -462,6 +463,8 @@ _DebugExceptionVector:
jx a3
#else
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
+ movi a0,PANIC_RSN_DEBUGEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* does not return */
rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
#endif
@@ -489,6 +492,8 @@ _DoubleExceptionVector:
#if XCHAL_HAVE_DEBUG
break 1, 4 /* unhandled double exception */
#endif
+ movi a0,PANIC_RSN_DOUBLEEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* does not return */
rfde /* make a0 point here not later */
@@ -522,6 +527,8 @@ _xt_kernel_exc:
#if XCHAL_HAVE_DEBUG
break 1, 0 /* unhandled kernel exception */
#endif
+ movi a0,PANIC_RSN_KERNELEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* does not return */
rfe /* make a0 point here not there */
@@ -904,19 +911,16 @@ _xt_coproc_exc:
core we're running on now. */
movi a2, pxCurrentTCB
getcoreid a3
- slli a3, a3, 2
- add a2, a2, a3
+ addx4 a2, a3, a2
l32i a2, a2, 0 /* a2 = start of pxCurrentTCB[cpuid] */
addi a2, a2, TASKTCB_XCOREID_OFFSET /* offset to xCoreID in tcb struct */
- getcoreid a3
s32i a3, a2, 0 /* store current cpuid */
- /* Grab correct xt_coproc_owner_sa for this core */
- getcoreid a2
- movi a3, XCHAL_CP_MAX << 2
- mull a2, a2, a3
+ /* Grab correct xt_coproc_owner_sa for this core */
+ movi a2, XCHAL_CP_MAX << 2
+ mull a2, a2, a3
movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
- add a3, a3, a2
+ add a3, a3, a2
extui a2, a0, 0, 16 /* coprocessor bitmask portion */
or a4, a4, a2 /* a4 = CPENABLE | (1 << n) */
@@ -1027,6 +1031,8 @@ _xt_coproc_exc:
#if XCHAL_HAVE_DEBUG
break 1, 1 /* unhandled user exception */
#endif
+ movi a0,PANIC_RSN_COPROCEXCEPTION
+ wsr a0,EXCCAUSE
call0 _xt_panic /* not in a thread (invalid) */
/* never returns */
@@ -1610,6 +1616,28 @@ _xt_highint4:
ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
*/
+
+
+ /* On the ESP32, this level is used for the INT_WDT handler. If that triggers, the program is stuck with interrupts
+ off and the CPU should panic. */
+ rsr a0, EXCSAVE_4
+ wsr a0, EXCSAVE_1 /* panic handler reads this register */
+ /* Set EXCCAUSE to reflect cause of the wdt int trigger */
+ movi a0,PANIC_RSN_INTWDT_CPU0
+ wsr a0,EXCCAUSE
+#if CONFIG_INT_WDT_CHECK_CPU1
+ /* Check if the cause is the app cpu failing to tick.*/
+ movi a0, int_wdt_app_cpu_ticked
+ l32i a0, a0, 0
+ bnez a0, 1f
+ /* It is. Modify cause. */
+ movi a0,PANIC_RSN_INTWDT_CPU1
+ wsr a0,EXCCAUSE
+1:
+#endif
+ call0 _xt_panic
+
+
.align 4
.L_xt_highint4_exit:
rsr a0, EXCSAVE_4 /* restore a0 */
diff --git a/components/freertos/xtensa_vectors.S-new b/components/freertos/xtensa_vectors.S-new
deleted file mode 100644
index 88349eee9..000000000
--- a/components/freertos/xtensa_vectors.S-new
+++ /dev/null
@@ -1,1915 +0,0 @@
-/*******************************************************************************
-Copyright (c) 2006-2015 Cadence Design Systems Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------------------------------------------------
-
- XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS
-
- Xtensa low level exception and interrupt vectors and handlers for an RTOS.
-
- Interrupt handlers and user exception handlers support interaction with
- the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and
- after user's specific interrupt handlers. These macros are defined in
- xtensa_.h to call suitable functions in a specific RTOS.
-
- Users can install application-specific interrupt handlers for low and
- medium level interrupts, by calling xt_set_interrupt_handler(). These
- handlers can be written in C, and must obey C calling convention. The
- handler table is indexed by the interrupt number. Each handler may be
- provided with an argument.
-
- Note that the system timer interrupt is handled specially, and is
- dispatched to the RTOS-specific handler. This timer cannot be hooked
- by application code.
-
- Optional hooks are also provided to install a handler per level at
- run-time, made available by compiling this source file with
- '-DXT_INTEXC_HOOKS' (useful for automated testing).
-
-!! This file is a template that usually needs to be modified to handle !!
-!! application specific interrupts. Search USER_EDIT for helpful comments !!
-!! on where to insert handlers and how to write them. !!
-
- Users can also install application-specific exception handlers in the
- same way, by calling xt_set_exception_handler(). One handler slot is
- provided for each exception type. Note that some exceptions are handled
- by the porting layer itself, and cannot be taken over by application
- code in this manner. These are the alloca, syscall, and coprocessor
- exceptions.
-
- The exception handlers can be written in C, and must follow C calling
- convention. Each handler is passed a pointer to an exception frame as
- its single argument. The exception frame is created on the stack, and
- holds the saved context of the thread that took the exception. If the
- handler returns, the context will be restored and the instruction that
- caused the exception will be retried. If the handler makes any changes
- to the saved state in the exception frame, the changes will be applied
- when restoring the context.
-
- Because Xtensa is a configurable architecture, this port supports all user
- generated configurations (except restrictions stated in the release notes).
- This is accomplished by conditional compilation using macros and functions
- defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
- Only the relevant parts of this file will be included in your RTOS build.
- For example, this file provides interrupt vector templates for all types and
- all priority levels, but only the ones in your configuration are built.
-
- NOTES on the use of 'call0' for long jumps instead of 'j':
- 1. This file should be assembled with the -mlongcalls option to xt-xcc.
- 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
- a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
- distance from the call to the destination. The linker then relaxes
- it back to 'call0 dest' if it determines that dest is within range.
- This allows more flexibility in locating code without the performance
- overhead of the 'l32r' literal data load in cases where the destination
- is in range of 'call0'. There is an additional benefit in that 'call0'
- has a longer range than 'j' due to the target being word-aligned, so
- the 'l32r' sequence is less likely needed.
- 3. The use of 'call0' with -mlongcalls requires that register a0 not be
- live at the time of the call, which is always the case for a function
- call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
- 4. This use of 'call0' is independent of the C function call ABI.
-
-*******************************************************************************/
-
-#include "xtensa_rtos.h"
-
-
-/* Enable stack backtrace across exception/interrupt - see below */
-#define XT_DEBUG_BACKTRACE 1
-
-
-/*
---------------------------------------------------------------------------------
- Defines used to access _xtos_interrupt_table.
---------------------------------------------------------------------------------
-*/
-#define XIE_HANDLER 0
-#define XIE_ARG 4
-#define XIE_SIZE 8
-
-/*
---------------------------------------------------------------------------------
- Macro extract_msb - return the input with only the highest bit set.
-
- Input : "ain" - Input value, clobbered.
- Output : "aout" - Output value, has only one bit set, MSB of "ain".
- The two arguments must be different AR registers.
---------------------------------------------------------------------------------
-*/
-
- .macro extract_msb aout ain
-1:
- addi \aout, \ain, -1 /* aout = ain - 1 */
- and \ain, \ain, \aout /* ain = ain & aout */
- bnez \ain, 1b /* repeat until ain == 0 */
- addi \aout, \aout, 1 /* return aout + 1 */
- .endm
-
-/*
---------------------------------------------------------------------------------
- Macro dispatch_c_isr - dispatch interrupts to user ISRs.
- This will dispatch to user handlers (if any) that are registered in the
- XTOS dispatch table (_xtos_interrupt_table). These handlers would have
- been registered by calling _xtos_set_interrupt_handler(). There is one
- exception - the timer interrupt used by the OS will not be dispatched
- to a user handler - this must be handled by the caller of this macro.
-
- Level triggered and software interrupts are automatically deasserted by
- this code.
-
- ASSUMPTIONS:
- -- PS.INTLEVEL is set to "level" at entry
- -- PS.EXCM = 0, C calling enabled
-
- NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
-
- NOTE: This macro will use registers a0 and a2-a6. The arguments are:
- level -- interrupt level
- mask -- interrupt bitmask for this level
---------------------------------------------------------------------------------
-*/
-
- .macro dispatch_c_isr level mask
-
- /* Get mask of pending, enabled interrupts at this level into a2. */
-
-.L_xt_user_int_&level&:
- rsr a2, INTENABLE
- rsr a3, INTERRUPT
- movi a4, \mask
- and a2, a2, a3
- and a2, a2, a4
- beqz a2, 9f /* nothing to do */
-
- /* This bit of code provides a nice debug backtrace in the debugger.
- It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
- if you want to save the cycles.
- */
- #if XT_DEBUG_BACKTRACE
- #ifndef __XTENSA_CALL0_ABI__
- rsr a0, EPC_1 + \level - 1 /* return address */
- movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */
- or a0, a0, a4 /* set top 2 bits */
- addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */
- #endif
- #endif
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a4, _xt_intexc_hooks
- l32i a4, a4, \level << 2
- beqz a4, 2f
- #ifdef __XTENSA_CALL0_ABI__
- callx0 a4
- beqz a2, 9f
- #else
- mov a6, a2
- callx4 a4
- beqz a6, 9f
- mov a2, a6
- #endif
-2:
- #endif
-
- /* Now look up in the dispatch table and call user ISR if any. */
- /* If multiple bits are set then MSB has highest priority. */
-
- extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
-
- #ifdef XT_USE_SWPRI
- /* Enable all interrupts at this level that are numerically higher
- than the one we just selected, since they are treated as higher
- priority.
- */
- movi a3, \mask /* a3 = all interrupts at this level */
- add a2, a4, a4 /* a2 = a4 << 1 */
- addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */
- and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */
- movi a3, _xt_intdata
- l32i a6, a3, 4 /* a6 = _xt_vpri_mask */
- neg a2, a2
- addi a2, a2, -1 /* a2 = mask to apply */
- and a5, a6, a2 /* mask off all bits <= a4 bit */
- s32i a5, a3, 4 /* update _xt_vpri_mask */
- rsr a3, INTENABLE
- and a3, a3, a2 /* mask off all bits <= a4 bit */
- wsr a3, INTENABLE
- rsil a3, \level - 1 /* lower interrupt level by 1 */
- #endif
-
- movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
- wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
- beq a3, a4, 7f /* if timer interrupt then skip table */
-
- find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
-
- movi a4, _xt_interrupt_table
- addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
- l32i a4, a3, XIE_HANDLER /* a4 = handler address */
- #ifdef __XTENSA_CALL0_ABI__
- mov a12, a6 /* save in callee-saved reg */
- l32i a2, a3, XIE_ARG /* a2 = handler arg */
- callx0 a4 /* call handler */
- mov a2, a12
- #else
- mov a2, a6 /* save in windowed reg */
- l32i a6, a3, XIE_ARG /* a6 = handler arg */
- callx4 a4 /* call handler */
- #endif
-
- #ifdef XT_USE_SWPRI
- j 8f
- #else
- j .L_xt_user_int_&level& /* check for more interrupts */
- #endif
-
-7:
-
- .ifeq XT_TIMER_INTPRI - \level
-.L_xt_user_int_timer_&level&:
- /*
- Interrupt handler for the RTOS tick timer if at this level.
- We'll be reading the interrupt state again after this call
- so no need to preserve any registers except a6 (vpri_mask).
- */
-
- #ifdef __XTENSA_CALL0_ABI__
- mov a12, a6
- call0 XT_RTOS_TIMER_INT
- mov a2, a12
- #else
- mov a2, a6
- call4 XT_RTOS_TIMER_INT
- #endif
- .endif
-
- #ifdef XT_USE_SWPRI
- j 8f
- #else
- j .L_xt_user_int_&level& /* check for more interrupts */
- #endif
-
- #ifdef XT_USE_SWPRI
-8:
- /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
- virtual _xt_intenable which _could_ have changed during interrupt
- processing. */
-
- movi a3, _xt_intdata
- l32i a4, a3, 0 /* a4 = _xt_intenable */
- s32i a2, a3, 4 /* update _xt_vpri_mask */
- and a4, a4, a2 /* a4 = masked intenable */
- wsr a4, INTENABLE /* update INTENABLE */
- #endif
-
-9:
- /* done */
-
- .endm
-
-
-/*
---------------------------------------------------------------------------------
- Panic handler.
- Should be reached by call0 (preferable) or jump only. If call0, a0 says where
- from. If on simulator, display panic message and abort, else loop indefinitely.
---------------------------------------------------------------------------------
-*/
-
- .text
- .global _xt_panic
- .type _xt_panic,@function
- .align 4
-
-_xt_panic:
- #ifdef XT_SIMULATOR
- addi a4, a0, -3 /* point to call0 */
- movi a3, _xt_panic_message
- movi a2, SYS_log_msg
- simcall
- movi a2, SYS_gdb_abort
- simcall
- #else
- rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */
-1: j 1b /* loop infinitely */
- #endif
-
- .section .rodata, "a"
- .align 4
-
-_xt_panic_message:
- .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n"
-
-
-/*
---------------------------------------------------------------------------------
- Hooks to dynamically install handlers for exceptions and interrupts.
- Allows automated regression frameworks to install handlers per test.
- Consists of an array of function pointers indexed by interrupt level,
- with index 0 containing the entry for user exceptions.
- Initialized with all 0s, meaning no handler is installed at each level.
- See comment in xtensa_rtos.h for more details.
---------------------------------------------------------------------------------
-*/
-
- #ifdef XT_INTEXC_HOOKS
- .data
- .global _xt_intexc_hooks
- .type _xt_intexc_hooks,@object
- .align 4
-
-_xt_intexc_hooks:
- .fill XT_INTEXC_HOOK_NUM, 4, 0
- #endif
-
-
-/*
---------------------------------------------------------------------------------
- EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
- (except window exception vectors).
-
- Each vector goes at a predetermined location according to the Xtensa
- hardware configuration, which is ensured by its placement in a special
- section known to the Xtensa linker support package (LSP). It performs
- the minimum necessary before jumping to the handler in the .text section.
-
- The corresponding handler goes in the normal .text section. It sets up
- the appropriate stack frame, saves a few vector-specific registers and
- calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
- and enter the RTOS, then sets up a C environment. It then calls the
- user's interrupt handler code (which may be coded in C) and finally
- calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
-
- While XT_RTOS_INT_EXIT does not return directly to the interruptee,
- eventually the RTOS scheduler will want to dispatch the interrupted
- task or handler. The scheduler will return to the exit point that was
- saved in the interrupt stack frame at XT_STK_EXIT.
---------------------------------------------------------------------------------
-*/
-
-
-/*
---------------------------------------------------------------------------------
-Debug Exception.
---------------------------------------------------------------------------------
-*/
-
-#if XCHAL_HAVE_DEBUG
-
- .begin literal_prefix .DebugExceptionVector
- .section .DebugExceptionVector.text, "ax"
- .global _DebugExceptionVector
- .align 4
-
-_DebugExceptionVector:
-
- #ifdef XT_SIMULATOR
- /*
- In the simulator, let the debugger (if any) handle the debug exception,
- or simply stop the simulation:
- */
- wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */
- movi a2, SYS_gdb_enter_sktloop
- simcall /* have ISS handle debug exc. */
- #elif 0 /* change condition to 1 to use the HAL minimal debug handler */
- wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL
- movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */
- jx a3
- #else
- wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
- call0 _xt_panic /* does not return */
- rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
- #endif
-
- .end literal_prefix
-
-#endif
-
-/*
---------------------------------------------------------------------------------
-Double Exception.
-Double exceptions are not a normal occurrence. They indicate a bug of some kind.
---------------------------------------------------------------------------------
-*/
-
-#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
-
- .begin literal_prefix .DoubleExceptionVector
- .section .DoubleExceptionVector.text, "ax"
- .global _DoubleExceptionVector
- .align 4
-
-_DoubleExceptionVector:
-
- #if XCHAL_HAVE_DEBUG
- break 1, 4 /* unhandled double exception */
- #endif
- call0 _xt_panic /* does not return */
- rfde /* make a0 point here not later */
-
- .end literal_prefix
-
-#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
-
-/*
---------------------------------------------------------------------------------
-Kernel Exception (including Level 1 Interrupt from kernel mode).
---------------------------------------------------------------------------------
-*/
-
- .begin literal_prefix .KernelExceptionVector
- .section .KernelExceptionVector.text, "ax"
- .global _KernelExceptionVector
- .align 4
-
-_KernelExceptionVector:
-
- wsr a0, EXCSAVE_1 /* preserve a0 */
- call0 _xt_kernel_exc /* kernel exception handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .align 4
-
-_xt_kernel_exc:
- #if XCHAL_HAVE_DEBUG
- break 1, 0 /* unhandled kernel exception */
- #endif
- call0 _xt_panic /* does not return */
- rfe /* make a0 point here not there */
-
-
-/*
---------------------------------------------------------------------------------
-User Exception (including Level 1 Interrupt from user mode).
---------------------------------------------------------------------------------
-*/
-
- .begin literal_prefix .UserExceptionVector
- .section .UserExceptionVector.text, "ax"
- .global _UserExceptionVector
- .type _UserExceptionVector,@function
- .align 4
-
-_UserExceptionVector:
-
- wsr a0, EXCSAVE_1 /* preserve a0 */
- call0 _xt_user_exc /* user exception handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
-/*
---------------------------------------------------------------------------------
- Insert some waypoints for jumping beyond the signed 8-bit range of
- conditional branch instructions, so the conditional branchces to specific
- exception handlers are not taken in the mainline. Saves some cycles in the
- mainline.
---------------------------------------------------------------------------------
-*/
-
- .text
-
- #if XCHAL_HAVE_WINDOWED
- .align 4
-_xt_to_alloca_exc:
- call0 _xt_alloca_exc /* in window vectors section */
- /* never returns here - call0 is used as a jump (see note at top) */
- #endif
-
- .align 4
-_xt_to_syscall_exc:
- call0 _xt_syscall_exc
- /* never returns here - call0 is used as a jump (see note at top) */
-
- #if XCHAL_CP_NUM > 0
- .align 4
-_xt_to_coproc_exc:
- call0 _xt_coproc_exc
- /* never returns here - call0 is used as a jump (see note at top) */
- #endif
-
-
-/*
---------------------------------------------------------------------------------
- User exception handler.
---------------------------------------------------------------------------------
-*/
-
- .type _xt_user_exc,@function
- .align 4
-
-_xt_user_exc:
-
- /* If level 1 interrupt then jump to the dispatcher */
- rsr a0, EXCCAUSE
- beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1
-
- /* Handle any coprocessor exceptions. Rely on the fact that exception
- numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
- */
- #if XCHAL_CP_NUM > 0
- bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
- #endif
-
- /* Handle alloca and syscall exceptions */
- #if XCHAL_HAVE_WINDOWED
- beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc
- #endif
- beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
-
- /* Handle all other exceptions. All can have user-defined handlers. */
- /* NOTE: we'll stay on the user stack for exception handling. */
-
- /* Allocate exception frame and save minimal context. */
- mov a0, sp
- addi sp, sp, -XT_STK_FRMSZ
- s32i a0, sp, XT_STK_A1
- #if XCHAL_HAVE_WINDOWED
- s32e a0, sp, -12 /* for debug backtrace */
- #endif
- rsr a0, PS /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_1 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_1 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- #if XCHAL_HAVE_WINDOWED
- s32e a0, sp, -16 /* for debug backtrace */
- #endif
- s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
- s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
- call0 _xt_context_save
-
- /* Save exc cause and vaddr into exception frame */
- rsr a0, EXCCAUSE
- s32i a0, sp, XT_STK_EXCCAUSE
- rsr a0, EXCVADDR
- s32i a0, sp, XT_STK_EXCVADDR
-
- /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
- #else
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
-
- #ifdef XT_DEBUG_BACKTRACE
- #ifndef __XTENSA_CALL0_ABI__
- rsr a0, EPC_1 /* return address for debug backtrace */
- movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */
- rsync /* wait for WSR.PS to complete */
- or a0, a0, a5 /* set top 2 bits */
- addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */
- #else
- rsync /* wait for WSR.PS to complete */
- #endif
- #endif
-
- rsr a2, EXCCAUSE /* recover exc cause */
-
- #ifdef XT_INTEXC_HOOKS
- /*
- Call exception hook to pre-handle exceptions (if installed).
- Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
- */
- movi a4, _xt_intexc_hooks
- l32i a4, a4, 0 /* user exception hook index 0 */
- beqz a4, 1f
-.Ln_xt_user_exc_call_hook:
- #ifdef __XTENSA_CALL0_ABI__
- callx0 a4
- beqi a2, -1, .L_xt_user_done
- #else
- mov a6, a2
- callx4 a4
- beqi a6, -1, .L_xt_user_done
- mov a2, a6
- #endif
-1:
- #endif
-
- rsr a2, EXCCAUSE /* recover exc cause */
- movi a3, _xt_exception_table
- addx4 a4, a2, a3 /* a4 = address of exception table entry */
- l32i a4, a4, 0 /* a4 = handler address */
- #ifdef __XTENSA_CALL0_ABI__
- mov a2, sp /* a2 = pointer to exc frame */
- callx0 a4 /* call handler */
- #else
- mov a6, sp /* a6 = pointer to exc frame */
- callx4 a4 /* call handler */
- #endif
-
-.L_xt_user_done:
-
- /* Restore context and return */
- call0 _xt_context_restore
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove exception frame */
- rsync /* ensure PS and EPC written */
- rfe /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
---------------------------------------------------------------------------------
-*/
-
- .global _xt_user_exit
- .type _xt_user_exit,@function
- .align 4
-_xt_user_exit:
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure PS and EPC written */
- rfe /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
-Syscall Exception Handler (jumped to from User Exception Handler).
-Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
-Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
---------------------------------------------------------------------------------
-*/
-
- .text
- .type _xt_syscall_exc,@function
- .align 4
-_xt_syscall_exc:
-
- #ifdef __XTENSA_CALL0_ABI__
- /*
- Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
- Use a minimal stack frame (16B) to save A2 & A3 for scratch.
- PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
- rsr a0, PS
- addi a0, a0, -PS_EXCM_MASK
- wsr a0, PS
- */
- addi sp, sp, -16
- s32i a2, sp, 8
- s32i a3, sp, 12
- #else /* Windowed ABI */
- /*
- Save necessary context and spill the register windows.
- PS.EXCM is still set and must remain set until after the spill.
- Reuse context save function though it saves more than necessary.
- For this reason, a full interrupt stack frame is allocated.
- */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
- s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
- call0 _xt_context_save
- #endif
-
- /*
- Grab the interruptee's PC and skip over the 'syscall' instruction.
- If it's at the end of a zero-overhead loop and it's not on the last
- iteration, decrement loop counter and skip to beginning of loop.
- */
- rsr a2, EPC_1 /* a2 = PC of 'syscall' */
- addi a3, a2, 3 /* ++PC */
- #if XCHAL_HAVE_LOOPS
- rsr a0, LEND /* if (PC == LEND */
- bne a3, a0, 1f
- rsr a0, LCOUNT /* && LCOUNT != 0) */
- beqz a0, 1f /* { */
- addi a0, a0, -1 /* --LCOUNT */
- rsr a3, LBEG /* PC = LBEG */
- wsr a0, LCOUNT /* } */
- #endif
-1: wsr a3, EPC_1 /* update PC */
-
- /* Restore interruptee's context and return from exception. */
- #ifdef __XTENSA_CALL0_ABI__
- l32i a2, sp, 8
- l32i a3, sp, 12
- addi sp, sp, 16
- #else
- call0 _xt_context_restore
- addi sp, sp, XT_STK_FRMSZ
- #endif
- movi a0, -1
- movnez a2, a0, a2 /* return -1 if not syscall 0 */
- rsr a0, EXCSAVE_1
- rfe
-
-/*
---------------------------------------------------------------------------------
-Co-Processor Exception Handler (jumped to from User Exception Handler).
-These exceptions are generated by co-processor instructions, which are only
-allowed in thread code (not in interrupts or kernel code). This restriction is
-deliberately imposed to reduce the burden of state-save/restore in interrupts.
---------------------------------------------------------------------------------
-*/
-#if XCHAL_CP_NUM > 0
-
- .section .rodata, "a"
-
-/* Offset to CP n save area in thread's CP save area. */
- .global _xt_coproc_sa_offset
- .type _xt_coproc_sa_offset,@object
- .align 16 /* minimize crossing cache boundaries */
-_xt_coproc_sa_offset:
- .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
- .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
-
-/* Bitmask for CP n's CPENABLE bit. */
- .type _xt_coproc_mask,@object
- .align 16,,8 /* try to keep it all in one cache line */
- .set i, 0
-_xt_coproc_mask:
- .rept XCHAL_CP_MAX
- .long (i<<16) | (1<= 2
-
- .begin literal_prefix .Level2InterruptVector
- .section .Level2InterruptVector.text, "ax"
- .global _Level2Vector
- .type _Level2Vector,@function
- .align 4
-_Level2Vector:
- wsr a0, EXCSAVE_2 /* preserve a0 */
- call0 _xt_medint2 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_medint2,@function
- .align 4
-_xt_medint2:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_2 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_2 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_2 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint2_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(2) | PS_UM
- #else
- movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint2_exit
- .type _xt_medint2_exit,@function
- .align 4
-_xt_medint2_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_2
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_2
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 2
-
-#endif /* Level 2 */
-
-#if XCHAL_EXCM_LEVEL >= 3
-
- .begin literal_prefix .Level3InterruptVector
- .section .Level3InterruptVector.text, "ax"
- .global _Level3Vector
- .type _Level3Vector,@function
- .align 4
-_Level3Vector:
- wsr a0, EXCSAVE_3 /* preserve a0 */
- call0 _xt_medint3 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_medint3,@function
- .align 4
-_xt_medint3:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_3 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_3 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_3 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint3_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(3) | PS_UM
- #else
- movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint3_exit
- .type _xt_medint3_exit,@function
- .align 4
-_xt_medint3_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_3
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_3
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 3
-
-#endif /* Level 3 */
-
-#if XCHAL_EXCM_LEVEL >= 4
-
- .begin literal_prefix .Level4InterruptVector
- .section .Level4InterruptVector.text, "ax"
- .global _Level4Vector
- .type _Level4Vector,@function
- .align 4
-_Level4Vector:
- wsr a0, EXCSAVE_4 /* preserve a0 */
- call0 _xt_medint4 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_medint4,@function
- .align 4
-_xt_medint4:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_4 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_4 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_4 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint4_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(4) | PS_UM
- #else
- movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint4_exit
- .type _xt_medint4_exit,@function
- .align 4
-_xt_medint4_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_4
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_4
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 4
-
-#endif /* Level 4 */
-
-#if XCHAL_EXCM_LEVEL >= 5
-
- .begin literal_prefix .Level5InterruptVector
- .section .Level5InterruptVector.text, "ax"
- .global _Level5Vector
- .type _Level5Vector,@function
- .align 4
-_Level5Vector:
- wsr a0, EXCSAVE_5 /* preserve a0 */
- call0 _xt_medint5 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_medint5,@function
- .align 4
-_xt_medint5:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_5 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_5 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_5 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint5_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(5) | PS_UM
- #else
- movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint5_exit
- .type _xt_medint5_exit,@function
- .align 4
-_xt_medint5_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_5
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_5
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 5
-
-#endif /* Level 5 */
-
-#if XCHAL_EXCM_LEVEL >= 6
-
- .begin literal_prefix .Level6InterruptVector
- .section .Level6InterruptVector.text, "ax"
- .global _Level6Vector
- .type _Level6Vector,@function
- .align 4
-_Level6Vector:
- wsr a0, EXCSAVE_6 /* preserve a0 */
- call0 _xt_medint6 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_medint6,@function
- .align 4
-_xt_medint6:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_6 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_6 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_6 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint6_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(6) | PS_UM
- #else
- movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint6_exit
- .type _xt_medint6_exit,@function
- .align 4
-_xt_medint6_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_6
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_6
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 6
-
-#endif /* Level 6 */
-
-
-/*******************************************************************************
-
-HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
-
-High priority interrupts are by definition those with priorities greater
-than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
-interrupts cannot interact with the RTOS, that is they must save all regs
-they use and not call any RTOS function.
-
-A further restriction imposed by the Xtensa windowed architecture is that
-high priority interrupts must not modify the stack area even logically
-"above" the top of the interrupted stack (they need to provide their
-own stack or static save area).
-
-Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
-and used for purposes requiring very short service times.
-
-Here are templates for high priority (level 2+) interrupt vectors.
-They assume only one interrupt per level to avoid the burden of identifying
-which interrupts at this level are pending and enabled. This allows for
-minimum latency and avoids having to save/restore a2 in addition to a0.
-If more than one interrupt per high priority level is configured, this burden
-is on the handler which in any case must provide a way to save and restore
-registers it uses without touching the interrupted stack.
-
-Each vector goes at a predetermined location according to the Xtensa
-hardware configuration, which is ensured by its placement in a special
-section known to the Xtensa linker support package (LSP). It performs
-the minimum necessary before jumping to the handler in the .text section.
-
-*******************************************************************************/
-
-/*
-Currently only shells for high priority interrupt handlers are provided
-here. However a template and example can be found in the Cadence Design Systems tools
-documentation: "Microprocessor Programmer's Guide".
-*/
-
-#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
-
- .begin literal_prefix .Level2InterruptVector
- .section .Level2InterruptVector.text, "ax"
- .global _Level2Vector
- .type _Level2Vector,@function
- .align 4
-_Level2Vector:
- wsr a0, EXCSAVE_2 /* preserve a0 */
- call0 _xt_highint2 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_highint2,@function
- .align 4
-_xt_highint2:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 2<<2
- beqz a0, 1f
-.Ln_xt_highint2_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint2_exit:
- rsr a0, EXCSAVE_2 /* restore a0 */
- rfi 2
-
-#endif /* Level 2 */
-
-#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
-
- .begin literal_prefix .Level3InterruptVector
- .section .Level3InterruptVector.text, "ax"
- .global _Level3Vector
- .type _Level3Vector,@function
- .align 4
-_Level3Vector:
- wsr a0, EXCSAVE_3 /* preserve a0 */
- call0 _xt_highint3 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint3,@function
- .align 4
-_xt_highint3:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 3<<2
- beqz a0, 1f
-.Ln_xt_highint3_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint3_exit:
- rsr a0, EXCSAVE_3 /* restore a0 */
- rfi 3
-
-#endif /* Level 3 */
-
-#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
-
- .begin literal_prefix .Level4InterruptVector
- .section .Level4InterruptVector.text, "ax"
- .global _Level4Vector
- .type _Level4Vector,@function
- .align 4
-_Level4Vector:
- wsr a0, EXCSAVE_4 /* preserve a0 */
- call0 _xt_highint4 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint4,@function
- .align 4
-_xt_highint4:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 4<<2
- beqz a0, 1f
-.Ln_xt_highint4_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint4_exit:
- rsr a0, EXCSAVE_4 /* restore a0 */
- rfi 4
-
-#endif /* Level 4 */
-
-#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
-
- .begin literal_prefix .Level5InterruptVector
- .section .Level5InterruptVector.text, "ax"
- .global _Level5Vector
- .type _Level5Vector,@function
- .align 4
-_Level5Vector:
- wsr a0, EXCSAVE_5 /* preserve a0 */
- call0 _xt_highint5 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint5,@function
- .align 4
-_xt_highint5:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 5<<2
- beqz a0, 1f
-.Ln_xt_highint5_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint5_exit:
- rsr a0, EXCSAVE_5 /* restore a0 */
- rfi 5
-
-#endif /* Level 5 */
-
-#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
-
- .begin literal_prefix .Level6InterruptVector
- .section .Level6InterruptVector.text, "ax"
- .global _Level6Vector
- .type _Level6Vector,@function
- .align 4
-_Level6Vector:
- wsr a0, EXCSAVE_6 /* preserve a0 */
- call0 _xt_highint6 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint6,@function
- .align 4
-_xt_highint6:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 6<<2
- beqz a0, 1f
-.Ln_xt_highint6_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint6_exit:
- rsr a0, EXCSAVE_6 /* restore a0 */
- rfi 6
-
-#endif /* Level 6 */
-
-#if XCHAL_HAVE_NMI
-
- .begin literal_prefix .NMIExceptionVector
- .section .NMIExceptionVector.text, "ax"
- .global _NMIExceptionVector
- .type _NMIExceptionVector,@function
- .align 4
-_NMIExceptionVector:
- wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
- call0 _xt_nmi /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_nmi,@function
- .align 4
-_xt_nmi:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, XCHAL_NMILEVEL<<2
- beqz a0, 1f
-.Ln_xt_nmi_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_nmi_exit:
- rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
- rfi XCHAL_NMILEVEL
-
-#endif /* NMI */
-
-
-/*******************************************************************************
-
-WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
-
-Here is the code for each window overflow/underflow exception vector and
-(interspersed) efficient code for handling the alloca exception cause.
-Window exceptions are handled entirely in the vector area and are very
-tight for performance. The alloca exception is also handled entirely in
-the window vector area so comes at essentially no cost in code size.
-Users should never need to modify them and Cadence Design Systems recommends
-they do not.
-
-Window handlers go at predetermined vector locations according to the
-Xtensa hardware configuration, which is ensured by their placement in a
-special section known to the Xtensa linker support package (LSP). Since
-their offsets in that section are always the same, the LSPs do not define
-a section per vector.
-
-These things are coded for XEA2 only (XEA1 is not supported).
-
-Note on Underflow Handlers:
-The underflow handler for returning from call[i+1] to call[i]
-must preserve all the registers from call[i+1]'s window.
-In particular, a0 and a1 must be preserved because the RETW instruction
-will be reexecuted (and may even underflow if an intervening exception
-has flushed call[i]'s registers).
-Registers a2 and up may contain return values.
-
-*******************************************************************************/
-
-#if XCHAL_HAVE_WINDOWED
-
- .section .WindowVectors.text, "ax"
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call4.
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call4 to call[j+1].
-On entry here:
- window rotated to call[j] start point;
- a0-a3 are registers to be saved;
- a4-a15 must be preserved;
- a5 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x0
- .global _WindowOverflow4
-_WindowOverflow4:
-
- s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */
- s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */
- s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */
- s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */
- rfwo /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call4
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call4 to call[i+1].
-On entry here:
- window rotated to call[i] start point;
- a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
- a4-a15 must be preserved (they are call[i+1].reg[0..11]);
- a5 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x40
- .global _WindowUnderflow4
-_WindowUnderflow4:
-
- l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */
- l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */
- l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */
- l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */
- rfwu
-
-/*
---------------------------------------------------------------------------------
-Handle alloca exception generated by interruptee executing 'movsp'.
-This uses space between the window vectors, so is essentially "free".
-All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
-and PS.EXCM has been set by the exception hardware (can't be interrupted).
-The fact the alloca exception was taken means the registers associated with
-the base-save area have been spilled and will be restored by the underflow
-handler, so those 4 registers are available for scratch.
-The code is optimized to avoid unaligned branches and minimize cache misses.
---------------------------------------------------------------------------------
-*/
-
- .align 4
- .global _xt_alloca_exc
-_xt_alloca_exc:
-
- rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */
- rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */
- rsr a2, PS
- extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
- xor a3, a3, a4 /* bits changed from old to current windowbase */
- rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */
- slli a3, a3, XCHAL_PS_OWB_SHIFT
- xor a2, a2, a3 /* flip changed bits in old window base */
- wsr a2, PS /* update PS.OWB to new window base */
- rsync
-
- _bbci.l a4, 31, _WindowUnderflow4
- rotw -1 /* original a0 goes to a8 */
- _bbci.l a8, 30, _WindowUnderflow8
- rotw -1
- j _WindowUnderflow12
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call8
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call8 to call[j+1].
-On entry here:
- window rotated to call[j] start point;
- a0-a7 are registers to be saved;
- a8-a15 must be preserved;
- a9 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x80
- .global _WindowOverflow8
-_WindowOverflow8:
-
- s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */
- l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
- (used to find end of call[j]'s frame) */
- s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */
- s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */
- s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */
- s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */
- s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */
- s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */
- s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */
- rfwo /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call8
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call8 to call[i+1].
-On entry here:
- window rotated to call[i] start point;
- a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
- a8-a15 must be preserved (they are call[i+1].reg[0..7]);
- a9 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0xC0
- .global _WindowUnderflow8
-_WindowUnderflow8:
-
- l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */
- l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */
- l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */
- l32e a7, a1, -12 /* a7 <- call[i-1]'s sp
- (used to find end of call[i]'s frame) */
- l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */
- l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */
- l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */
- l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */
- l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */
- rfwu
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call12
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call12 to call[j+1].
-On entry here:
- window rotated to call[j] start point;
- a0-a11 are registers to be saved;
- a12-a15 must be preserved;
- a13 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x100
- .global _WindowOverflow12
-_WindowOverflow12:
-
- s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */
- l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
- (used to find end of call[j]'s frame) */
- s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */
- s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */
- s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */
- s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */
- s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */
- s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */
- s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */
- s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */
- s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */
- s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */
- s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */
- rfwo /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call12
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call12 to call[i+1].
-On entry here:
- window rotated to call[i] start point;
- a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
- a12-a15 must be preserved (they are call[i+1].reg[0..3]);
- a13 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x140
- .global _WindowUnderflow12
-_WindowUnderflow12:
-
- l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */
- l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */
- l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */
- l32e a11, a1, -12 /* a11 <- call[i-1]'s sp
- (used to find end of call[i]'s frame) */
- l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */
- l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */
- l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */
- l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */
- l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */
- l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */
- l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */
- l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */
- l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */
- rfwu
-
-#endif /* XCHAL_HAVE_WINDOWED */
-
- .section .UserEnter.text, "ax"
- .global call_user_start
- .type call_user_start,@function
- .align 4
- .literal_position
-
-
-call_user_start:
-
- movi a2, 0x40040000 /* note: absolute symbol, not a ptr */
- wsr a2, vecbase
- call0 user_start /* user exception handler */
diff --git a/components/freertos/xtensa_vectors.S-old b/components/freertos/xtensa_vectors.S-old
deleted file mode 100644
index 2d0f7a99d..000000000
--- a/components/freertos/xtensa_vectors.S-old
+++ /dev/null
@@ -1,2064 +0,0 @@
-/*******************************************************************************
-Copyright (c) 2006-2015 Cadence Design Systems Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------------------------------------------------
-
- XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS
-
- Xtensa low level exception and interrupt vectors and handlers for an RTOS.
-
- Interrupt handlers and user exception handlers support interaction with
- the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and
- after user's specific interrupt handlers. These macros are defined in
- xtensa_.h to call suitable functions in a specific RTOS.
-
- Users can install application-specific interrupt handlers for low and
- medium level interrupts, by calling xt_set_interrupt_handler(). These
- handlers can be written in C, and must obey C calling convention. The
- handler table is indexed by the interrupt number. Each handler may be
- provided with an argument.
-
- Note that the system timer interrupt is handled specially, and is
- dispatched to the RTOS-specific handler. This timer cannot be hooked
- by application code.
-
- Optional hooks are also provided to install a handler per level at
- run-time, made available by compiling this source file with
- '-DXT_INTEXC_HOOKS' (useful for automated testing).
-
-!! This file is a template that usually needs to be modified to handle !!
-!! application specific interrupts. Search USER_EDIT for helpful comments !!
-!! on where to insert handlers and how to write them. !!
-
- Users can also install application-specific exception handlers in the
- same way, by calling xt_set_exception_handler(). One handler slot is
- provided for each exception type. Note that some exceptions are handled
- by the porting layer itself, and cannot be taken over by application
- code in this manner. These are the alloca, syscall, and coprocessor
- exceptions.
-
- The exception handlers can be written in C, and must follow C calling
- convention. Each handler is passed a pointer to an exception frame as
- its single argument. The exception frame is created on the stack, and
- holds the saved context of the thread that took the exception. If the
- handler returns, the context will be restored and the instruction that
- caused the exception will be retried. If the handler makes any changes
- to the saved state in the exception frame, the changes will be applied
- when restoring the context.
-
- Because Xtensa is a configurable architecture, this port supports all user
- generated configurations (except restrictions stated in the release notes).
- This is accomplished by conditional compilation using macros and functions
- defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
- Only the relevant parts of this file will be included in your RTOS build.
- For example, this file provides interrupt vector templates for all types and
- all priority levels, but only the ones in your configuration are built.
-
- NOTES on the use of 'call0' for long jumps instead of 'j':
- 1. This file should be assembled with the -mlongcalls option to xt-xcc.
- 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
- a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
- distance from the call to the destination. The linker then relaxes
- it back to 'call0 dest' if it determines that dest is within range.
- This allows more flexibility in locating code without the performance
- overhead of the 'l32r' literal data load in cases where the destination
- is in range of 'call0'. There is an additional benefit in that 'call0'
- has a longer range than 'j' due to the target being word-aligned, so
- the 'l32r' sequence is less likely needed.
- 3. The use of 'call0' with -mlongcalls requires that register a0 not be
- live at the time of the call, which is always the case for a function
- call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
- 4. This use of 'call0' is independent of the C function call ABI.
-
-*******************************************************************************/
-
-#include "xtensa_rtos.h"
-
-
-/* Enable stack backtrace across exception/interrupt - see below */
-#define XT_DEBUG_BACKTRACE 0
-
-
-/*
---------------------------------------------------------------------------------
- Defines used to access _xtos_interrupt_table.
---------------------------------------------------------------------------------
-*/
-#define XIE_HANDLER 0
-#define XIE_ARG 4
-#define XIE_SIZE 8
-
-/*
---------------------------------------------------------------------------------
- Macro extract_msb - return the input with only the highest bit set.
-
- Input : "ain" - Input value, clobbered.
- Output : "aout" - Output value, has only one bit set, MSB of "ain".
- The two arguments must be different AR registers.
---------------------------------------------------------------------------------
-*/
-
- .macro extract_msb aout ain
-1:
- addi \aout, \ain, -1 /* aout = ain - 1 */
- and \ain, \ain, \aout /* ain = ain & aout */
- bnez \ain, 1b /* repeat until ain == 0 */
- addi \aout, \aout, 1 /* return aout + 1 */
- .endm
-
-/*
---------------------------------------------------------------------------------
- Macro dispatch_c_isr - dispatch interrupts to user ISRs.
- This will dispatch to user handlers (if any) that are registered in the
- XTOS dispatch table (_xtos_interrupt_table). These handlers would have
- been registered by calling _xtos_set_interrupt_handler(). There is one
- exception - the timer interrupt used by the OS will not be dispatched
- to a user handler - this must be handled by the caller of this macro.
-
- Level triggered and software interrupts are automatically deasserted by
- this code.
-
- ASSUMPTIONS:
- -- PS.INTLEVEL is set to "level" at entry
- -- PS.EXCM = 0, C calling enabled
-
- NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
-
- NOTE: This macro will use registers a0 and a2-a6. The arguments are:
- level -- interrupt level
- mask -- interrupt bitmask for this level
---------------------------------------------------------------------------------
-*/
-
- .macro dispatch_c_isr level mask
-
- /* Get mask of pending, enabled interrupts at this level into a2. */
-
-.L_xt_user_int_&level&:
- rsr a2, INTENABLE
- rsr a3, INTERRUPT
- movi a4, \mask
- and a2, a2, a3
- and a2, a2, a4
- beqz a2, 9f /* nothing to do */
-
- /* This bit of code provides a nice debug backtrace in the debugger.
- It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
- if you want to save the cycles.
- */
- #if XT_DEBUG_BACKTRACE
- #ifndef __XTENSA_CALL0_ABI__
- rsr a0, EPC_1 + \level - 1 /* return address */
- movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */
- or a0, a0, a4 /* set top 2 bits */
- addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */
- #endif
- #endif
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a4, _xt_intexc_hooks
- l32i a4, a4, \level << 2
- beqz a4, 2f
- #ifdef __XTENSA_CALL0_ABI__
- callx0 a4
- beqz a2, 9f
- #else
- mov a6, a2
- callx4 a4
- beqz a6, 9f
- mov a2, a6
- #endif
-2:
- #endif
-
- /* Now look up in the dispatch table and call user ISR if any. */
- /* If multiple bits are set then MSB has highest priority. */
-
- extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
-
- #ifdef XT_USE_SWPRI
- /* Enable all interrupts at this level that are numerically higher
- than the one we just selected, since they are treated as higher
- priority.
- */
- movi a3, \mask /* a3 = all interrupts at this level */
- add a2, a4, a4 /* a2 = a4 << 1 */
- addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */
- and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */
- movi a3, _xt_intdata
- l32i a6, a3, 4 /* a6 = _xt_vpri_mask */
- neg a2, a2
- addi a2, a2, -1 /* a2 = mask to apply */
- and a5, a6, a2 /* mask off all bits <= a4 bit */
- s32i a5, a3, 4 /* update _xt_vpri_mask */
- rsr a3, INTENABLE
- and a3, a3, a2 /* mask off all bits <= a4 bit */
- wsr a3, INTENABLE
- rsil a3, \level - 1 /* lower interrupt level by 1 */
- #endif
-
- movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
- wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
- beq a3, a4, 7f /* if timer interrupt then skip table */
-
- find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
-
- movi a4, _xt_interrupt_table
- addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
- l32i a4, a3, XIE_HANDLER /* a4 = handler address */
- #ifdef __XTENSA_CALL0_ABI__
- mov a12, a6 /* save in callee-saved reg */
- l32i a2, a3, XIE_ARG /* a2 = handler arg */
- callx0 a4 /* call handler */
- mov a2, a12
- #else
- mov a2, a6 /* save in windowed reg */
- l32i a6, a3, XIE_ARG /* a6 = handler arg */
- callx4 a4 /* call handler */
- #endif
-
- #ifdef XT_USE_SWPRI
- j 8f
- #else
- j .L_xt_user_int_&level& /* check for more interrupts */
- #endif
-
-7:
-
- .ifeq XT_TIMER_INTPRI - \level
-.L_xt_user_int_timer_&level&:
- /*
- Interrupt handler for the RTOS tick timer if at this level.
- We'll be reading the interrupt state again after this call
- so no need to preserve any registers except a6 (vpri_mask).
- */
-
- #ifdef __XTENSA_CALL0_ABI__
- mov a12, a6
- call0 XT_RTOS_TIMER_INT
- mov a2, a12
- #else
- mov a2, a6
- call4 XT_RTOS_TIMER_INT
- #endif
- .endif
-
- #ifdef XT_USE_SWPRI
- j 8f
- #else
- j .L_xt_user_int_&level& /* check for more interrupts */
- #endif
-
- #ifdef XT_USE_SWPRI
-8:
- /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
- virtual _xt_intenable which _could_ have changed during interrupt
- processing. */
-
- movi a3, _xt_intdata
- l32i a4, a3, 0 /* a4 = _xt_intenable */
- s32i a2, a3, 4 /* update _xt_vpri_mask */
- and a4, a4, a2 /* a4 = masked intenable */
- wsr a4, INTENABLE /* update INTENABLE */
- #endif
-
-9:
- /* done */
-
- .endm
-
-
-/*
---------------------------------------------------------------------------------
- Panic handler.
- Should be reached by call0 (preferable) or jump only. If call0, a0 says where
- from. If on simulator, display panic message and abort, else loop indefinitely.
---------------------------------------------------------------------------------
-*/
-
- .text
- .global panicHandlerRegs
- .global panicHandler
- .global panicStack
-
- .global _xt_panic
- .type _xt_panic,@function
- .align 4
-
-_xt_panic:
- //ToDo: save registers
- movi a2, panicHandlerRegs
- s32i a0,a2,0
- s32i a1,a2,4
- s32i a2,a2,8
- s32i a3,a2,12
- s32i a4,a2,16
- s32i a5,a2,20
- s32i a6,a2,24
- s32i a7,a2,28
- s32i a8,a2,32
- s32i a9,a2,36
- s32i a10,a2,40
- s32i a11,a2,44
- s32i a12,a2,48
- s32i a13,a2,52
- s32i a14,a2,56
- s32i a15,a2,60
-
- rsr a3, EXCSAVE
- s32i a3,a2,64
- rsr a3, EXCSAVE+1
- s32i a3,a2,68
- rsr a3, EXCSAVE+2
- s32i a3,a2,72
- rsr a3, EXCSAVE+3
- s32i a3,a2,76
- rsr a3, EXCSAVE+4
- s32i a3,a2,80
- rsr a3, EXCSAVE+5
- s32i a3,a2,84
- rsr a3, EXCSAVE+6
- s32i a3,a2,88
- rsr a3, EXCSAVE+7
- s32i a3,a2,92
-
- rsr a3, EPC
- s32i a3,a2,96
- rsr a3, EPC+1
- s32i a3,a2,100
- rsr a3, EPC+2
- s32i a3,a2,104
- rsr a3, EPC+3
- s32i a3,a2,108
- rsr a3, EPC+4
- s32i a3,a2,112
- rsr a3, EPC+5
- s32i a3,a2,116
- rsr a3, EPC+6
- s32i a3,a2,120
- rsr a3, EPC+7
- s32i a3,a2,124
-
- rsr a3, DEPC
- s32i a3,a2,128
- rsr a3, EXCVADDR
- s32i a3,a2,132
-
- //Reset window start / base to 0
- movi a2, 1
- wsr a2, windowstart
- movi a2, 0
- wsr a2, windowbase
- rsync
-
- //Clear EXCM, set WOE flags
- rsr a2, ps
- movi a3, ~(PS_EXCM_MASK)
- and a2, a2, a3
- movi a3, PS_WOE_MASK
- or a2, a2, a3
- wsr a2, ps
- rsync
-
- //Switch to private stack
- movi a1,panicStack+(255*4)
- rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */
-
-
- // Debug: output '!' on serport
- movi a2,0x60000000
- movi a3,'!'
- s32i a3,a2,0
-
- movi a3, panicHandlerRegs
- l32i a2,a3,0
- call0 panic_print_hex
- rsr a2, EXCCAUSE
- call0 panic_print_hex
- rsr a2, EXCVADDR
- call0 panic_print_hex
- rsr a2,EPC+1
- call0 panic_print_hex
- rsr a2,EPC+2
- call0 panic_print_hex
- rsr a2,EPC+3
- call0 panic_print_hex
- rsr a2,EPC+6
- call0 panic_print_hex
- rsr a2,EXCSAVE_1
- call0 panic_print_hex
- rsr a2,DEPC
- call0 panic_print_hex
-
- //Call panic handler
-// movi a4, panicHandler
-// callx4 a4
- call4 panicHandler
-
- movi a2,0x60000000
- movi a3,'d'
- s32i a3,a2,0
-
-
-1: j 1b /* loop infinitely */
-
- .align 4
-panicHandlerz:
- entry a1,32
- movi a2,0x60000000
- movi a3,'h'
- memw
- s32i a3,a2,0
-
- retw
-
-
- .align 4
-//Call using call0. Prints the hex char in a2. Kills a3, a4, a5
-panic_print_hex:
- movi a3,0x60000000
- movi a4,8
-panic_print_hex_loop:
- l32i a5, a3, 0x1c
- extui a5, a5, 16, 8
- bgei a5,64,panic_print_hex_loop
-
- srli a5,a2,28
- bgei a5,10,panic_print_hex_a
- addi a5,a5,'0'
- j panic_print_hex_ok
-panic_print_hex_a:
- addi a5,a5,'A'-10
-panic_print_hex_ok:
- s32i a5,a3,0
- slli a2,a2,4
-
- addi a4,a4,-1
- bnei a4,0,panic_print_hex_loop
- movi a5,' '
- s32i a5,a3,0
-
- ret
-
-
-
- .section .rodata, "a"
- .align 4
-
-
-
-/*
---------------------------------------------------------------------------------
- Hooks to dynamically install handlers for exceptions and interrupts.
- Allows automated regression frameworks to install handlers per test.
- Consists of an array of function pointers indexed by interrupt level,
- with index 0 containing the entry for user exceptions.
- Initialized with all 0s, meaning no handler is installed at each level.
- See comment in xtensa_rtos.h for more details.
---------------------------------------------------------------------------------
-*/
-
- #ifdef XT_INTEXC_HOOKS
- .data
- .global _xt_intexc_hooks
- .type _xt_intexc_hooks,@object
- .align 4
-
-_xt_intexc_hooks:
- .fill XT_INTEXC_HOOK_NUM, 4, 0
- #endif
-
-
-/*
---------------------------------------------------------------------------------
- EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
- (except window exception vectors).
-
- Each vector goes at a predetermined location according to the Xtensa
- hardware configuration, which is ensured by its placement in a special
- section known to the Xtensa linker support package (LSP). It performs
- the minimum necessary before jumping to the handler in the .text section.
-
- The corresponding handler goes in the normal .text section. It sets up
- the appropriate stack frame, saves a few vector-specific registers and
- calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
- and enter the RTOS, then sets up a C environment. It then calls the
- user's interrupt handler code (which may be coded in C) and finally
- calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
-
- While XT_RTOS_INT_EXIT does not return directly to the interruptee,
- eventually the RTOS scheduler will want to dispatch the interrupted
- task or handler. The scheduler will return to the exit point that was
- saved in the interrupt stack frame at XT_STK_EXIT.
---------------------------------------------------------------------------------
-*/
-
-
-/*
---------------------------------------------------------------------------------
-Debug Exception.
---------------------------------------------------------------------------------
-*/
-
-#if XCHAL_HAVE_DEBUG
-
- .begin literal_prefix .DebugExceptionVector
- .section .DebugExceptionVector.text, "ax"
- .global _DebugExceptionVector
- .align 4
-
-_DebugExceptionVector:
-
- #ifdef XT_SIMULATOR
- /*
- In the simulator, let the debugger (if any) handle the debug exception,
- or simply stop the simulation:
- */
- wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */
- movi a2, SYS_gdb_enter_sktloop
- simcall /* have ISS handle debug exc. */
- #elif 0 /* change condition to 1 to use the HAL minimal debug handler */
- wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL
- movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */
- jx a3
- #else
- wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
- call0 _xt_panic /* does not return */
- rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
- #endif
-
- .end literal_prefix
-
-#endif
-
-/*
---------------------------------------------------------------------------------
-Double Exception.
-Double exceptions are not a normal occurrence. They indicate a bug of some kind.
---------------------------------------------------------------------------------
-*/
-
-#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
-
- .begin literal_prefix .DoubleExceptionVector
- .section .DoubleExceptionVector.text, "ax"
- .global _DoubleExceptionVector
- .align 4
-
-_DoubleExceptionVector:
-
- #if XCHAL_HAVE_DEBUG
- break 1, 4 /* unhandled double exception */
- #endif
- call0 _xt_panic /* does not return */
- rfde /* make a0 point here not later */
-
- .end literal_prefix
-
-#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
-
-/*
---------------------------------------------------------------------------------
-Kernel Exception (including Level 1 Interrupt from kernel mode).
---------------------------------------------------------------------------------
-*/
-
- .begin literal_prefix .KernelExceptionVector
- .section .KernelExceptionVector.text, "ax"
- .global _KernelExceptionVector
- .align 4
-
-_KernelExceptionVector:
-
- wsr a0, EXCSAVE_1 /* preserve a0 */
- call0 _xt_kernel_exc /* kernel exception handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .align 4
-
-_xt_kernel_exc:
- #if XCHAL_HAVE_DEBUG
- break 1, 0 /* unhandled kernel exception */
- #endif
- call0 _xt_panic /* does not return */
- rfe /* make a0 point here not there */
-
-
-/*
---------------------------------------------------------------------------------
-User Exception (including Level 1 Interrupt from user mode).
---------------------------------------------------------------------------------
-*/
-
- .begin literal_prefix .UserExceptionVector
- .section .UserExceptionVector.text, "ax"
- .global _UserExceptionVector
- .type _UserExceptionVector,@function
- .align 4
-
-_UserExceptionVector:
-
- wsr a0, EXCSAVE_1 /* preserve a0 */
- call0 _xt_user_exc /* user exception handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
-/*
---------------------------------------------------------------------------------
- Insert some waypoints for jumping beyond the signed 8-bit range of
- conditional branch instructions, so the conditional branchces to specific
- exception handlers are not taken in the mainline. Saves some cycles in the
- mainline.
---------------------------------------------------------------------------------
-*/
-
- .text
-
- #if XCHAL_HAVE_WINDOWED
- .align 4
-_xt_to_alloca_exc:
- call0 _xt_alloca_exc /* in window vectors section */
- /* never returns here - call0 is used as a jump (see note at top) */
- #endif
-
- .align 4
-_xt_to_syscall_exc:
- call0 _xt_syscall_exc
- /* never returns here - call0 is used as a jump (see note at top) */
-
- #if XCHAL_CP_NUM > 0
- .align 4
-_xt_to_coproc_exc:
- call0 _xt_coproc_exc
- /* never returns here - call0 is used as a jump (see note at top) */
- #endif
-
-
-/*
---------------------------------------------------------------------------------
- User exception handler.
---------------------------------------------------------------------------------
-*/
-
- .type _xt_user_exc,@function
- .align 4
-
-_xt_user_exc:
-
- /* If level 1 interrupt then jump to the dispatcher */
- rsr a0, EXCCAUSE
- beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1
-
- /* Handle any coprocessor exceptions. Rely on the fact that exception
- numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
- */
- #if XCHAL_CP_NUM > 0
- bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
- #endif
-
- /* Handle alloca and syscall exceptions */
- #if XCHAL_HAVE_WINDOWED
- beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc
- #endif
- beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
-
- //HACK! No custom vector stuff, just call panic handler directly. ToDo: remove this when possible. -JD
- call0 _xt_panic
-
- /* Handle all other exceptions. All can have user-defined handlers. */
- /* NOTE: we'll stay on the user stack for exception handling. */
-
- /* Allocate exception frame and save minimal context. */
- mov a0, sp
- addi sp, sp, -XT_STK_FRMSZ
- s32i a0, sp, XT_STK_A1
- #if XCHAL_HAVE_WINDOWED
- s32e a0, sp, -12 /* for debug backtrace */
- #endif
- rsr a0, PS /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_1 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_1 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- #if XCHAL_HAVE_WINDOWED
- s32e a0, sp, -16 /* for debug backtrace */
- #endif
- s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
- s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
- call0 _xt_context_save
-
- /* Save exc cause and vaddr into exception frame */
- rsr a0, EXCCAUSE
- s32i a0, sp, XT_STK_EXCCAUSE
- rsr a0, EXCVADDR
- s32i a0, sp, XT_STK_EXCVADDR
-
- /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
- #else
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
-
- #ifdef XT_DEBUG_BACKTRACE
- #ifndef __XTENSA_CALL0_ABI__
- rsr a0, EPC_1 /* return address for debug backtrace */
- movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */
- rsync /* wait for WSR.PS to complete */
- or a0, a0, a5 /* set top 2 bits */
- addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */
- #else
- rsync /* wait for WSR.PS to complete */
- #endif
- #endif
-
- rsr a2, EXCCAUSE /* recover exc cause */
-
- #ifdef XT_INTEXC_HOOKS
- /*
- Call exception hook to pre-handle exceptions (if installed).
- Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
- */
- movi a4, _xt_intexc_hooks
- l32i a4, a4, 0 /* user exception hook index 0 */
- beqz a4, 1f
-.Ln_xt_user_exc_call_hook:
- #ifdef __XTENSA_CALL0_ABI__
- callx0 a4
- beqi a2, -1, .L_xt_user_done
- #else
- mov a6, a2
- callx4 a4
- beqi a6, -1, .L_xt_user_done
- mov a2, a6
- #endif
-1:
- #endif
-
- rsr a2, EXCCAUSE /* recover exc cause */
- movi a3, _xt_exception_table
- addx4 a4, a2, a3 /* a4 = address of exception table entry */
- l32i a4, a4, 0 /* a4 = handler address */
- #ifdef __XTENSA_CALL0_ABI__
- mov a2, sp /* a2 = pointer to exc frame */
- callx0 a4 /* call handler */
- #else
- mov a6, sp /* a6 = pointer to exc frame */
- callx4 a4 /* call handler */
- #endif
-
-.L_xt_user_done:
-
- /* Restore context and return */
- call0 _xt_context_restore
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove exception frame */
- rsync /* ensure PS and EPC written */
- rfe /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
---------------------------------------------------------------------------------
-*/
-
- .global _xt_user_exit
- .type _xt_user_exit,@function
- .align 4
-_xt_user_exit:
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure PS and EPC written */
- rfe /* PS.EXCM is cleared */
-
-
-/*
---------------------------------------------------------------------------------
-Syscall Exception Handler (jumped to from User Exception Handler).
-Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
-Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
---------------------------------------------------------------------------------
-*/
-
- .text
- .type _xt_syscall_exc,@function
- .align 4
-_xt_syscall_exc:
-
- #ifdef __XTENSA_CALL0_ABI__
- /*
- Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
- Use a minimal stack frame (16B) to save A2 & A3 for scratch.
- PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
- rsr a0, PS
- addi a0, a0, -PS_EXCM_MASK
- wsr a0, PS
- */
- addi sp, sp, -16
- s32i a2, sp, 8
- s32i a3, sp, 12
- #else /* Windowed ABI */
- /*
- Save necessary context and spill the register windows.
- PS.EXCM is still set and must remain set until after the spill.
- Reuse context save function though it saves more than necessary.
- For this reason, a full interrupt stack frame is allocated.
- */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
- s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
- call0 _xt_context_save
- #endif
-
- /*
- Grab the interruptee's PC and skip over the 'syscall' instruction.
- If it's at the end of a zero-overhead loop and it's not on the last
- iteration, decrement loop counter and skip to beginning of loop.
- */
- rsr a2, EPC_1 /* a2 = PC of 'syscall' */
- addi a3, a2, 3 /* ++PC */
- #if XCHAL_HAVE_LOOPS
- rsr a0, LEND /* if (PC == LEND */
- bne a3, a0, 1f
- rsr a0, LCOUNT /* && LCOUNT != 0) */
- beqz a0, 1f /* { */
- addi a0, a0, -1 /* --LCOUNT */
- rsr a3, LBEG /* PC = LBEG */
- wsr a0, LCOUNT /* } */
- #endif
-1: wsr a3, EPC_1 /* update PC */
-
- /* Restore interruptee's context and return from exception. */
- #ifdef __XTENSA_CALL0_ABI__
- l32i a2, sp, 8
- l32i a3, sp, 12
- addi sp, sp, 16
- #else
- call0 _xt_context_restore
- addi sp, sp, XT_STK_FRMSZ
- #endif
- movi a0, -1
- movnez a2, a0, a2 /* return -1 if not syscall 0 */
- rsr a0, EXCSAVE_1
- rfe
-
-/*
---------------------------------------------------------------------------------
-Co-Processor Exception Handler (jumped to from User Exception Handler).
-These exceptions are generated by co-processor instructions, which are only
-allowed in thread code (not in interrupts or kernel code). This restriction is
-deliberately imposed to reduce the burden of state-save/restore in interrupts.
---------------------------------------------------------------------------------
-*/
-#if XCHAL_CP_NUM > 0
-
- .section .rodata, "a"
-
-/* Offset to CP n save area in thread's CP save area. */
- .global _xt_coproc_sa_offset
- .type _xt_coproc_sa_offset,@object
- .align 16 /* minimize crossing cache boundaries */
-_xt_coproc_sa_offset:
- .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
- .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
-
-/* Bitmask for CP n's CPENABLE bit. */
- .type _xt_coproc_mask,@object
- .align 16,,8 /* try to keep it all in one cache line */
- .set i, 0
-_xt_coproc_mask:
- .rept XCHAL_CP_MAX
- .long (i<<16) | (1<= 2
-
- .begin literal_prefix .Level2InterruptVector
- .section .Level2InterruptVector.text, "ax"
- .global _Level2Vector
- .type _Level2Vector,@function
- .align 4
-_Level2Vector:
- wsr a0, EXCSAVE_2 /* preserve a0 */
- call0 _xt_medint2 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_medint2,@function
- .align 4
-_xt_medint2:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_2 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_2 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_2 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint2_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(2) | PS_UM
- #else
- movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint2_exit
- .type _xt_medint2_exit,@function
- .align 4
-_xt_medint2_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_2
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_2
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 2
-
-#endif /* Level 2 */
-
-#if XCHAL_EXCM_LEVEL >= 3
-
- .begin literal_prefix .Level3InterruptVector
- .section .Level3InterruptVector.text, "ax"
- .global _Level3Vector
- .type _Level3Vector,@function
- .align 4
-_Level3Vector:
- wsr a0, EXCSAVE_3 /* preserve a0 */
- call0 _xt_medint3 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_medint3,@function
- .align 4
-_xt_medint3:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_3 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_3 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_3 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint3_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(3) | PS_UM
- #else
- movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint3_exit
- .type _xt_medint3_exit,@function
- .align 4
-_xt_medint3_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_3
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_3
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 3
-
-#endif /* Level 3 */
-
-#if XCHAL_EXCM_LEVEL >= 4
-
- .begin literal_prefix .Level4InterruptVector
- .section .Level4InterruptVector.text, "ax"
- .global _Level4Vector
- .type _Level4Vector,@function
- .align 4
-_Level4Vector:
- wsr a0, EXCSAVE_4 /* preserve a0 */
- call0 _xt_medint4 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_medint4,@function
- .align 4
-_xt_medint4:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_4 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_4 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_4 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint4_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(4) | PS_UM
- #else
- movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint4_exit
- .type _xt_medint4_exit,@function
- .align 4
-_xt_medint4_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_4
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_4
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 4
-
-#endif /* Level 4 */
-
-#if XCHAL_EXCM_LEVEL >= 5
-
- .begin literal_prefix .Level5InterruptVector
- .section .Level5InterruptVector.text, "ax"
- .global _Level5Vector
- .type _Level5Vector,@function
- .align 4
-_Level5Vector:
- wsr a0, EXCSAVE_5 /* preserve a0 */
- call0 _xt_medint5 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_medint5,@function
- .align 4
-_xt_medint5:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_5 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_5 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_5 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint5_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(5) | PS_UM
- #else
- movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint5_exit
- .type _xt_medint5_exit,@function
- .align 4
-_xt_medint5_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_5
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_5
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 5
-
-#endif /* Level 5 */
-
-#if XCHAL_EXCM_LEVEL >= 6
-
- .begin literal_prefix .Level6InterruptVector
- .section .Level6InterruptVector.text, "ax"
- .global _Level6Vector
- .type _Level6Vector,@function
- .align 4
-_Level6Vector:
- wsr a0, EXCSAVE_6 /* preserve a0 */
- call0 _xt_medint6 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_medint6,@function
- .align 4
-_xt_medint6:
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
- s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
- rsr a0, EPS_6 /* save interruptee's PS */
- s32i a0, sp, XT_STK_PS
- rsr a0, EPC_6 /* save interruptee's PC */
- s32i a0, sp, XT_STK_PC
- rsr a0, EXCSAVE_6 /* save interruptee's a0 */
- s32i a0, sp, XT_STK_A0
- movi a0, _xt_medint6_exit /* save exit point for dispatch */
- s32i a0, sp, XT_STK_EXIT
-
- /* Save rest of interrupt context and enter RTOS. */
- call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
-
- /* !! We are now on the RTOS system stack !! */
-
- /* Set up PS for C, enable interrupts above this level and clear EXCM. */
- #ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(6) | PS_UM
- #else
- movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
- #endif
- wsr a0, PS
- rsync
-
- /* OK to call C code at this point, dispatch user ISRs */
-
- dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
-
- /* Done handling interrupts, transfer control to OS */
- call0 XT_RTOS_INT_EXIT /* does not return directly here */
-
- /*
- Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
- on entry and used to return to a thread or interrupted interrupt handler.
- */
- .global _xt_medint6_exit
- .type _xt_medint6_exit,@function
- .align 4
-_xt_medint6_exit:
- /* Restore only level-specific regs (the rest were already restored) */
- l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
- wsr a0, EPS_6
- l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
- wsr a0, EPC_6
- l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
- l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
- rsync /* ensure EPS and EPC written */
- rfi 6
-
-#endif /* Level 6 */
-
-
-/*******************************************************************************
-
-HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
-
-High priority interrupts are by definition those with priorities greater
-than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
-interrupts cannot interact with the RTOS, that is they must save all regs
-they use and not call any RTOS function.
-
-A further restriction imposed by the Xtensa windowed architecture is that
-high priority interrupts must not modify the stack area even logically
-"above" the top of the interrupted stack (they need to provide their
-own stack or static save area).
-
-Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
-and used for purposes requiring very short service times.
-
-Here are templates for high priority (level 2+) interrupt vectors.
-They assume only one interrupt per level to avoid the burden of identifying
-which interrupts at this level are pending and enabled. This allows for
-minimum latency and avoids having to save/restore a2 in addition to a0.
-If more than one interrupt per high priority level is configured, this burden
-is on the handler which in any case must provide a way to save and restore
-registers it uses without touching the interrupted stack.
-
-Each vector goes at a predetermined location according to the Xtensa
-hardware configuration, which is ensured by its placement in a special
-section known to the Xtensa linker support package (LSP). It performs
-the minimum necessary before jumping to the handler in the .text section.
-
-*******************************************************************************/
-
-/*
-Currently only shells for high priority interrupt handlers are provided
-here. However a template and example can be found in the Cadence Design Systems tools
-documentation: "Microprocessor Programmer's Guide".
-*/
-
-#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
-
- .begin literal_prefix .Level2InterruptVector
- .section .Level2InterruptVector.text, "ax"
- .global _Level2Vector
- .type _Level2Vector,@function
- .align 4
-_Level2Vector:
- wsr a0, EXCSAVE_2 /* preserve a0 */
- call0 _xt_highint2 /* load interrupt handler */
-
- .end literal_prefix
-
- .text
- .type _xt_highint2,@function
- .align 4
-_xt_highint2:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 2<<2
- beqz a0, 1f
-.Ln_xt_highint2_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint2_exit:
- rsr a0, EXCSAVE_2 /* restore a0 */
- rfi 2
-
-#endif /* Level 2 */
-
-#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
-
- .begin literal_prefix .Level3InterruptVector
- .section .Level3InterruptVector.text, "ax"
- .global _Level3Vector
- .type _Level3Vector,@function
- .align 4
-_Level3Vector:
- wsr a0, EXCSAVE_3 /* preserve a0 */
- call0 _xt_highint3 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint3,@function
- .align 4
-_xt_highint3:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 3<<2
- beqz a0, 1f
-.Ln_xt_highint3_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint3_exit:
- rsr a0, EXCSAVE_3 /* restore a0 */
- rfi 3
-
-#endif /* Level 3 */
-
-#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
-
- .begin literal_prefix .Level4InterruptVector
- .section .Level4InterruptVector.text, "ax"
- .global _Level4Vector
- .type _Level4Vector,@function
- .align 4
-_Level4Vector:
- wsr a0, EXCSAVE_4 /* preserve a0 */
- call0 _xt_highint4 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint4,@function
- .align 4
-_xt_highint4:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 4<<2
- beqz a0, 1f
-.Ln_xt_highint4_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint4_exit:
- rsr a0, EXCSAVE_4 /* restore a0 */
- rfi 4
-
-#endif /* Level 4 */
-
-#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
-
- .begin literal_prefix .Level5InterruptVector
- .section .Level5InterruptVector.text, "ax"
- .global _Level5Vector
- .type _Level5Vector,@function
- .align 4
-_Level5Vector:
- wsr a0, EXCSAVE_5 /* preserve a0 */
- call0 _xt_highint5 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint5,@function
- .align 4
-_xt_highint5:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 5<<2
- beqz a0, 1f
-.Ln_xt_highint5_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint5_exit:
- rsr a0, EXCSAVE_5 /* restore a0 */
- rfi 5
-
-#endif /* Level 5 */
-
-#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
-
- .begin literal_prefix .Level6InterruptVector
- .section .Level6InterruptVector.text, "ax"
- .global _Level6Vector
- .type _Level6Vector,@function
- .align 4
-_Level6Vector:
- wsr a0, EXCSAVE_6 /* preserve a0 */
- call0 _xt_highint6 /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_highint6,@function
- .align 4
-_xt_highint6:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, 6<<2
- beqz a0, 1f
-.Ln_xt_highint6_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_highint6_exit:
- rsr a0, EXCSAVE_6 /* restore a0 */
- rfi 6
-
-#endif /* Level 6 */
-
-#if XCHAL_HAVE_NMI
-
- .begin literal_prefix .NMIExceptionVector
- .section .NMIExceptionVector.text, "ax"
- .global _NMIExceptionVector
- .type _NMIExceptionVector,@function
- .align 4
-_NMIExceptionVector:
- wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */
- call0 _xt_nmi /* load interrupt handler */
- /* never returns here - call0 is used as a jump (see note at top) */
-
- .end literal_prefix
-
- .text
- .type _xt_nmi,@function
- .align 4
-_xt_nmi:
-
- #ifdef XT_INTEXC_HOOKS
- /* Call interrupt hook if present to (pre)handle interrupts. */
- movi a0, _xt_intexc_hooks
- l32i a0, a0, XCHAL_NMILEVEL<<2
- beqz a0, 1f
-.Ln_xt_nmi_call_hook:
- callx0 a0 /* must NOT disturb stack! */
-1:
- #endif
-
- /* USER_EDIT:
- ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
- */
-
- .align 4
-.L_xt_nmi_exit:
- rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
- rfi XCHAL_NMILEVEL
-
-#endif /* NMI */
-
-
-/*******************************************************************************
-
-WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
-
-Here is the code for each window overflow/underflow exception vector and
-(interspersed) efficient code for handling the alloca exception cause.
-Window exceptions are handled entirely in the vector area and are very
-tight for performance. The alloca exception is also handled entirely in
-the window vector area so comes at essentially no cost in code size.
-Users should never need to modify them and Cadence Design Systems recommends
-they do not.
-
-Window handlers go at predetermined vector locations according to the
-Xtensa hardware configuration, which is ensured by their placement in a
-special section known to the Xtensa linker support package (LSP). Since
-their offsets in that section are always the same, the LSPs do not define
-a section per vector.
-
-These things are coded for XEA2 only (XEA1 is not supported).
-
-Note on Underflow Handlers:
-The underflow handler for returning from call[i+1] to call[i]
-must preserve all the registers from call[i+1]'s window.
-In particular, a0 and a1 must be preserved because the RETW instruction
-will be reexecuted (and may even underflow if an intervening exception
-has flushed call[i]'s registers).
-Registers a2 and up may contain return values.
-
-*******************************************************************************/
-
-#if XCHAL_HAVE_WINDOWED
-
- .section .WindowVectors.text, "ax"
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call4.
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call4 to call[j+1].
-On entry here:
- window rotated to call[j] start point;
- a0-a3 are registers to be saved;
- a4-a15 must be preserved;
- a5 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x0
- .global _WindowOverflow4
-_WindowOverflow4:
-
- s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */
- s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */
- s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */
- s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */
- rfwo /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call4
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call4 to call[i+1].
-On entry here:
- window rotated to call[i] start point;
- a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
- a4-a15 must be preserved (they are call[i+1].reg[0..11]);
- a5 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x40
- .global _WindowUnderflow4
-_WindowUnderflow4:
-
- l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */
- l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */
- l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */
- l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */
- rfwu
-
-/*
---------------------------------------------------------------------------------
-Handle alloca exception generated by interruptee executing 'movsp'.
-This uses space between the window vectors, so is essentially "free".
-All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
-and PS.EXCM has been set by the exception hardware (can't be interrupted).
-The fact the alloca exception was taken means the registers associated with
-the base-save area have been spilled and will be restored by the underflow
-handler, so those 4 registers are available for scratch.
-The code is optimized to avoid unaligned branches and minimize cache misses.
---------------------------------------------------------------------------------
-*/
-
- .align 4
- .global _xt_alloca_exc
-_xt_alloca_exc:
-
- rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */
- rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */
- rsr a2, PS
- extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
- xor a3, a3, a4 /* bits changed from old to current windowbase */
- rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */
- slli a3, a3, XCHAL_PS_OWB_SHIFT
- xor a2, a2, a3 /* flip changed bits in old window base */
- wsr a2, PS /* update PS.OWB to new window base */
- rsync
-
- _bbci.l a4, 31, _WindowUnderflow4
- rotw -1 /* original a0 goes to a8 */
- _bbci.l a8, 30, _WindowUnderflow8
- rotw -1
- j _WindowUnderflow12
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call8
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call8 to call[j+1].
-On entry here:
- window rotated to call[j] start point;
- a0-a7 are registers to be saved;
- a8-a15 must be preserved;
- a9 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x80
- .global _WindowOverflow8
-_WindowOverflow8:
-
- s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */
- l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
- (used to find end of call[j]'s frame) */
- s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */
- s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */
- s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */
- s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */
- s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */
- s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */
- s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */
- rfwo /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call8
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call8 to call[i+1].
-On entry here:
- window rotated to call[i] start point;
- a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
- a8-a15 must be preserved (they are call[i+1].reg[0..7]);
- a9 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0xC0
- .global _WindowUnderflow8
-_WindowUnderflow8:
-
- l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */
- l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */
- l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */
- l32e a7, a1, -12 /* a7 <- call[i-1]'s sp
- (used to find end of call[i]'s frame) */
- l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */
- l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */
- l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */
- l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */
- l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */
- rfwu
-
-/*
---------------------------------------------------------------------------------
-Window Overflow Exception for Call12
-
-Invoked if a call[i] referenced a register (a4-a15)
-that contains data from ancestor call[j];
-call[j] had done a call12 to call[j+1].
-On entry here:
- window rotated to call[j] start point;
- a0-a11 are registers to be saved;
- a12-a15 must be preserved;
- a13 is call[j+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x100
- .global _WindowOverflow12
-_WindowOverflow12:
-
- s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */
- l32e a0, a1, -12 /* a0 <- call[j-1]'s sp
- (used to find end of call[j]'s frame) */
- s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */
- s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */
- s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */
- s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */
- s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */
- s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */
- s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */
- s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */
- s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */
- s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */
- s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */
- rfwo /* rotates back to call[i] position */
-
-/*
---------------------------------------------------------------------------------
-Window Underflow Exception for Call12
-
-Invoked by RETW returning from call[i+1] to call[i]
-where call[i]'s registers must be reloaded (not live in ARs);
-where call[i] had done a call12 to call[i+1].
-On entry here:
- window rotated to call[i] start point;
- a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
- a12-a15 must be preserved (they are call[i+1].reg[0..3]);
- a13 is call[i+1]'s stack pointer.
---------------------------------------------------------------------------------
-*/
-
- .org 0x140
- .global _WindowUnderflow12
-_WindowUnderflow12:
-
- l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */
- l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */
- l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */
- l32e a11, a1, -12 /* a11 <- call[i-1]'s sp
- (used to find end of call[i]'s frame) */
- l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */
- l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */
- l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */
- l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */
- l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */
- l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */
- l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */
- l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */
- l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */
- rfwu
-
-#endif /* XCHAL_HAVE_WINDOWED */
-
- .section .UserEnter.text, "ax"
- .global call_user_start
- .type call_user_start,@function
- .align 4
- .literal_position
-
-
-call_user_start:
-
- movi a2, 0x40040000 /* note: absolute symbol, not a ptr */
- wsr a2, vecbase
- call0 user_start /* user exception handler */
diff --git a/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_02.yml b/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_02.yml
index 61adea982..73618e0d7 100644
--- a/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_02.yml
+++ b/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_02.yml
@@ -4,7 +4,7 @@ Filter:
- Add:
ID: [TCPIP_IGMP_0203, ^TCPIP_TCP_0403, ^TCPIP_TCP_0408, TCPIP_UDP_0201, TCPIP_UDP_0202,
^TCPIP_DHCP_0301, ^TCPIP_TCP_0101, ^TCPIP_TCP_0103, ^TCPIP_TCP_0105, ^TCPIP_TCP_0104,
- ^TCPIP_TCP_0107, ^TCPIP_TCP_0106, ^TCPIP_DHCP_0210, ^TCPIP_DHCP_0211, ^TCPIP_TCP_0404,
- TCPIP_TCP_0212, TCPIP_TCP_0210, ^TCPIP_TCP_0406, ^TCPIP_TCP_0407, ^TCPIP_TCP_0401,
- ^TCPIP_TCP_0210, ^TCPIP_TCP_0212, TCPIP_DHCP_0211, TCPIP_DHCP_0210, TCPIP_DHCP_0101,
- TCPIP_DHCP_0103, TCPIP_DHCP_0102, TCPIP_DHCP_0206, TCPIP_DHCP_0207, ^TCPIP_IP_0102]
+ ^TCPIP_TCP_0107, ^TCPIP_TCP_0106, ^TCPIP_DHCP_0210, ^TCPIP_DHCP_0211, ^TCPIP_DHCP_0212,
+ ^TCPIP_TCP_0404, TCPIP_TCP_0212, TCPIP_TCP_0210, ^TCPIP_TCP_0406, ^TCPIP_TCP_0407,
+ ^TCPIP_TCP_0401, ^TCPIP_TCP_0210, ^TCPIP_TCP_0212, TCPIP_DHCP_0211, TCPIP_DHCP_0210,
+ TCPIP_DHCP_0212, TCPIP_DHCP_0101, TCPIP_DHCP_0103, TCPIP_DHCP_0206, TCPIP_DHCP_0207]
diff --git a/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_03.yml b/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_03.yml
index 9d64630e9..b326ed721 100644
--- a/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_03.yml
+++ b/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_03.yml
@@ -2,7 +2,7 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
- ID: [^TCPIP_UDP_0105, ^TCPIP_UDP_0107, ^TCPIP_UDP_0106, ^TCPIP_UDP_0101, TCPIP_TCP_0203,
+ ID: [^TCPIP_IP_0102, ^TCPIP_UDP_0105, ^TCPIP_UDP_0107, ^TCPIP_UDP_0106, ^TCPIP_UDP_0101,
TCPIP_TCP_0202, ^TCPIP_UDP_0108, ^TCPIP_IGMP_0201, ^TCPIP_IGMP_0203, ^TCPIP_IGMP_0202,
^TCPIP_IGMP_0103, TCPIP_UDP_0114, TCPIP_UDP_0113, TCPIP_UDP_0112, TCPIP_DHCP_0205,
TCPIP_DHCP_0202, TCPIP_DHCP_0203, ^TCPIP_TCP_0102, TCPIP_TCP_0106, TCPIP_TCP_0107,
diff --git a/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_04.yml b/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_04.yml
index 6be01f698..314de4a7e 100644
--- a/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_04.yml
+++ b/components/idf_test/integration_test/CIConfigs/IT_Function_TCPIP_04.yml
@@ -5,6 +5,6 @@ Filter:
ID: [^TCPIP_TCP_0110, ^TCPIP_TCP_0111, TCPIP_DHCP_0209, ^TCPIP_DHCP_0209, ^TCPIP_DHCP_0207,
^TCPIP_DHCP_0206, ^TCPIP_DHCP_0205, ^TCPIP_DHCP_0204, ^TCPIP_DHCP_0203, ^TCPIP_DHCP_0202,
^TCPIP_DHCP_0201, TCPIP_TCP_0204, TCPIP_TCP_0207, TCPIP_TCP_0206, TCPIP_TCP_0201,
- ^TCPIP_DHCP_0101, ^TCPIP_DHCP_0102, ^TCPIP_DHCP_0103, ^TCPIP_DHCP_0208, TCPIP_TCP_0208,
+ ^TCPIP_DHCP_0101, TCPIP_TCP_0203, ^TCPIP_DHCP_0103, ^TCPIP_DHCP_0208, TCPIP_TCP_0208,
^TCPIP_TCP_0202, ^TCPIP_TCP_0203, TCPIP_DHCP_0204, ^TCPIP_TCP_0201, ^TCPIP_TCP_0206,
^TCPIP_TCP_0207, ^TCPIP_TCP_0204, TCPIP_DHCP_0201, ^TCPIP_TCP_0208, TCPIP_DHCP_0208]
diff --git a/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_01.yml b/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_01.yml
index c22bc59bd..9f8424f6d 100644
--- a/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_01.yml
+++ b/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_01.yml
@@ -4,7 +4,7 @@ Filter:
- Add:
ID: [^WIFI_CONN_0601, ^WIFI_ADDR_0101, WIFI_SCAN_0103, WIFI_SCAN_0102, WIFI_SCAN_0101,
WIFI_SCAN_0105, WIFI_SCAN_0104, ^WIFI_CONN_0103, WIFI_CONN_0201, WIFI_CONN_0904,
- ^WIFI_SCAN_0102, ^WIFI_SCAN_0103, ^WIFI_SCAN_0104, ^WIFI_SCAN_0105, WIFI_CONN_0401,
- WIFI_ADDR_0101, WIFI_ADDR_0102, WIFI_CONN_0301, ^WIFI_CONN_0801, ^WIFI_CONN_0301,
- WIFI_CONN_0501, WIFI_CONN_0502, ^WIFI_CONN_0401, WIFI_MODE_0101, WIFI_MODE_0103,
- WIFI_MODE_0102, ^WIFI_CONN_0904, ^WIFI_CONN_0901, WIFI_CONN_0601, ^WIFI_CONN_0201]
+ ^WIFI_SCAN_0102, ^WIFI_SCAN_0103, ^WIFI_SCAN_0104, WIFI_CONN_0401, WIFI_ADDR_0101,
+ WIFI_ADDR_0102, WIFI_CONN_0301, WIFI_SCAN_0301, WIFI_SCAN_0303, ^WIFI_CONN_0801,
+ WIFI_SCAN_0304, ^WIFI_CONN_0301, WIFI_CONN_0501, WIFI_CONN_0502, ^WIFI_CONN_0401,
+ WIFI_MODE_0101, WIFI_MODE_0103, WIFI_MODE_0102, ^WIFI_CONN_0904, ^WIFI_CONN_0901]
diff --git a/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_02.yml b/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_02.yml
index 049054dba..74e6ca612 100644
--- a/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_02.yml
+++ b/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_02.yml
@@ -2,6 +2,6 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
- ID: [^WIFI_ADDR_0102, WIFI_CONN_0901, WIFI_CONN_0801, ^WIFI_CONN_0104, WIFI_CONN_0104,
- WIFI_CONN_0101, WIFI_CONN_0102, WIFI_CONN_0103, ^WIFI_SCAN_0101, ^WIFI_CONN_0101,
- ^WIFI_CONN_0502, ^WIFI_CONN_0501]
+ ID: [WIFI_SCAN_0302, WIFI_CONN_0601, ^WIFI_CONN_0201, ^WIFI_ADDR_0102, WIFI_CONN_0901,
+ WIFI_CONN_0801, ^WIFI_CONN_0104, WIFI_CONN_0104, WIFI_CONN_0101, WIFI_CONN_0102,
+ WIFI_CONN_0103, ^WIFI_SCAN_0101, ^WIFI_CONN_0101, ^WIFI_CONN_0502, ^WIFI_CONN_0501]
diff --git a/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_06.yml b/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_06.yml
index 9d639f912..dd42815a9 100644
--- a/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_06.yml
+++ b/components/idf_test/integration_test/CIConfigs/IT_Function_WIFI_06.yml
@@ -2,6 +2,5 @@ Config: {execute count: 1, execute order: in order}
DUT: [SSC2, SSC1]
Filter:
- Add:
- ID: [WIFI_SCAN_0301, WIFI_SCAN_0303, WIFI_SCAN_0304, WIFI_SCAN_0302, WIFI_SCAN_0201,
- WIFI_PHY_0403, WIFI_PHY_0402, WIFI_PHY_0401, WIFI_PHY_0407, WIFI_PHY_0406, WIFI_PHY_0405,
- WIFI_PHY_0404, WIFI_PHY_0408]
+ ID: [WIFI_SCAN_0201, WIFI_PHY_0403, WIFI_PHY_0402, WIFI_PHY_0401, WIFI_PHY_0407,
+ WIFI_PHY_0406, WIFI_PHY_0405, WIFI_PHY_0404, WIFI_PHY_0408]
diff --git a/components/idf_test/integration_test/KnownIssues b/components/idf_test/integration_test/KnownIssues
index 08bc48f18..e0991f39b 100644
--- a/components/idf_test/integration_test/KnownIssues
+++ b/components/idf_test/integration_test/KnownIssues
@@ -23,10 +23,29 @@ TCPIP_IGMP_0204
^TCPIP_IGMP_0203
^TCPIP_IGMP_0204
+# don't support PHY mode command
+WIFI_SCAN_0201
+WIFI_SCAN_0302
+WIFI_PHY_0401
+WIFI_PHY_0402
+WIFI_PHY_0403
+WIFI_PHY_0404
+WIFI_PHY_0405
+WIFI_PHY_0407
+WIFI_PHY_0406
+WIFI_PHY_0408
+WIFI_PHY_0501
+WIFI_PHY_0502
+WIFI_PHY_0503
+WIFI_PHY_0504
+WIFI_PHY_0505
+WIFI_PHY_0506
+
# BUG
# auth change event
WIFI_CONN_0801
+^WIFI_CONN_0801
# disconnect reason
WIFI_CONN_0904
@@ -37,6 +56,16 @@ WIFI_CONN_0901
# Wifi connect issue
WIFI_CONN_0104
^WIFI_CONN_0104
+^WIFI_CONN_0601
+
+# Wifi scan issue
+WIFI_SCAN_0303
+^WIFI_SCAN_0103
+^WIFI_SCAN_0105
+
+# set mac address may lead to exception
+WIFI_ADDR_0101
+^WIFI_ADDR_0101
# DHCP issues
^TCPIP_DHCP_0301
@@ -46,6 +75,10 @@ TCPIP_DHCP_0207
^TCPIP_DHCP_0207
TCPIP_DHCP_0208
^TCPIP_DHCP_0208
+TCPIP_DHCP_0205
+^TCPIP_DHCP_0205
+TCPIP_DHCP_0209
+^TCPIP_DHCP_0209
# TCP issue
TCPIP_TCP_0402
@@ -54,6 +87,9 @@ TCPIP_TCP_0402
TCPIP_TCP_0210
^TCPIP_TCP_0210
TCPIP_TCP_0103
+^TCPIP_TCP_0103
+TCPIP_TCP_0112
+^TCPIP_TCP_0112
# UDP issue
@@ -61,6 +97,10 @@ TCPIP_UDP_0103
^TCPIP_UDP_0103
TCPIP_UDP_0110
^TCPIP_UDP_0110
+TCPIP_UDP_0305
+^TCPIP_UDP_0305
+^TCPIP_UDP_0304
+TCPIP_UDP_0104
diff --git a/components/idf_test/integration_test/TestCaseAll.yml b/components/idf_test/integration_test/TestCaseAll.yml
index 0835c146b..9e4823a29 100644
--- a/components/idf_test/integration_test/TestCaseAll.yml
+++ b/components/idf_test/integration_test/TestCaseAll.yml
@@ -87,7 +87,7 @@ test cases:
- - SSC SSC1 dhcp -E -o 1
- ['R SSC1 C +DHCP:STA,OK']
- - SSC SSC1 ip -S -i 0.0.0.0
- - ['R SSC1 C +IP:OK']
+ - [R SSC1 C +IP]
- - SSC SSC1 sta -C -s -p
- ['']
- - DELAY 20
@@ -121,54 +121,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: DHCP client function test
- version: v1 (2016-8-15)
-- CI ready: 'Yes'
- ID: TCPIP_DHCP_0102
- SDK: '8266_NonOS
-
- 8266_RTOS
-
- ESP32_IDF'
- Test App: SSC
- allow fail: ''
- auto test: 'Yes'
- category: Function
- cmd set:
- - ''
- - - SSC SSC1 ap -S -s -p -t
- - ['R SSC1 C +SAP:OK']
- - - SSC SSC1 dhcp -E -o 2
- - ['R SSC1 C +DHCP:AP,OK']
- - - SSC SSC2 sta -C -s -p
- - ['']
- - - DELAY 20
- - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
- - - SSC SSC1 dhcp -S -o 2
- - ['R SSC1 C +DHCP:AP,OK']
- - - SSC SSC2 sta -C -s -p
- - ['R SSC2 C +JAP:CONNECTED']
- comment: ''
- execution time: 0.0
- expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
- \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
- initial condition: T2_1
- initial condition description (auto): target 1 as SoftAP, target 2 as STA, will
- autogen a TC with initial condition T2_2
- level: Integration
- module: TCPIP
- steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
- 4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
- sub module: DHCP
- summary: dhcp server function test
- test environment: SSC_T2_1
- test environment description (auto): 'PC has 1 wired NIC connected to AP.
-
- PC has 1 WiFi NIC.
-
- 2 SSC target connect with PC by UART.'
- test point 1: basic function
- test point 2: DHCP client function test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_DHCP_0103
SDK: '8266_NonOS
@@ -927,7 +880,7 @@ test cases:
- ['R SSC1 C +DHCP:AP,OK']
- - SSC SSC2 sta -C -s -p
- ['R SSC2 C +JAP:CONNECTED']
- - - DELAY 10
+ - - DELAY 30
- ['']
- - SSC SSC1 ap -L
- [R SSC1 C 192.168.4.2 C 192.168.4.3 P P ]
@@ -967,6 +920,53 @@ test cases:
test point 1: basic function
test point 2: DHCP server function test
version: v1 (2016-8-15)
+- CI ready: 'Yes'
+ ID: TCPIP_DHCP_0212
+ SDK: '8266_NonOS
+
+ 8266_RTOS
+
+ ESP32_IDF'
+ Test App: SSC
+ allow fail: ''
+ auto test: 'Yes'
+ category: Function
+ cmd set:
+ - ''
+ - - SSC SSC1 ap -S -s -p -t
+ - ['R SSC1 C +SAP:OK']
+ - - SSC SSC1 dhcp -E -o 2
+ - ['R SSC1 C +DHCP:AP,OK']
+ - - SSC SSC2 sta -C -s -p
+ - ['']
+ - - DELAY 20
+ - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
+ - - SSC SSC1 dhcp -S -o 2
+ - ['R SSC1 C +DHCP:AP,OK']
+ - - SSC SSC2 sta -C -s -p
+ - ['R SSC2 C +JAP:CONNECTED']
+ comment: ''
+ execution time: 0.0
+ expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
+ \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+ initial condition: T2_1
+ initial condition description (auto): target 1 as SoftAP, target 2 as STA, will
+ autogen a TC with initial condition T2_2
+ level: Integration
+ module: TCPIP
+ steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
+ 4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+ sub module: DHCP
+ summary: dhcp server function test
+ test environment: SSC_T2_1
+ test environment description (auto): 'PC has 1 wired NIC connected to AP.
+
+ PC has 1 WiFi NIC.
+
+ 2 SSC target connect with PC by UART.'
+ test point 1: basic function
+ test point 2: DHCP server function test
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_DHCP_0301
SDK: '8266_NonOS
@@ -987,7 +987,7 @@ test cases:
- - SSC SSC1 sta -C -s -p
- ['R SSC1 C +JAP:CONNECTED']
- - SSC SSC1 ip -S -i 0.0.0.0 -o 1
- - ['R SSC1 C +IP:OK']
+ - [R SSC1 C +IP]
- - SSC SSC1 sta -C -s -p
- ['']
- - DELAY 10
@@ -1027,7 +1027,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: interaction
test point 2: static IP and DHCP interaction test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_DHCP_0302
SDK: '8266_NonOS
@@ -1143,7 +1143,7 @@ test cases:
category: Function
cmd set:
- ''
- - - SSC SSC1 soc -H -d iot.espressif.cn
+ - - SSC SSC1 soc -H -d factory.espressif.cn
- ['R SSC1 A :\+HOSTIP:OK,(.+)\r\n']
- - SSC SSC1 soc -B -t TCP
- ['R SSC1 A :\+BIND:(\d+),OK']
@@ -1178,7 +1178,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: DNS function test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_DNS_0103
SDK: '8266_NonOS
@@ -1192,7 +1192,7 @@ test cases:
category: Function
cmd set:
- ''
- - - SSC SSC1 soc -H -d iot.espressif.cn
+ - - SSC SSC1 soc -H -d factory.espressif.cn
- ['R SSC1 A :\+HOSTIP:OK,(.+)\r\n']
- - SSC SSC1 soc -B -t UDP
- ['R SSC1 A :\+BIND:(\d+),OK']
@@ -1223,7 +1223,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: DNS function test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_ICMP_0101
SDK: '8266_NonOS
@@ -3189,14 +3189,12 @@ test cases:
- ''
- - SOC SOC1 LISTEN
- [R SOC_COM L OK]
- - - SSC SSC1 soc -B -t TCP
+ - - SSC SSC1 soc -B -t TCP -w 0
- ['R SSC1 A :BIND:(\d+),OK']
- - SSC SSC1 soc -C -s -i -p
- ['R SSC1 RE CONNECT:\d+,OK']
- - SOC SOC1 ACCEPT SOC2
- [R SOC_COM L OK]
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
- - SOC SOC2 SEND 146000
- [P SOC_COM R *]
- - SSC SSC1 soc -W -s -o 1
@@ -3246,7 +3244,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: use TCP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_TCP_0206
SDK: '8266_NonOS
@@ -3280,7 +3278,7 @@ test cases:
- ['R SSC1 A :ACCEPT:(\d+),\d+,.+,\d+']
- - SSC SSC1 soc -I
- ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(,,,)',
- 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(,)',
+ 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(,)',
'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(,,,)']
comment: ''
execution time: 0.0
@@ -3531,14 +3529,12 @@ test cases:
- ''
- - SOC SOC1 LISTEN
- [R SOC_COM L OK]
- - - SSC SSC1 soc -B -t TCP
+ - - SSC SSC1 soc -B -t TCP -w 0
- ['R SSC1 A :BIND:(\d+),OK']
- - SSC SSC1 soc -C -s -i -p
- ['R SSC1 RE CONNECT:\d+,OK']
- - SOC SOC1 ACCEPT SOC2
- [R SOC_COM L OK]
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
- - SOC SOC2 SEND 146000
- [P SOC_COM R *]
- - SSC SSC1 soc -W -s -o 1
@@ -3586,7 +3582,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: use TCP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_TCP_0212
SDK: '8266_NonOS
@@ -3620,7 +3616,7 @@ test cases:
- ['R SSC1 A :ACCEPT:(\d+),\d+,.+,\d+']
- - SSC SSC1 soc -I
- ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(,,,)',
- 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(,)',
+ 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(,)',
'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(,,,)']
comment: ''
execution time: 0.0
@@ -5119,10 +5115,8 @@ test cases:
- ''
- - SOC SOC1 BIND
- [R SOC_COM L OK]
- - - SSC SSC1 soc -B -t UDP -p
+ - - SSC SSC1 soc -B -t UDP -p -w 0
- ['R SSC1 A :BIND:(\d+),OK']
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
- - SOC SOC1 SENDTO 1472
- ['']
- - SOC SOC1 SENDTO 1472
@@ -5180,7 +5174,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: abnormal/special use
test point 2: use UDP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_UDP_0202
SDK: '8266_NonOS
@@ -5198,8 +5192,8 @@ test cases:
- [R SOC_COM L OK]
- - SSC SSC1 soc -B -t UDP -p
- ['R SSC1 A :BIND:(\d+),OK']
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
+ - - SOC SOC1 SENDTO 1472
+ - ['']
- - SOC SOC1 SENDTO 1472
- ['']
- - SOC SOC1 SENDTO 1472
@@ -5257,7 +5251,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: abnormal/special use
test point 2: use UDP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: TCPIP_UDP_0301
SDK: '8266_NonOS
@@ -5874,6 +5868,8 @@ test cases:
- ['R SSC2 RE "\+JAP:CONNECTED,%%s"%%()']
- - SSC SSC1 ap -S -s -n 15
- ['R SSC1 C +SAP:OK']
+ - - SSC SSC2 sta -C -s -p
+ - ['R SSC2 RE "\+JAP:CONNECTED,%%s"%%()']
- - SSC SSC2 sta -S
- ['R SSC2 RE "\+SCAN:%%s,.+,\d+,1"%%()']
comment: ''
@@ -7915,7 +7911,7 @@ test cases:
- - SSC SSC1 sta -S
- ['']
- - SSC SSC1 sta -S
- - [P SSC1 C +SCANFAIL, 'P SSC1 P +SCAN:', R SSC1 C +SCANDONE]
+ - [P SSC1 C +SCANFAIL, 'P SSC1 C +SCAN:', R SSC1 C +SCANDONE]
comment: ''
execution time: 0.0
expected result: '1. second scan failed
@@ -7931,14 +7927,12 @@ test cases:
2. do scan before scan finished'
sub module: WIFI Scan
summary: reject scan request before scan finished
- test environment: SSC_T2_PhyMode
- test environment description (auto): '2 SSC target connect with PC by UART.
+ test environment: SSC_T1_1
+ test environment description (auto): 'PC has 2 wired NIC connected to AP.
- PC has one WiFi NIC support capture wlan packet using libpcap.
+ PC has 1 WiFi NIC.
- Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
-
- Put 4 APs near SSC targets.'
+ 1 SSC target connect with PC by UART.'
test point 1: interaction
test point 2: Scan interact with other WiFi operation
version: v1 (2015-8-15)
@@ -7987,14 +7981,12 @@ test cases:
3. target 2 scan in AP channel in 11b.g,n,ht40 mode'
sub module: WIFI Scan
summary: scan in congest channel
- test environment: SSC_T2_PhyMode
- test environment description (auto): '2 SSC target connect with PC by UART.
+ test environment: SSC_T2_1
+ test environment description (auto): 'PC has 1 wired NIC connected to AP.
- PC has one WiFi NIC support capture wlan packet using libpcap.
+ PC has 1 WiFi NIC.
- Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
-
- Put 4 APs near SSC targets.'
+ 2 SSC target connect with PC by UART.'
test point 1: interaction
test point 2: Scan interact with other WiFi operation
version: v1 (2015-8-15)
@@ -8022,8 +8014,9 @@ test cases:
expected result: '2. scan succeed, JAP succeed
5. JAP succeed, scan succeed'
- initial condition: T2_2
- initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
+ initial condition: STAM1
+ initial condition description (auto): sta mode, quit AP, DHCP on, will autogen a
+ TC with initial condition STAAP1
level: Integration
module: WIFI MAC
steps: '1. target 1 STA join AP
@@ -8037,14 +8030,12 @@ test cases:
5. target 1 JAP before scan succeed'
sub module: WIFI Scan
summary: scan during JAP
- test environment: SSC_T2_PhyMode
- test environment description (auto): '2 SSC target connect with PC by UART.
+ test environment: SSC_T1_1
+ test environment description (auto): 'PC has 2 wired NIC connected to AP.
- PC has one WiFi NIC support capture wlan packet using libpcap.
+ PC has 1 WiFi NIC.
- Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
-
- Put 4 APs near SSC targets.'
+ 1 SSC target connect with PC by UART.'
test point 1: interaction
test point 2: Scan interact with other WiFi operation
version: v1 (2015-8-15)
@@ -8057,6 +8048,8 @@ test cases:
category: Function
cmd set:
- ''
+ - - SSC SSC1 ap -S -s -p -t
+ - ['R SSC1 C +SAP:OK']
- - SSC SSC2 sta -C -s -p
- ['R SSC2 C +JAP:OK']
- - SSC SSC1 sta -S
@@ -8087,14 +8080,12 @@ test cases:
5. target 2 STA JAP before target 1 STA scan succeed'
sub module: WIFI Scan
summary: scan during ext STA join SoftAP
- test environment: SSC_T2_PhyMode
- test environment description (auto): '2 SSC target connect with PC by UART.
+ test environment: SSC_T2_1
+ test environment description (auto): 'PC has 1 wired NIC connected to AP.
- PC has one WiFi NIC support capture wlan packet using libpcap.
+ PC has 1 WiFi NIC.
- Set 4 AP with phy mode 11b, 11g, 11n HT20, 11n HT40.
-
- Put 4 APs near SSC targets.'
+ 2 SSC target connect with PC by UART.'
test point 1: interaction
test point 2: Scan interact with other WiFi operation
version: v1 (2015-8-15)
@@ -8114,7 +8105,7 @@ test cases:
- - SSC SSC1 dhcp -E -o 1
- ['R SSC1 C +DHCP:STA,OK']
- - SSC SSC1 ip -S -i 0.0.0.0
- - ['R SSC1 C +IP:OK']
+ - [R SSC1 C +IP]
- - SSC SSC1 sta -C -s -p
- ['']
- - DELAY 20
@@ -8148,53 +8139,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: DHCP client function test
- version: v1 (2016-8-15)
-- CI ready: 'Yes'
- ID: ^TCPIP_DHCP_0102
- SDK: '8266_NonOS
-
- 8266_RTOS
-
- ESP32_IDF'
- Test App: SSC
- allow fail: ''
- auto test: 'Yes'
- category: Function
- cmd set:
- - ''
- - - SSC SSC1 ap -S -s -p -t
- - ['R SSC1 C +SAP:OK']
- - - SSC SSC1 dhcp -E -o 2
- - ['R SSC1 C +DHCP:AP,OK']
- - - SSC SSC2 sta -C -s -p
- - ['']
- - - DELAY 20
- - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
- - - SSC SSC1 dhcp -S -o 2
- - ['R SSC1 C +DHCP:AP,OK']
- - - SSC SSC2 sta -C -s -p
- - ['R SSC2 C +JAP:CONNECTED']
- comment: ''
- execution time: 0.0
- expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
- \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
- initial condition: T2_2
- initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
- level: Integration
- module: TCPIP
- steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
- 4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
- sub module: DHCP
- summary: dhcp server function test
- test environment: SSC_T2_1
- test environment description (auto): 'PC has 1 wired NIC connected to AP.
-
- PC has 1 WiFi NIC.
-
- 2 SSC target connect with PC by UART.'
- test point 1: basic function
- test point 2: DHCP client function test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_DHCP_0103
SDK: '8266_NonOS
@@ -8943,7 +8888,7 @@ test cases:
- ['R SSC1 C +DHCP:AP,OK']
- - SSC SSC2 sta -C -s -p
- ['R SSC2 C +JAP:CONNECTED']
- - - DELAY 10
+ - - DELAY 30
- ['']
- - SSC SSC1 ap -L
- [R SSC1 C 192.168.4.2 C 192.168.4.3 P P ]
@@ -8982,6 +8927,52 @@ test cases:
test point 1: basic function
test point 2: DHCP server function test
version: v1 (2016-8-15)
+- CI ready: 'Yes'
+ ID: ^TCPIP_DHCP_0212
+ SDK: '8266_NonOS
+
+ 8266_RTOS
+
+ ESP32_IDF'
+ Test App: SSC
+ allow fail: ''
+ auto test: 'Yes'
+ category: Function
+ cmd set:
+ - ''
+ - - SSC SSC1 ap -S -s -p -t
+ - ['R SSC1 C +SAP:OK']
+ - - SSC SSC1 dhcp -E -o 2
+ - ['R SSC1 C +DHCP:AP,OK']
+ - - SSC SSC2 sta -C -s -p
+ - ['']
+ - - DELAY 20
+ - [P PC_COM C +DELAYDONE, 'P SSC2 NC +JAP:CONNECTED']
+ - - SSC SSC1 dhcp -S -o 2
+ - ['R SSC1 C +DHCP:AP,OK']
+ - - SSC SSC2 sta -C -s -p
+ - ['R SSC2 C +JAP:CONNECTED']
+ comment: ''
+ execution time: 0.0
+ expected result: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target\
+ \ 1,FAIL \n4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+ initial condition: T2_2
+ initial condition description (auto): target 1 as AP+STA, target 2 as AP+STA (autogen)
+ level: Integration
+ module: TCPIP
+ steps: "1.target1 set AP OK \n2.target1 关闭DHCP OK\n3.target2 jap target 1,FAIL \n\
+ 4.target1 打开DHCP OK\n5.target2 jap target 1,ok"
+ sub module: DHCP
+ summary: dhcp server function test
+ test environment: SSC_T2_1
+ test environment description (auto): 'PC has 1 wired NIC connected to AP.
+
+ PC has 1 WiFi NIC.
+
+ 2 SSC target connect with PC by UART.'
+ test point 1: basic function
+ test point 2: DHCP server function test
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_DHCP_0301
SDK: '8266_NonOS
@@ -9002,7 +8993,7 @@ test cases:
- - SSC SSC1 sta -C -s -p
- ['R SSC1 C +JAP:CONNECTED']
- - SSC SSC1 ip -S -i 0.0.0.0 -o 1
- - ['R SSC1 C +IP:OK']
+ - [R SSC1 C +IP]
- - SSC SSC1 sta -C -s -p
- ['']
- - DELAY 10
@@ -9042,7 +9033,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: interaction
test point 2: static IP and DHCP interaction test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_DHCP_0302
SDK: '8266_NonOS
@@ -9157,7 +9148,7 @@ test cases:
category: Function
cmd set:
- ''
- - - SSC SSC1 soc -H -d iot.espressif.cn
+ - - SSC SSC1 soc -H -d factory.espressif.cn
- ['R SSC1 A :\+HOSTIP:OK,(.+)\r\n']
- - SSC SSC1 soc -B -t TCP
- ['R SSC1 A :\+BIND:(\d+),OK']
@@ -9192,7 +9183,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: DNS function test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_DNS_0103
SDK: '8266_NonOS
@@ -9206,7 +9197,7 @@ test cases:
category: Function
cmd set:
- ''
- - - SSC SSC1 soc -H -d iot.espressif.cn
+ - - SSC SSC1 soc -H -d factory.espressif.cn
- ['R SSC1 A :\+HOSTIP:OK,(.+)\r\n']
- - SSC SSC1 soc -B -t UDP
- ['R SSC1 A :\+BIND:(\d+),OK']
@@ -9237,7 +9228,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: DNS function test
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_ICMP_0101
SDK: '8266_NonOS
@@ -11199,14 +11190,12 @@ test cases:
- ''
- - SOC SOC1 LISTEN
- [R SOC_COM L OK]
- - - SSC SSC1 soc -B -t TCP
+ - - SSC SSC1 soc -B -t TCP -w 0
- ['R SSC1 A :BIND:(\d+),OK']
- - SSC SSC1 soc -C -s -i -p
- ['R SSC1 RE CONNECT:\d+,OK']
- - SOC SOC1 ACCEPT SOC2
- [R SOC_COM L OK]
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
- - SOC SOC2 SEND 146000
- [P SOC_COM R *]
- - SSC SSC1 soc -W -s -o 1
@@ -11254,7 +11243,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: use TCP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_TCP_0206
SDK: '8266_NonOS
@@ -11288,7 +11277,7 @@ test cases:
- ['R SSC1 A :ACCEPT:(\d+),\d+,.+,\d+']
- - SSC SSC1 soc -I
- ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(,,,)',
- 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(,)',
+ 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(,)',
'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(,,,)']
comment: ''
execution time: 0.0
@@ -11539,14 +11528,12 @@ test cases:
- ''
- - SOC SOC1 LISTEN
- [R SOC_COM L OK]
- - - SSC SSC1 soc -B -t TCP
+ - - SSC SSC1 soc -B -t TCP -w 0
- ['R SSC1 A :BIND:(\d+),OK']
- - SSC SSC1 soc -C -s -i -p
- ['R SSC1 RE CONNECT:\d+,OK']
- - SOC SOC1 ACCEPT SOC2
- [R SOC_COM L OK]
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
- - SOC SOC2 SEND 146000
- [P SOC_COM R *]
- - SSC SSC1 soc -W -s -o 1
@@ -11592,7 +11579,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: basic function
test point 2: use TCP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_TCP_0212
SDK: '8266_NonOS
@@ -11626,7 +11613,7 @@ test cases:
- ['R SSC1 A :ACCEPT:(\d+),\d+,.+,\d+']
- - SSC SSC1 soc -I
- ['P SSC1 RE "SOCINFO:%%s,2,%%s,\d+,%%s,%%d"%%(,,,)',
- 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d,.+,\d+"%%(,)',
+ 'P SSC1 RE "SOCINFO:%%s,2,.+,\d+,.+,\d+"%%()', 'P SSC1 RE "SOCINFO:%%s,82,.+,%%d"%%(,)',
'P SSC1 RE "SOCINFO:%%s,2,%%s,%%d,%%s,\d+"%%(,,,)']
comment: ''
execution time: 0.0
@@ -12981,10 +12968,8 @@ test cases:
- ''
- - SOC SOC1 BIND
- [R SOC_COM L OK]
- - - SSC SSC1 soc -B -t UDP -p
+ - - SSC SSC1 soc -B -t UDP -p -w 0
- ['R SSC1 A :BIND:(\d+),OK']
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
- - SOC SOC1 SENDTO 1472
- ['']
- - SOC SOC1 SENDTO 1472
@@ -13042,7 +13027,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: abnormal/special use
test point 2: use UDP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_UDP_0202
SDK: '8266_NonOS
@@ -13060,8 +13045,8 @@ test cases:
- [R SOC_COM L OK]
- - SSC SSC1 soc -B -t UDP -p
- ['R SSC1 A :BIND:(\d+),OK']
- - - SSC SSC1 soc -W -s -o 0
- - ['R SSC1 RE WORKTHREAD:\d+,OK']
+ - - SOC SOC1 SENDTO 1472
+ - ['']
- - SOC SOC1 SENDTO 1472
- ['']
- - SOC SOC1 SENDTO 1472
@@ -13119,7 +13104,7 @@ test cases:
1 SSC target connect with PC by UART.'
test point 1: abnormal/special use
test point 2: use UDP SAP (socket/espconn API) in different state
- version: v1 (2016-8-15)
+ version: v2 (2016-10-19)
- CI ready: 'Yes'
ID: ^TCPIP_UDP_0301
SDK: '8266_NonOS
@@ -14652,67 +14637,3 @@ test cases:
test point 1: basic function
test point 2: scan with different config
version: v1 (2016-8-15)
-- CI ready: 'Yes'
- ID: ^WIFI_SCAN_0105
- SDK: '8266_NonOS
-
- 8266_RTOS
-
- ESP32_IDF'
- Test App: SSC
- allow fail: ''
- auto test: 'Yes'
- category: Function
- cmd set:
- - ''
- - - SSC SSC1 sta -D
- - ['R SSC1 C +QAP:']
- - - SSC SSC1 ap -S -s -p 123456789 -t 3 -h 0 -n 11
- - ['R SSC1 C +SAP:OK']
- - - SSC SSC2 sta -S -s -b -n 11
- - [R SSC2 P C +SCANDONE]
- - - SSC SSC2 sta -S -s -b -n 11
- - [R SSC2 NP C +SCANDONE]
- - - SSC SSC2 sta -S -s -b ff:ff:ff:ff:ff:11 -n 11
- - [R SSC2 P , R SSC2 NP C +SCANDONE]
- - - SSC SSC2 sta -S -s -b -n 10
- - [R SSC2 P , R SSC2 NP C +SCANDONE]
- comment: ''
- execution time: 0.0
- expected result: '1.target1 QAP
-
- 2. target1 set AP,set ssid broad cast,set channel 11
-
- 3.target2 上查询到
-
- 4.target2 上查询不到
-
- 5.target2 上查询不到
-
- 6.target2 上查询不到