From 06afe9be456877d26656aeb3fc98916059425747 Mon Sep 17 00:00:00 2001 From: arnabcdns <32582604+arnabcdns@users.noreply.github.com> Date: Wed, 29 May 2019 10:20:47 -0700 Subject: [PATCH] Xtensa port version 2.0. Major reorg of Xtensa port sources. See readme and relnotes files for details. --- demos/cadence/sim/README.TXT | 108 ---- .../application_code/cadence_code/example.c | 535 +++++++----------- .../application_code/cadence_code/xt_alloca.c | 2 +- .../application_code/cadence_code/xt_clib.c | 326 ++++------- .../application_code/cadence_code/xt_coproc.c | 2 +- .../application_code/cadence_code/xt_intr.c | 8 +- .../sim/common/config_files/FreeRTOSConfig.h | 18 +- lib/FreeRTOS/portable/XCC/Xtensa/Makefile | 4 +- lib/FreeRTOS/portable/XCC/Xtensa/port.c | 406 ++++++++----- lib/FreeRTOS/portable/XCC/Xtensa/portasm.S | 205 ++----- lib/FreeRTOS/portable/XCC/Xtensa/portclib.c | 7 + lib/FreeRTOS/portable/XCC/Xtensa/portmacro.h | 105 ++-- .../portable/XCC/Xtensa/readme_xtensa.txt | 64 +-- lib/FreeRTOS/portable/XCC/Xtensa/relnotes.txt | 123 ++++ lib/FreeRTOS/portable/XCC/Xtensa/xtensa_api.h | 70 ++- .../portable/XCC/Xtensa/xtensa_config.h | 35 +- .../portable/XCC/Xtensa/xtensa_context.S | 220 +------ .../XCC/Xtensa/xtensa_coproc_handler.S | 535 ++++++++++++++++++ .../portable/XCC/Xtensa/xtensa_init.c | 66 --- .../portable/XCC/Xtensa/xtensa_intr.c | 187 ++++-- .../portable/XCC/Xtensa/xtensa_intr_asm.S | 165 +++--- .../portable/XCC/Xtensa/xtensa_rtos.h | 8 +- .../portable/XCC/Xtensa/xtensa_vectors.S | 279 +-------- 23 files changed, 1713 insertions(+), 1765 deletions(-) create mode 100644 lib/FreeRTOS/portable/XCC/Xtensa/relnotes.txt create mode 100644 lib/FreeRTOS/portable/XCC/Xtensa/xtensa_coproc_handler.S delete mode 100644 lib/FreeRTOS/portable/XCC/Xtensa/xtensa_init.c diff --git a/demos/cadence/sim/README.TXT b/demos/cadence/sim/README.TXT index 1a18608217e..9d638acdddb 100644 --- a/demos/cadence/sim/README.TXT +++ b/demos/cadence/sim/README.TXT @@ -1,8 +1,4 @@ -Release Notes for FreeRTOS Xtensa port --------------------------------------- - - How to build and run the tests ------------------------------ @@ -55,109 +51,5 @@ If you build from Xplorer, remember to enable -mlongcalls in the Assembler options for certain targets (e.g. when you get the linker warning: dangerous relocation). - -Notes for version 1.7 ---------------------- - -- portSTACK_TYPE changed to uint32_t from uint8_t. Stack size definitions - adjusted accordingly. - -- portYIELD_FROM_ISR changed to call _frxt_setup_switch conditionally. - -- Tick handler calls xTaskIncrementTick inside critical region to prevent - interrupt nesting issues. - - -Notes for version 1.6 ---------------------- - -- This version supports FreeRTOS version 10.0.0. - -- The directory structure and makefiles have been reorganized to conform - to the structure of FreeRTOS version 10.0.0. - - -Notes for version 1.5 ---------------------- - -- This version supports FreeRTOS version 9.0.0. - -- This version supports thread safe operation with the Xtensa C Library - (xclib) in addition to the Newlib C library (newlib). - The xtensa_config.h file is set up to enable thread safe operation by - default if xclib or newlib is detected. Use -D XT_USE_THREAD_SAFE_CLIB=0 - on the command line or in the project definition to disable this. - -- Incorrect function prototypes for xt_ints_on/xt_ints_off have been fixed. - - -Notes for version 1.4.2 ------------------------ - -- This version implements a bugfix. The bug was that even when the - config parameter "configUSE_TIME_SLICING" was set to zero, time - slicing would still occur due to a problem in the Xtensa interrupt - processing code. - -- The "small_test" test has been added to illustrate how FreeRTOS - can be configured to reduce the memory footprint. - - -Notes for version 1.4 ---------------------- - -- This version supports FreeRTOS version 8.2.0. - -- This version adds a new test xt_intr.c for interrupts testing. - -- This version separates the trace and benchmark facilities into a - separate downloadable. - - -Notes for version 1.3 ---------------------- - -- This version implements a separate interrupt stack. The interrupt - dispatch code saves the current task's state on to the task's own - stack and then switches to the interrupt stack for the interrupt - processing. Nested interrupts will continue to use the interrupt - stack. This helps to reduce the sizes of task stacks, since task - stacks no longer have to account for space to accommodate possible - nested interrupts. The size of the interrupt stack is controlled - by a config parameter. - - -Notes for version 1.2 ---------------------- - -- This version supports FreeRTOS version 8.1.2. - -- This version supports both CALL0 and windowed Xtensa configurations. - -- This version supports thread safe operation for the Newlib C library. - -- This version introduces an API for installing low/medium priority - interrupt handlers and exception handlers, which can be written in C. - See xtensa_api.h for details. - -- This version supports software prioritization of interrupts at the - same level. Define XT_USE_SWPRI to use this feature. Higher-numbered - interrupts are handled at a higher priority than lower-numbered ones. - -- The FreeRTOS demo application requires a stack size of at least 4 KB. - The standalone tests should be able to run with smaller stack sizes. - The minimum stack size depends on the specific Xtensa configuration. - Adjust the stack size of your application as required. - -- The examples are all defined with a heap size of 256 KB. This could - be a problem with Xtensa configurations that have only small amounts - of memory. Adjust the heap size to suit your platform and application. - There is an example of a small-footprint configuration in the directory - Xtensa_XCC_small. - -- NOTE: Code overlay support is not yet enabled for this port, even though - the support code is present. This feature is not enabled nor tested. - Do not define XT_USE_OVLY when building. - -End- diff --git a/demos/cadence/sim/common/application_code/cadence_code/example.c b/demos/cadence/sim/common/application_code/cadence_code/example.c index bc4bec42572..7f90c31708c 100644 --- a/demos/cadence/sim/common/application_code/cadence_code/example.c +++ b/demos/cadence/sim/common/application_code/cadence_code/example.c @@ -1,5 +1,6 @@ -/******************************************************************************* -// Copyright (c) 2003-2015 Cadence Design Systems, Inc. + +//----------------------------------------------------------------------------- +// Copyright (c) 2003-2019 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 @@ -19,53 +20,25 @@ // 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. --------------------------------------------------------------------------------- -*/ - -/* -********************************************************************************************************* -* -* EXAMPLE APPLICATION -* -* This is a simple example application for the Xtensa port of FreeRTOSI. -* It does not rely on a C library so can run on practically anything. -* If compiled with C library support (XT_USE_THREAD_SAFE_CLIB), uses C -* library stdio output instead of putstr() and outbyte(). -* -* Target : All Xtensa configurable and Diamond preconfigured processors. -* -********************************************************************************************************* -*/ - -#include -#include -#include -#include +//----------------------------------------------------------------------------- -#ifdef XT_BOARD -#include -#endif +//----------------------------------------------------------------------------- +// This is a simple example to demonstrate the Xtensa port of FreeRTOS. +//----------------------------------------------------------------------------- -#include "FreeRTOS.h" -#include "semphr.h" -#include "event_groups.h" +#include +#include + +#include "FreeRTOS.h" +#include "semphr.h" +#include "event_groups.h" #include -#if XT_USE_THREAD_SAFE_CLIB > 0u -#include +#if (XT_USE_THREAD_SAFE_CLIB > 0) +#include #endif -// There should be no need to check port_xSchedulerRunning; from main, don't call protected putline function. -// But we'll keep it to test this flag. -extern unsigned int port_xSchedulerRunning; - -/* -The first task to be created should have highest priority of those created by -main(), so that it runs first (it may create other tasks of higher priority). -Priority inheritance priorities are specified here too so all priorities are -defined in one place to make their relationships obvious. -*/ #define NEWLIB_MUTEX_PRIO 6 // prio above any task that uses C library #define CONS_MUTEX_PRIO 5 // prio above any task doing line output @@ -73,361 +46,234 @@ defined in one place to make their relationships obvious. #define COUNT_TASK_PRIO 3 #define REPORT_TASK_PRIO 2 - #ifdef XT_BOARD -/* A low priority task puts something on the display for equipped boards. */ +#include +// A low priority task puts something on the display for equipped boards. #define DISPLAY_TASK_PRIO 1 #endif +// Default task stack size. +#define TASK_STK_SIZE (XT_STACK_MIN_SIZE + 0x400) -/* -********************************************************************************************************* -* SHARED DATA -********************************************************************************************************* -*/ - -/* Stack size for tasks that do not use the C library. */ -#define TASK_STK_SIZE_MIN (XT_STACK_MIN_SIZE) +// Flags set by each task on completion. +#define TASK_TERM_INIT (1<<0) +#define TASK_TERM_REPORT (1<<1) +#define TASK_TERM_COUNT (1<<2) -/* Stack size for tasks that use the C library and/or the coprocessors */ -#define TASK_STK_SIZE_STD (0x1000 + XT_STACK_EXTRA_CLIB) +// Message queue size. +#define QUEUE_SIZE 10 -/* Mutex to avoid interleaving lines on console output. */ -SemaphoreHandle_t ConsMutex; - -/* Flags set by each task on completion, just before it terminates. */ -#define TASK_TERM_INIT (1<<0) -#define TASK_TERM_REPORT (1<<1) -#define TASK_TERM_COUNT (1<<2) EventGroupHandle_t TaskTermFlags; +QueueHandle_t Queue; +TaskHandle_t Count_Task_TCB; +TaskHandle_t Report_Task_TCB; -/* Queue for passing count. */ -#define QUEUE_SIZE 10 -QueueHandle_t Queue; - -/* -********************************************************************************************************* -* LOCAL FUNCTIONS -********************************************************************************************************* -*/ - -#if XT_USE_THREAD_SAFE_CLIB > 0u -#define putstr(s) printf(s) -#define outbyte(c) putchar(c);fflush(stdout) +#if (XT_USE_THREAD_SAFE_CLIB > 0) +#define PRINTF(s) printf(s);fflush(stdout) +#define PUTCHAR(c) putchar(c);fflush(stdout) #else -/* Output a simple string to the console. */ -static void putstr(const char *s) -{ - char c; - unsigned err = 0; - - while ((c = *s) != '\0') { - if (c == '\n') { - outbyte('\r'); - outbyte('\n'); - } - else if (iscntrl(c) && c != '\r') { - outbyte('^'); - outbyte('@' + c); - } - else outbyte(c); - ++s; - } -} -#endif /* XT_USE_THREAD_SAFE_CLIB */ - -/* -Output a line to the console and terminate it with '\n'. Protected by a mutex to prevent lines -from different tasks interleaving. To allow this to be used before tasks are running (eg. in -main), the port_xSchedulerRunning flag is checked before using the mutex. -*/ -static void putline(const char *s) -{ - if (port_xSchedulerRunning) { - xSemaphoreTake(ConsMutex, portMAX_DELAY); - } - - putstr(s); - putstr("\n"); - - if (port_xSchedulerRunning) { - xSemaphoreGive(ConsMutex); - } -} - -/* -Print a 32-bit decimal unsigned integer as a string, into a buffer with room for 10 chars + NUL. -Return the pointer to the beginning of the string. The string is right-aligned in the buffer -with leading spaces (padding) that can be useful for right-aligning columns of numbers. -*/ -static char *put_u32dec(char buf[11], const unsigned n) -{ - char *p, *l; - unsigned quo, rem; - - /* Print the number in reverse. */ - buf[10] = '\0'; - p = &buf[9]; - for (quo = n; quo >= 10; quo /= 10) { - rem = quo % 10; - *p-- = '0' + rem; - } - assert(quo < 10); - *p = '0' + quo; +#define PRINTF(s) +#define PUTCHAR(c) +#endif - /* Pad the beginning of the buffer. */ - for (l = &buf[0]; l < p; ++l) - *l = ' '; - return p; -} - -/* -********************************************************************************************************* -* DISPLAY TASK -* -* Display something on display-equipped boards to show FreeRTOS Xtensa example is running. -* Meant to be lightweight and low-priority because LCD displays may require lots of busy-waiting. -* -********************************************************************************************************* -*/ +//----------------------------------------------------------------------------- +// Display Task. Display something on display-equipped boards to show the +// FreeRTOS Xtensa example is running. +//----------------------------------------------------------------------------- #ifdef XT_BOARD -#define DISPLAY_TASK_STK_SIZE TASK_STK_SIZE_MIN +#define DISPLAY_TASK_STK_SIZE TASK_STK_SIZE -void Display_Task(void *pdata) +void Display_Task( void * pdata ) { - while(1) + while( 1 ) { - xtbsp_display_string("FreeRTOS Xtensa"); + xtbsp_display_string( "FreeRTOS Xtensa" ); vTaskDelay(configTICK_RATE_HZ); - xtbsp_display_string("Counting Example"); + xtbsp_display_string( "Counting Example" ); vTaskDelay(configTICK_RATE_HZ); } } -#endif /* XT_BOARD */ - - -/* -********************************************************************************************************* -* COUNT TASK -* -* This task counts at regular intervals and places the cumulative count in the queue to Report_Task. -* If the queue is full, the count will be skipped and the next count posted a second later. -* -********************************************************************************************************* -*/ - +#endif -#define COUNT_TASK_STK_SIZE TASK_STK_SIZE_STD -TaskHandle_t Count_Task_TCB; -void Count_Task(void *pdata) +//----------------------------------------------------------------------------- +// Count Task. Counts at regular intervals and sends the count via queue to +// the Report Task. +//----------------------------------------------------------------------------- +void Count_Task( void * pdata ) { - unsigned count = 0; + uint32_t count = 1; + + PRINTF( "[Count_Task] Started.\n" ); - putline("[Count_Task] Started."); + // Count at regular intervals and place counter in queue. + PRINTF( "[Count_Task] Counting.\n" ); - /* Count at regular intervals and place counter in queue. */ - putline("[Count_Task] Counting."); - do { - xQueueSend(Queue, (void*)&count, portMAX_DELAY); + while ( 1 ) + { + xQueueSend( Queue, (void *) &count, 2 ); ++count; - vTaskDelay(configTICK_RATE_HZ / 5); + vTaskDelay( 1 ); #ifdef XT_SIMULATOR - /* On simulator, stop after a number of iterations (to bound run-time for testing). */ - if (count >= 250) + // On simulator, stop after a number of iterations. + if ( count > 250 ) + { break; + } #endif - } while (1); + } + + // Send a last message to terminate the Report Task. + count = 0xFFFFFFFF; + xQueueSend( Queue, (void *) &count, portMAX_DELAY ); - putline(""); - putline("[Count_Task] Terminating."); + PRINTF( "\n[Count_Task] Terminating.\n" ); - /* Set termination flag to alert Init_Task. */ - xEventGroupSetBits(TaskTermFlags, TASK_TERM_COUNT); + // Set termination flag to alert Init_Task. + xEventGroupSetBits( TaskTermFlags, TASK_TERM_COUNT ); - /* Terminate this task. RTOS will continue to run timer, stats and idle tasks. */ - vTaskDelete(NULL); - /* Does not reach here. */ + // Terminate this task. RTOS will continue to run other tasks. + vTaskDelete( NULL ); } -/* -********************************************************************************************************* -* REPORT TASK -* -* This task waits on a message queue for a series on numbers from Count_Task (these should be -* incrementing by 1 in the sequence received) and reports progress in a readable format that -* fits in 80 columns. -* If it doesn't receive any count from the count task for a few seconds, it terminates. -* -********************************************************************************************************* -*/ - -#define REPORT_TASK_STK_SIZE TASK_STK_SIZE_STD -unsigned char Report_Task_Stack [REPORT_TASK_STK_SIZE] __attribute__ ((aligned(0x10))); // Let's try one non heap task -TaskHandle_t Report_Task_TCB; - -void Report_Task(void *pdata) + +//----------------------------------------------------------------------------- +// The Report Task waits for messages coming through the queue from the Count +// Task and reports progress. It terminates when it receives a magic value for +// the message. +//----------------------------------------------------------------------------- +void Report_Task( void * pdata ) { - static unsigned prev = 0; - unsigned count, tens, ones; - int err = 0; - char buf[11]; - - putline("[Report_Task] Started."); - - /* Acquire console mutex, wait on queue and report, until count task signals termination. */ - /* NOTE: this can create a deadlock when Init_Task can't create Count_Task */ - // xSemaphoreTake(ConsMutex, portMAX_DELAY); - do { - err = xQueueReceive(Queue, &count, 3*configTICK_RATE_HZ); - if (err == pdFAIL) // Timeout + uint32_t count; + int32_t err = 0; + + PRINTF( "[Report_Task] Started.\n" ); + + while ( 1 ) + { + err = xQueueReceive( Queue, &count, 2 ); + if ( err == pdFAIL ) + { + // Error break; - tens = count / 10; - ones = count % 10; - xSemaphoreTake(ConsMutex, portMAX_DELAY); - if (count % 50 == 0) { - put_u32dec(buf, tens); - if (tens == 0) // special case: suppress 0 in tens column if tens == 0 - buf[9] = ' '; - putstr("\n "); - putstr(" "); - putstr(buf); - putstr("0+"); } - if (ones == 0) - outbyte(' '); - outbyte('0' + ones); - xSemaphoreGive(ConsMutex); - prev = count; - } while (1); - - putline(""); - putline("[Report_Task] Terminating."); - - /* Set termination flag to alert Init_Task. */ - xEventGroupSetBits(TaskTermFlags, TASK_TERM_REPORT); - - /* Terminate this task. RTOS will continue to run timer, stats and idle tasks. */ - vTaskDelete(NULL); - /* Does not reach here. */ -} -/* -********************************************************************************************************* -* APP INITIALZATION TASK -* -* This is the first application task created, before starting. -* It can create other tasks. -* -********************************************************************************************************* -*/ + if ( count == 0xFFFFFFFF ) + { + // End + break; + } -#define INIT_TASK_STK_SIZE TASK_STK_SIZE_STD + PUTCHAR( '.' ); + if ( (count > 0) && (count % 10 == 0) ) + { + PUTCHAR( ' ' ); + } + if ( (count > 0) && (count % 50 == 0) ) + { + PUTCHAR( '\n' ); + } + } -void Init_Task(void *pdata) -{ - int err = 0; - int exit_code = 0; + PRINTF( "\n[Report_Task] Terminating.\n" ); - /* Create mutex for console access before putstr() can be used. */ - ConsMutex = xSemaphoreCreateMutex(); - if (ConsMutex == NULL) - goto done; + // Set termination flag to alert Init_Task. + xEventGroupSetBits( TaskTermFlags, TASK_TERM_REPORT ); + + // Terminate this task. RTOS will continue to run other tasks. + vTaskDelete( NULL ); +} - putline("[Init_Task] Started!"); - /* Create event flag group for task termination. */ - putline("[Init_Task] Creating event flag group for task termination."); +//----------------------------------------------------------------------------- +// The Init Task creates the other tasks and waits for them to finish. +//----------------------------------------------------------------------------- +void Init_Task( void * pdata ) +{ + int32_t err = 0; + int32_t exit_code = 0; + + PRINTF( "[Init_Task] Started.\n" ); + + // Create event flag group for task termination. + PRINTF( "[Init_Task] Creating event flag group for task termination.\n" ); TaskTermFlags = xEventGroupCreate(); - if (TaskTermFlags == NULL) { - putline("...FAILED .1!"); + if ( TaskTermFlags == NULL ) + { + PRINTF( "...FAILED .1!\n" ); goto done; } - /* Create queue for sequence of counts. */ - putline("[Init_Task] Creating queue for sequence of counts."); - Queue = xQueueCreate(QUEUE_SIZE, sizeof(unsigned)); - if (Queue == NULL) { - putline("...FAILED .2!"); + // Create queue for sequence of counts. + PRINTF( "[Init_Task] Creating queue for sequence of counts.\n" ); + Queue = xQueueCreate( QUEUE_SIZE, sizeof(uint32_t) ); + if ( Queue == NULL ) + { + PRINTF( "...FAILED .2!\n" ); err = 101; goto done; } - /* Create reporting task. */ - putline("[Init_Task] Creating reporting task Report_Task."); + // Create reporting task. + PRINTF( "[Init_Task] Creating reporting task Report_Task.\n" ); - // This version supplies stack buffer (not auto-allocated on heap); just for testing - //err = xTaskGenericCreate(Report_Task, "Report_Task", REPORT_TASK_STK_SIZE, NULL, REPORT_TASK_PRIO, Report_Task_TCB, Report_Task_Stack, NULL); - err = xTaskCreate(Report_Task, "Report_Task", REPORT_TASK_STK_SIZE, NULL, REPORT_TASK_PRIO, &Report_Task_TCB); - if (err != pdPASS) + err = xTaskCreate( Report_Task, "Report_Task", TASK_STK_SIZE, NULL, REPORT_TASK_PRIO, &Report_Task_TCB ); + if ( err != pdPASS ) { - putline("...FAILED! .3"); + PRINTF( "...FAILED! .3!\n" ); goto done; } - /* Create counting task. */ - putline("[Init_Task] Creating counting task Count_Task."); - err = xTaskCreate(Count_Task, "Count_Task", COUNT_TASK_STK_SIZE, NULL, COUNT_TASK_PRIO, &Count_Task_TCB); - if (err != pdPASS) + // Create counting task. + PRINTF( "[Init_Task] Creating counting task Count_Task.\n" ); + err = xTaskCreate( Count_Task, "Count_Task", TASK_STK_SIZE, NULL, COUNT_TASK_PRIO, &Count_Task_TCB ); + if ( err != pdPASS ) { - putline("...FAILED! .4"); + PRINTF( "...FAILED! .4!\n" ); goto done; } #ifdef XT_BOARD - /* Create display task, if board has a display. */ - if (xtbsp_display_exists()) { - putline("[Init_Task] Creating display task Display_Task."); - err = xTaskCreate(Display_Task, "Display_Task", DISPLAY_TASK_STK_SIZE, NULL, DISPLAY_TASK_PRIO, NULL); - if (err != pdPASS) + // Create display task, if board has a display. + if ( xtbsp_display_exists() ) + { + PRINTF( "[Init_Task] Creating display task Display_Task.\n" ); + err = xTaskCreate( Display_Task, "Display_Task", TASK_STK_SIZE, NULL, DISPLAY_TASK_PRIO, NULL ); + if ( err != pdPASS ) { - putline("...FAILED! .5"); + PRINTF( "...FAILED! .5!\n" ); goto done; } } -#endif /* XT_BOARD */ +#endif - /* Wait for counting and reporting tasks to finish. */ - putline("[Init_Task] Waiting for counting and reporting tasks to finish."); - xEventGroupWaitBits(TaskTermFlags, TASK_TERM_REPORT | TASK_TERM_COUNT, 0, pdTRUE, portMAX_DELAY); + // Wait for counting and reporting tasks to finish. + PRINTF( "[Init_Task] Waiting for counting and reporting tasks to finish.\n" ); + xEventGroupWaitBits( TaskTermFlags, TASK_TERM_REPORT | TASK_TERM_COUNT, 0, pdTRUE, portMAX_DELAY ); done: - /* Clean up and shut down. */ - exit_code = (err != pdPASS); - putline("[Init_Task] Cleaning up resources and terminating."); + // Clean up and shut down. + exit_code = ( err != pdPASS ); + PRINTF( "[Init_Task] Cleaning up resources and terminating.\n" ); - vQueueDelete(Queue); - vEventGroupDelete(TaskTermFlags); - vSemaphoreDelete(ConsMutex); + vQueueDelete( Queue ); + vEventGroupDelete( TaskTermFlags ); #ifdef XT_SIMULATOR - /* This string indicates test passed. */ - if (exit_code == 0) { - putline("PASS"); + // This string indicates test passed. + if ( exit_code == 0 ) + { + PRINTF( "PASS\n" ); } - /* Shut down simulator and report error code as exit code to host (0 = OK). */ - _exit(exit_code); + // Shut down simulator and report error code as exit code to host (0 = OK). + exit( exit_code ); #endif - /* Terminate this task. RTOS will continue to run timer, stats and idle tasks. */ - vTaskDelete(NULL); - /* Does not reach here. */ + // Terminate this task. RTOS will continue to run other tasks. + vTaskDelete( NULL ); } -/* -********************************************************************************************************* -* C ENTRY POINT -* -* Initializes FreeRTOS after the platorm's run-time system has initialized the basic platform. -* Creates at least the first task, which can then create other tasks. -* Starts multitasking. -* -********************************************************************************************************* -*/ - -/* Hook functions for standalone tests */ -#ifdef STANDALONE #if configUSE_TICK_HOOK void vApplicationTickHook( void ) @@ -435,44 +281,41 @@ void vApplicationTickHook( void ) } #endif -void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ) + +void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ) { - /* For some reason printing pcTaskName is not working */ - puts("\nStack overflow, stopping."); - exit(0); + puts( "\nStack overflow, stopping." ); + exit( 0 ); } -int main(int argc, char *argv[]) -#else -int main_example(int argc, char *argv[]) -#endif +int main( int argc, char * argv[] ) { - unsigned err = 0; + uint32_t err = 0; - #ifdef XT_BOARD - /* Display waypoint for debugging. Display task will identify this example later. */ - xtbsp_display_string("main()"); - #endif +#ifdef XT_BOARD + // Display waypoint for debugging. + xtbsp_display_string( "main()" ); +#endif - putline("\nFreeRTOS example on Xtensa."); - putline("Xtensa port version " XTENSA_PORT_VERSION_STRING); + PRINTF( "\nFreeRTOS example on Xtensa.\n" ); + PRINTF( "Xtensa port version " XTENSA_PORT_VERSION_STRING "\n" ); - /* Create only the Init_Task here. It will create the others. */ - putline("[main] Creating first task Init_Task."); - err = xTaskCreate(Init_Task, "Init_Task", INIT_TASK_STK_SIZE, NULL, INIT_TASK_PRIO, NULL); + // Create only the Init_Task here. It will create the others. + PRINTF( "[main] Creating first task Init_Task.\n" ); + err = xTaskCreate( Init_Task, "Init_Task", TASK_STK_SIZE, NULL, INIT_TASK_PRIO, NULL ); - if (err != pdPASS) + if ( err != pdPASS ) { - putline("FAILED! main"); + PRINTF( "FAILED! main\n" ); return 1; } - /* Start task scheduler */ - putline("[main] Starting multi-tasking."); - vTaskStartScheduler(); + // Start task scheduler. + PRINTF( "[main] Starting multi-tasking.\n" ); + vTaskStartScheduler(); - /* If we got here then scheduler failed. */ - putline("vTaskStartScheduler FAILED!"); + // If we got here then scheduler failed. + PRINTF( "vTaskStartScheduler FAILED!\n" ); return 1; } diff --git a/demos/cadence/sim/common/application_code/cadence_code/xt_alloca.c b/demos/cadence/sim/common/application_code/cadence_code/xt_alloca.c index fc5c1e07b13..4a8b78f5ec0 100644 --- a/demos/cadence/sim/common/application_code/cadence_code/xt_alloca.c +++ b/demos/cadence/sim/common/application_code/cadence_code/xt_alloca.c @@ -154,7 +154,7 @@ static int test_alloca(void) */ #define TASK_INIT_PRIO 20 -#define INIT_TASK_STK_SIZE (0x1000 + XT_STACK_EXTRA_CLIB) +#define INIT_TASK_STK_SIZE (XT_STACK_EXTRA + 0x1000) static void Init_Task(void *pdata) { diff --git a/demos/cadence/sim/common/application_code/cadence_code/xt_clib.c b/demos/cadence/sim/common/application_code/cadence_code/xt_clib.c index 234292772f3..a2f22922fdd 100644 --- a/demos/cadence/sim/common/application_code/cadence_code/xt_clib.c +++ b/demos/cadence/sim/common/application_code/cadence_code/xt_clib.c @@ -1,5 +1,6 @@ -/******************************************************************************* -// Copyright (c) 2003-2015 Cadence Design Systems, Inc. + +//----------------------------------------------------------------------------- +// Copyright (c) 2003-2019 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 @@ -19,32 +20,28 @@ // 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. --------------------------------------------------------------------------------- -*/ - -/* -********************************************************************************************************* -* -* C LIBRARY TEST -* -* This test exercises the C library thread safety mechanism in the Xtensa port of FreeRTOS. -* It verifies that every task that specifies C library context save gets its own private -* save area, and tasks that do not specify this get to share a global context area. -* -* This test is only meaningful if XT_USE_THREAD_SAFE_CLIB is enabled. -* Currently this test works only for the newlib and xclib C libraries as they are the only -* ones supporting thread safety. -* -* Target : All Xtensa configurable and Diamond preconfigured processors. -********************************************************************************************************* -*/ +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// This test checks that the C library per-thread context is being properly +// maintained by the OS. When a thread is running, the global C context must +// point to this thread's C library context. This test is only meaningful if +// XT_USE_THREAD_SAFE_CLIB is enabled. Thread support is only available with +// the newlib C library and the Xtensa C library (xclib). +//----------------------------------------------------------------------------- -#include "FreeRTOS.h" #include +#include #include -#if XT_USE_THREAD_SAFE_CLIB > 0u +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#include + +#if (XT_USE_THREAD_SAFE_CLIB > 0) #include #else #warning XT_USE_THREAD_SAFE_CLIB not defined, this test will do nothing. @@ -54,142 +51,77 @@ #include #endif -#include - -#include "task.h" -#include "queue.h" -/* -********************************************************************************************************* -* SHARED DATA AND MACROS -********************************************************************************************************* -*/ +// Task stack sizes. Can be reduced if printf() etc. are not called. +#define TASK_STK_SIZE (XT_STACK_MIN_SIZE + 0x800) -/* Stack size for tasks that do not use the C library */ -#define TASK_STK_SIZE_MIN (XT_STACK_MIN_SIZE + XT_STACK_EXTRA) +// Uniform prefix for reporting PASS/FAIL test results. +#define TEST_PFX "Xtensa C library context switch test (xt_clib)" -/* Stack size for tasks that use the C library and the coprocessors */ -#define TASK_STK_SIZE_STD (0x1000 + XT_STACK_EXTRA_CLIB) +// Number of concurrent tasks. +#define NTASKS 4 -/* Uniform prefix for reporting PASS/FAIL test results. */ -#define TEST_PFX "Xtensa C library context switch test (xt_clib)" +// Byte offset of C context pointer inside TCB. We cannot detect this at +// compile time because the TCB struct is not exposed to user code. +// If the TCB changes in size then manually adjust this offset to match. +#define IMPURE_PTR_OFFSET 0x4C -#define NTASKS 1 -unsigned int result[NTASKS]; +uint32_t result[NTASKS]; +TaskHandle_t Task_TCB[NTASKS]; -// Hack to access TCB's content (xNewLib_reent) for test purposes -typedef struct -{ - volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ - - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ - #endif - - ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ - ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ - UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ - StackType_t *pxStack; /*< Points to the start of the stack. */ - char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - - #if ( portSTACK_GROWTH > 0 ) - StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ - #endif - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ - UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ - #endif - - #if ( configUSE_MUTEXES == 1 ) - UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ - UBaseType_t uxMutexesHeld; - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - TaskHookFunction_t pxTaskTag; - #endif - - #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; - #endif - - #if( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ - #endif - - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - /* Allocate a Newlib reent structure that is specific to this task. - Note Newlib support has been included by popular demand, but is not - used by the FreeRTOS maintainers themselves. FreeRTOS is not - responsible for resulting newlib operation. User must be familiar with - newlib and must provide system-wide implementations of the necessary - stubs. Be warned that (at the time of writing) the current newlib design - implements a system-wide malloc() that must be provided with locks. */ - struct _reent xNewLib_reent; - #endif - - // Truncated after this point - -} clibTCB_t; -extern volatile clibTCB_t * volatile pxCurrentTCB; - -/* -********************************************************************************************************* -* APPLICATION TASKS -********************************************************************************************************* -*/ +extern volatile uint32_t * volatile pxCurrentTCB; -TaskHandle_t Task_TCB[NTASKS]; -void Task_Func(void *pdata) +// Task function. +void Task_Func( void * pdata ) { - int val = (int) pdata; - unsigned cnt = 0; - void *test_p; + int32_t val = (int32_t) pdata; + uint32_t cnt = 0; + void * test_p; - srand(val); + srand( val ); -#if XT_USE_THREAD_SAFE_CLIB > 0u +#if (XT_USE_THREAD_SAFE_CLIB > 0) - while (cnt < 400) { + while ( cnt < 400 ) + { #if XSHAL_CLIB == XTHAL_CLIB_XCLIB || XSHAL_CLIB == XTHAL_CLIB_NEWLIB - if (pxCurrentTCB) + if ( pxCurrentTCB ) { - // Note that _impure_ptr (newlib) is redefined as _reent_ptr in the case of - // xclib. - if ((uint32_t)_impure_ptr != (uint32_t)(&pxCurrentTCB->xNewLib_reent)) { - // A failure might mean that the hack definition of TCB in this file, xt_clib.c, - // is out of date with respect to the official definition in tasks.c. - printf("Task %d, Bad reent ptr\n", val); - exit(1); + // Note that _impure_ptr (newlib) is redefined as _reent_ptr in the case of + // xclib. + if ( _impure_ptr != (void *)(&pxCurrentTCB[IMPURE_PTR_OFFSET/4]) ) + { + // A failure might mean that the hack definition of TCB in this file, xt_clib.c, + // is out of date with respect to the official definition in tasks.c. + printf( "Task %d, Bad reent ptr\n", val ); + exit( 1 ); } } - else { - printf("Task %d, Bad TCB pointer!\n", val); // This means there is some corruption - exit(2); + else + { + printf( "Task %d, Bad TCB pointer!\n", val ); // This means there is some corruption + exit( 2 ); } #else #error Unsupported C library #endif - test_p = malloc(rand() % 500); - if (!test_p) { - printf("Task %d, malloc() failed\n", val); - exit(3); + test_p = malloc( rand() % 500 ); + if ( !test_p ) + { + printf( "Task %d, malloc() failed\n", val ); + exit( 3 ); } - if (val == 0 && cnt % 100 == 99) { - printf("100...\n"); + if ( (val == 0) && (cnt % 100 == 99) ) + { + printf( "100...\n" ); } - vTaskDelay(1); - free(test_p); + vTaskDelay( 1 ); + free( test_p ); cnt++; } @@ -198,132 +130,106 @@ void Task_Func(void *pdata) // No thread-safe library, nothing to do test_p = 0; cnt = 0; - vTaskDelay(1); + vTaskDelay( 1 ); #endif result[val] = 1; - vTaskDelete(NULL); + vTaskDelete( NULL ); } -/* -********************************************************************************************************* -* APP INITIALZATION TASK -* -* It initializes the RTOS, creates the other tasks, controls the test and reports the results. -* -********************************************************************************************************* -*/ - -#define INIT_TASK_STK_SIZE (TASK_STK_SIZE_MIN) - -static void Init_Task(void *pdata) +// Init Task. +static void Init_Task( void * pdata ) { - int t0, t1; - int i, busy; - int err = 0; + int32_t t0; + int32_t t1; + int32_t i; + int32_t busy; + int32_t err = 0; - for (i = 0; i < NTASKS; ++i) { - /* Create the application tasks (all are lower priority so wait for us). */ - err = xTaskCreate(Task_Func, "Task", TASK_STK_SIZE_STD, (void*)i, 18, &Task_TCB[i]); + for ( i = 0; i < NTASKS; ++i ) + { + // Create the application tasks (all are lower priority so wait for us). + err = xTaskCreate( Task_Func, "Task", TASK_STK_SIZE, (void *) i, 18, &Task_TCB[i] ); - if (err != pdPASS) + if ( err != pdPASS ) { - printf(TEST_PFX " FAILED to create Task\n"); + printf( TEST_PFX " FAILED to create Task\n" ); goto done; } } - /* The test begins here. */ + // The test begins here. t0 = xTaskGetTickCount(); - /* Simulate round-robin of the application tasks every tick. Stop when all results are in. */ - do { + // Simulate round-robin of the application tasks every tick. + do + { busy = 0; - for (i = 0; i < NTASKS; ++i) { - //vTaskPrioritySet(Task_TCB[i], 21); - vTaskDelay(NTASKS); - //vTaskPrioritySet(Task_TCB[i], 22); - busy |= result[i] == 0.0; + for ( i = 0; i < NTASKS; ++i ) + { + //vTaskPrioritySet(Task_TCB[i], 21); + vTaskDelay( NTASKS ); + //vTaskPrioritySet(Task_TCB[i], 22); + busy |= ( result[i] == 0 ); } - } while (busy); + } + while ( busy ); - /* The test ends here. Pause to let application tasks shut down cleanly. */ t1 = xTaskGetTickCount(); - //vTaskDelay(NTASKS); - - printf(TEST_PFX " PASSED!\n"); + printf( TEST_PFX " PASSED!\n" ); done: - #ifdef XT_SIMULATOR - /* Shut down simulator and report error code as exit code to host (0 = OK). */ - exit(0); - #endif +#ifdef XT_SIMULATOR + // Shut down simulator and report error code as exit code to host (0 = OK). + exit( 0 ); +#endif - /* Terminate this task. RTOS will continue to run timer, stats and idle tasks. */ - vTaskDelete(NULL); + // Terminate this task. RTOS will continue to run timer, stats and idle tasks. + vTaskDelete( NULL ); } -/* -********************************************************************************************************* -* C ENTRY POINT -* -* Initializes FreeRTOS after the platorm's run-time system has initialized the basic platform. -* Creates at least the first task, which can then create other tasks. -* Starts multitasking. -* -********************************************************************************************************* -*/ - -/* Hook functions for standalone tests */ -#ifdef STANDALONE - -#if configUSE_TICK_HOOK -void vApplicationTickHook( void ) + +void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ) { + puts( "\nStack overflow, stopping." ); + exit( -1 ); } -#endif -void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ) + +void vApplicationTickHook( void ) { - /* For some reason printing pcTaskName is not working */ - puts("\nStack overflow, stopping."); - exit(0); } -int main(void) -#else -int main_xt_clib(int argc, char *argv[]) -#endif + +int main( void ) { int err = 0; int exit_code = 0; - printf(TEST_PFX " running...\n"); - - /* Create the control task initially with the high priority. */ - err = xTaskCreate(Init_Task, "Init_Task", INIT_TASK_STK_SIZE, NULL, 20, NULL); + printf( TEST_PFX " running...\n" ); + // Create the control task initially with the high priority. + err = xTaskCreate( Init_Task, "Init_Task", TASK_STK_SIZE, NULL, 20, NULL ); - if (err != pdPASS) + if ( err != pdPASS ) { - printf(TEST_PFX " FAILED to create Init_Task\n"); + printf( TEST_PFX " FAILED to create Init_Task\n" ); goto done; } - /* Start task scheduler */ - vTaskStartScheduler(); + // Start task scheduler. + vTaskStartScheduler(); done: exit_code = err; #ifdef XT_SIMULATOR - /* Shut down simulator and report error code as exit code to host (0 = OK). */ - exit(exit_code); + // Shut down simulator and report error code as exit code to host (0 = OK). + exit( exit_code ); #endif - /* Does not reach here ('return' statement keeps compiler happy). */ return 0; } diff --git a/demos/cadence/sim/common/application_code/cadence_code/xt_coproc.c b/demos/cadence/sim/common/application_code/cadence_code/xt_coproc.c index 708e73bc8d8..3cd49588c39 100644 --- a/demos/cadence/sim/common/application_code/cadence_code/xt_coproc.c +++ b/demos/cadence/sim/common/application_code/cadence_code/xt_coproc.c @@ -76,7 +76,7 @@ #define TASK_STK_SIZE_MIN (XT_STACK_MIN_SIZE) /* Stack size for tasks that use the C library and/or the coprocessors */ -#define TASK_STK_SIZE_STD (0x1000 + XT_STACK_EXTRA_CLIB) +#define TASK_STK_SIZE_STD (XT_STACK_EXTRA + 0x1000) /* Uniform prefix for reporting PASS/FAIL test results. */ #define TEST_PFX "Xtensa co-processor context-switch test (xt_coproc)" diff --git a/demos/cadence/sim/common/application_code/cadence_code/xt_intr.c b/demos/cadence/sim/common/application_code/cadence_code/xt_intr.c index e9331ecee37..294a67deee0 100644 --- a/demos/cadence/sim/common/application_code/cadence_code/xt_intr.c +++ b/demos/cadence/sim/common/application_code/cadence_code/xt_intr.c @@ -69,7 +69,7 @@ volatile int iExcCount = 0; /* Stack size for tasks that do not use the C library. */ #define TASK_STK_SIZE_MIN (XT_STACK_MIN_SIZE) /* Stack size for tasks that use the C library and/or the coprocessors */ -#define TASK_STK_SIZE_STD (0x1000 + XT_STACK_EXTRA_CLIB) +#define TASK_STK_SIZE_STD (XT_STACK_EXTRA + 0x1000) /* Queue for passing count. */ #define QUEUE_SIZE 16 @@ -189,13 +189,13 @@ static void Task1(void *pvData) /* Set up interrupt handling and enable interrupt */ xt_set_interrupt_handler(uiSwIntNum, softwareIntHandler, (void*)xSem); - xt_ints_on(1 << uiSwIntNum); + xt_interrupt_enable(uiSwIntNum); #ifdef XT_USE_SWPRI /* Set up the higher priority interrupt if available */ if (uiSwInt2Num) { xt_set_interrupt_handler(uiSwInt2Num, softwareHighHandler, 0); - xt_ints_on(1 << uiSwInt2Num); + xt_interrupt_enable(uiSwInt2Num); } #endif @@ -213,7 +213,7 @@ static void Task1(void *pvData) putchar('+'); /* Now trigger the interrupt handler */ - xt_set_intset(1 << uiSwIntNum); + xt_interrupt_trigger(uiSwIntNum); } #ifdef DEMO_USE_PRINTF diff --git a/demos/cadence/sim/common/config_files/FreeRTOSConfig.h b/demos/cadence/sim/common/config_files/FreeRTOSConfig.h index 3d87760f3e6..66f0e5bfce9 100644 --- a/demos/cadence/sim/common/config_files/FreeRTOSConfig.h +++ b/demos/cadence/sim/common/config_files/FreeRTOSConfig.h @@ -74,7 +74,17 @@ /* Required for configuration-dependent settings */ #include "xtensa_config.h" -/*----------------------------------------------------------- +/* + *----------------------------------------------------------------------------- + * Xtensa port specific definitions. These are required for proper operation + * and must not be changed. + *----------------------------------------------------------------------------- + */ + +#define configRECORD_STACK_HIGH_ADDRESS 1 + +/* + *----------------------------------------------------------------------------- * Application specific definitions. * * These definitions should be adjusted for your particular hardware and @@ -86,7 +96,8 @@ * * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - *----------------------------------------------------------*/ + *----------------------------------------------------------------------------- + */ #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 @@ -99,6 +110,9 @@ #define configTICK_RATE_HZ ( 50 ) +/* Use port-defined tickless idle */ +#define configUSE_TICKLESS_IDLE 2 + /* Default clock rate for simulator */ #define configCPU_CLOCK_HZ 2000000 diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/Makefile b/lib/FreeRTOS/portable/XCC/Xtensa/Makefile index 2b295e0e3d8..17e30b13a07 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/Makefile +++ b/lib/FreeRTOS/portable/XCC/Xtensa/Makefile @@ -60,8 +60,10 @@ IFLAGS = \ -I$(FR_SRCDIR)$(S)..$(S)include -I$(FR_SRCDIR)$(S)..$(S)include$(S)private \ -I$(XT_SRCDIR) -I$(TSTROOT)$(S)common$(S)config_files -I$(BLDDIR) +CSTD = -std=c99 CFLAGS = -O2 -g -CCFLAGS = $(CFLAGS) -Wall -mno-coproc -mlongcalls -ffunction-sections -mno-l32r-flix $(DFLAGS) +WFLAGS = -Werror -Wall -Wextra +CCFLAGS = $(CSTD) $(CFLAGS) $(WFLAGS) -mno-coproc -mlongcalls -ffunction-sections -mno-l32r-flix $(DFLAGS) ASFLAGS = $(CCFLAGS) # Include dependency rules (generated using -MD) diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/port.c b/lib/FreeRTOS/portable/XCC/Xtensa/port.c index 371ccfa2def..68c09f8cfe8 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/port.c +++ b/lib/FreeRTOS/portable/XCC/Xtensa/port.c @@ -51,172 +51,318 @@ */ #include -#include +#include + +#include "xtensa_api.h" #include "xtensa_rtos.h" #include "FreeRTOS.h" #include "task.h" -/* Defined in portasm.h */ -extern void _frxt_tick_timer_init(void); - -/* Defined in xtensa_context.S */ -extern void _xt_coproc_init(void); +// Defined in xtensa_context.S. +extern void _xt_coproc_init( void ); +// Defined in xtensa_vectors.S. +extern void _xt_task_start( void ); -/*-----------------------------------------------------------*/ +// Timer tick interval in cycles. +static uint32_t xt_tick_cycles; -/* We require the address of the pxCurrentTCB variable, but don't want to know -any details of its type. */ -typedef void TCB_t; -extern volatile TCB_t * volatile pxCurrentTCB; +// Flag to indicate tick handling should be skipped. +static uint32_t xt_skip_tick; -unsigned port_xSchedulerRunning = 0; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting -unsigned port_interruptNesting = 0; // Interrupt nesting level +// Duplicate of inaccessible xSchedulerRunning. +uint32_t port_xSchedulerRunning = 0U; -/*-----------------------------------------------------------*/ +// Interrupt nesting level. +uint32_t port_interruptNesting = 0U; -// User exception dispatcher when exiting -void _xt_user_exit(void); -/* - * Stack initialization - */ -#if portUSING_MPU_WRAPPERS -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) -#else -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) -#endif +//----------------------------------------------------------------------------- +// Tick timer interrupt handler. +//----------------------------------------------------------------------------- +static void xt_tick_handler( void ) { - StackType_t *sp, *tp; - XtExcFrame *frame; - #if XCHAL_CP_NUM > 0 - uint32_t *p; - #endif - - /* Create interrupt stack frame aligned to 16 byte boundary */ - sp = (StackType_t *) (((UBaseType_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf); - - /* Clear the entire frame (do not use memset() because we don't depend on C library) */ - for (tp = sp; tp <= pxTopOfStack; ++tp) - *tp = 0; - - frame = (XtExcFrame *) sp; - - /* Explicitly initialize certain saved registers */ - frame->pc = (UBaseType_t) pxCode; /* task entrypoint */ - frame->a0 = 0; /* to terminate GDB backtrace */ - frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */ - frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */ - - /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ - /* Also set entry point argument parameter. */ - #ifdef __XTENSA_CALL0_ABI__ - frame->a2 = (UBaseType_t) pvParameters; - frame->ps = PS_UM | PS_EXCM; - #else - /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */ - frame->a6 = (UBaseType_t) pvParameters; - frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1); - #endif - - #ifdef XT_USE_SWPRI - /* Set the initial virtual priority mask value to all 1's. */ - frame->vpri = 0xFFFFFFFF; - #endif - - #if XCHAL_CP_NUM > 0 - /* Init the coprocessor save area (see xtensa_context.h) */ - /* No access to TCB here, so derive indirectly. Stack growth is top to bottom. - * //p = (uint32_t *) xMPUSettings->coproc_area; - */ - p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf); - p[0] = 0; - p[1] = 0; - p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN; - #endif - - return sp; + uint32_t diff; + + // Skip if flag set, but clear flag. + if (xt_skip_tick > 0) { + xt_skip_tick = 0; + return; + } + + do + { + BaseType_t ret; + uint32_t interruptMask; + uint32_t ulOldCCompare = xt_get_ccompare( XT_TIMER_INDEX ); + + // Set CCOMPARE for next tick. + xt_set_ccompare( XT_TIMER_INDEX, ulOldCCompare + xt_tick_cycles ); + + portbenchmarkIntLatency(); + + // Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be + // disabled before calling xTaskIncrementTick as it accesses the + // kernel lists. + interruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + ret = xTaskIncrementTick(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask ); + + portYIELD_FROM_ISR( ret ); + + diff = xt_get_ccount() - ulOldCCompare; + } + while ( diff > xt_tick_cycles ); } -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) +//----------------------------------------------------------------------------- +// Tick timer init. Install interrupt handler, set up first tick, and +// enable timer interrupt. +//----------------------------------------------------------------------------- +static void xt_tick_timer_init( void ) { - /* It is unlikely that the Xtensa port will get stopped. If required simply - disable the tick interrupt here. */ + // Compute the number of cycles per tick. + #ifdef XT_CLOCK_FREQ + xt_tick_cycles = ( XT_CLOCK_FREQ / XT_TICK_PER_SEC ); + #else + #ifdef XT_BOARD + xt_tick_cycles = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; + #else + #error "No way to obtain processor clock frequency" + #endif + #endif + + xt_set_interrupt_handler( XT_TIMER_INTNUM, (xt_handler) xt_tick_handler, 0 ); + xt_set_ccompare( XT_TIMER_INDEX, xthal_get_ccount() + xt_tick_cycles ); + xt_interrupt_enable( XT_TIMER_INTNUM ); } -/*-----------------------------------------------------------*/ +//----------------------------------------------------------------------------- +// Tick timer stop. Disable timer interrupt and clear ccompare register. +//----------------------------------------------------------------------------- +static void xt_tick_timer_stop( void ) +{ + xt_interrupt_disable( XT_TIMER_INTNUM ); + xt_set_ccompare( XT_TIMER_INDEX, 0 ); +} +//----------------------------------------------------------------------------- +// Start the scheduler. +//----------------------------------------------------------------------------- BaseType_t xPortStartScheduler( void ) { - // Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored + // Interrupts are disabled at this point and stack contains PS with + // enabled interrupts when task context is restored. - #if XCHAL_CP_NUM > 0 - /* Initialize co-processor management for tasks. Leave CPENABLE alone. */ - _xt_coproc_init(); - #endif + #if XCHAL_CP_NUM > 0 + // Initialize co-processor management for tasks. Leave CPENABLE alone. + _xt_coproc_init(); + #endif - /* Init the tick divisor value */ - _xt_tick_divisor_init(); + // Set up and enable timer tick. + xt_tick_timer_init(); - /* Setup the hardware to generate the tick. */ - _frxt_tick_timer_init(); + #if XT_USE_THREAD_SAFE_CLIB + // Init C library + vPortClibInit(); + #endif - #if XT_USE_THREAD_SAFE_CLIB - // Init C library - vPortClibInit(); - #endif + port_xSchedulerRunning = 1U; - port_xSchedulerRunning = 1; + // Cannot be directly called from C; never returns + __asm__ volatile ("call0 _frxt_dispatch\n"); - // Cannot be directly called from C; never returns - __asm__ volatile ("call0 _frxt_dispatch\n"); - - /* Should not get here. */ - return pdTRUE; + // Should never get here. + return pdFALSE; } -/*-----------------------------------------------------------*/ -BaseType_t xPortSysTickHandler( void ) +//----------------------------------------------------------------------------- +// Stop the scheduler. +//----------------------------------------------------------------------------- +void vPortEndScheduler( void ) { - BaseType_t ret; - uint32_t interruptMask; - - portbenchmarkIntLatency(); - - /* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be - * disabled before calling xTaskIncrementTick as it access the - * kernel lists. */ - interruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); - { - ret = xTaskIncrementTick(); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask ); - - portYIELD_FROM_ISR( ret ); - - return ret; + xt_tick_timer_stop(); + port_xSchedulerRunning = 0U; } -/*-----------------------------------------------------------*/ -/* - * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area. - */ -#if portUSING_MPU_WRAPPERS -void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) +//----------------------------------------------------------------------------- +// Stack initialization. +// Reserve coprocessor save area if needed, construct a dummy stack frame and +// populate it for task startup. Return adjusted top-of-stack pointer, which +// is also the pointer to the dummy stack frame. +// (NOTE: the value returned from this function is expected to be stored in +// pxTCB->pxTopOfStack. In the task wrapper code, we will copy this value into +// pxTCB->pxEndOfStack, which will then be treated as the coprocessor state +// area pointer. +//----------------------------------------------------------------------------- +StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) { - #if XCHAL_CP_NUM > 0 - xMPUSettings->coproc_area = (StackType_t*)((((uint32_t)(pxBottomOfStack + ulStackDepth - 1)) - XT_CP_SIZE ) & ~0xf); - + StackType_t *sp, *tp; + XtExcFrame *frame; + #if XCHAL_CP_NUM > 0 + uint32_t *p; + #endif + + // Allocate enough space for coprocessor state, align base address. This is the + // adjusted top-of-stack. + sp = (StackType_t *) ((((uint32_t) pxTopOfStack) - (uint32_t) XT_CP_SIZE) & ~0xF); + + // Allocate interrupt stack frame. XT_STK_FRMSZ is always a multiple of 16 bytes + // so 16-byte alignment is ensured. + tp = sp - (XT_STK_FRMSZ/sizeof(StackType_t)); + frame = (XtExcFrame *) tp; + + // Clear the frame (do not use memset() because we don't depend on C library). + for (; tp < sp; ++tp) + { + *tp = 0; + } + + // Explicitly initialize certain saved registers. + frame->pc = (UBaseType_t) pxCode; // task entrypoint + frame->a0 = 0; // to terminate GDB backtrace + frame->a1 = (UBaseType_t) sp; // physical top of stack frame + frame->exit = (UBaseType_t) _xt_task_start; // task start wrapper + + // Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. + // Also set entry point argument parameter. + #ifdef __XTENSA_CALL0_ABI__ + frame->a2 = (UBaseType_t) pvParameters; + frame->ps = PS_UM | PS_EXCM; + #else + // + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). + frame->a6 = (UBaseType_t) pvParameters; + frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1); + #endif + + #ifdef XT_USE_SWPRI + // Set the initial virtual priority mask value to all 1's. + frame->vpri = 0xFFFFFFFF; + #endif + + #if XCHAL_CP_NUM > 0 + // Init the coprocessor save area (see xtensa_context.h). + p = (uint32_t *) sp; + p[0] = 0; + p[1] = 0; + p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN; + #endif + + return (StackType_t *) frame; +} - /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to - * clear the stack area after we return. This is done in pxPortInitialiseStack(). - */ - #endif +//----------------------------------------------------------------------------- +// Tickless idle support. Suppress N ticks and sleep when directed by kernel. +//----------------------------------------------------------------------------- +#if ( configUSE_TICKLESS_IDLE != 0 ) +void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) +{ + TickType_t xMaxSuppressedTicks = 0xFFFFFFFFU / xt_tick_cycles; + eSleepModeStatus eSleepStatus; + uint32_t num_cycles; + uint32_t ps; + + // Compute number of cycles to sleep for, capped by max limit. + // we use one less than the number of ticks because we are already + // partway through the current tick. This is adjusted later below. + if ( xExpectedIdleTime > xMaxSuppressedTicks ) + { + num_cycles = xt_tick_cycles * ( xMaxSuppressedTicks - 1U ); + } + else + { + num_cycles = xt_tick_cycles * ( xExpectedIdleTime - 1U ); + } + + // Lock out all interrupts. Otherwise reading and using ccount can + // get messy. Shouldn't be a problem here since we are about to go + // to sleep, and the waiti will re-enable interrupts shortly. + ps = XT_RSIL( XCHAL_NUM_INTLEVELS ); + + eSleepStatus = eTaskConfirmSleepModeStatus(); + if ( eSleepStatus == eAbortSleep ) + { + // Abort, fall through. + } + else + { + uint32_t cnt1; + uint32_t cnt2; + uint32_t ticks; + uint32_t save_ccompare = xt_get_ccompare( XT_TIMER_INDEX ); + + // We don't want the timer handler to be run before execution can + // resume after waiti, so set the skip flag. + xt_skip_tick = 1; + + // Adjust for the remaining time in the current tick period. + cnt1 = xthal_get_ccount(); + num_cycles += save_ccompare - cnt1; + + if ( (save_ccompare - cnt1) > xt_tick_cycles ) + { + // The only way this can happen is if the interrupt is pending. + XT_WSR_PS( ps ); + return; + } + + // Set up for timer interrupt and sleep. + xt_set_ccompare( XT_TIMER_INDEX, cnt1 + num_cycles ); + XT_WAITI( 0 ); + + // Block interrupts again before messing around with ccount. + XT_RSIL( XCHAL_NUM_INTLEVELS ); + cnt2 = xthal_get_ccount(); + + // Set up the next tick. This works whether we were woken up by the + // tick interrupt or some other interrupt. It pulls in the next tick + // interrupt if we were woken by something else. + + // Set up the next tick. How we do it depends on what woke us up. + // If we still haven't reached the 'old' tick target (save_ccompare) + // then obviously we were woken by another interrupt. Set the next + // tick time back to what it was, as long as it is not so close to + // ccount as to risk ccount going past it while we are setting it. + if ( (int32_t)(save_ccompare - cnt2) > 100 ) + { + xt_set_ccompare( XT_TIMER_INDEX, save_ccompare ); + } + else + { + xt_set_ccompare( XT_TIMER_INDEX, xt_tick_cycles - ((cnt2 - cnt1) % xt_tick_cycles) + cnt2 ); + } + + // Step the tick count forward by the number of ticks that actually + // elapsed before wakeup, less 1. + ticks = ( cnt2 - cnt1 ) / xt_tick_cycles; + + if ( ticks > 1U ) + { + vTaskStepTick( ticks - 1U ); + } + else + { + // We need to keep track of partial tick periods spent in sleep + // else the tick count will fall behind. + static uint32_t accum_cycles = 0U; + + accum_cycles += cnt2 - cnt1; + while ( accum_cycles > xt_tick_cycles ) + { + vTaskStepTick( 1 ); + accum_cycles -= xt_tick_cycles; + } + } + } + + XT_WSR_PS( ps ); } #endif diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/portasm.S b/lib/FreeRTOS/portable/XCC/Xtensa/portasm.S index 03852d8c5c6..1e7a5651e77 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/portasm.S +++ b/lib/FreeRTOS/portable/XCC/Xtensa/portasm.S @@ -24,10 +24,11 @@ #include "xtensa_rtos.h" -#define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */ -#define CP_TOPOFSTACK_OFFS 0x04 /* xMPU_SETTINGS.coproc_area */ +#define MPUSETTINGS_SIZE 0x00 /* Size of MPU settings struct */ +#define TOS_OFFSET 0x00 /* pxTCB->pxTopOfStack offset */ +#define EOS_OFFSET (0x3C + MPUSETTINGS_SIZE) /* pxTCB->pxEndOfStack offset */ -.extern pxCurrentTCB + .extern pxCurrentTCB /* @@ -115,7 +116,7 @@ _frxt_int_enter: movi a2, pxCurrentTCB l32i a2, a2, 0 /* a2 = current TCB */ beqz a2, 1f - s32i a1, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */ + s32i a1, a2, TOS_OFFSET /* pxCurrentTCB->pxTopOfStack = SP */ movi a1, port_IntStackTop /* a1 = top of intr stack */ .Lnested: @@ -156,7 +157,7 @@ _frxt_int_exit: movi a2, pxCurrentTCB l32i a2, a2, 0 /* a2 = current TCB */ beqz a2, 1f /* no task ? go to dispatcher */ - l32i a1, a2, TOPOFSTACK_OFFS /* SP = pxCurrentTCB->pxTopOfStack */ + l32i a1, a2, TOS_OFFSET /* SP = pxCurrentTCB->pxTopOfStack */ movi a2, port_switch_flag /* address of switch flag */ l32i a3, a2, 0 /* a3 = port_switch_flag */ @@ -205,129 +206,6 @@ _frxt_int_exit: l32i a0, a1, XT_STK_EXIT ret - -/* -********************************************************************************************************** -* _frxt_timer_int -* void _frxt_timer_int(void) -* -* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for FreeRTOS. -* Called every timer interrupt. -* Manages the tick timer and calls xPortSysTickHandler() every tick. -* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. -* -* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance. -* -********************************************************************************************************** -*/ - .globl _frxt_timer_int - .type _frxt_timer_int,@function - .align 4 -_frxt_timer_int: - - /* - Xtensa timers work by comparing a cycle counter with a preset value. Once the match occurs - an interrupt is generated, and the handler has to set a new cycle count into the comparator. - To avoid clock drift due to interrupt latency, the new cycle count is computed from the old, - not the time the interrupt was serviced. However if a timer interrupt is ever serviced more - than one tick late, it is necessary to process multiple ticks until the new cycle count is - in the future, otherwise the next timer interrupt would not occur until after the cycle - counter had wrapped (2^32 cycles later). - - do { - ticks++; - old_ccompare = read_ccompare_i(); - write_ccompare_i( old_ccompare + divisor ); - service one tick; - diff = read_ccount() - old_ccompare; - } while ( diff > divisor ); - */ - - ENTRY(16) - -.L_xt_timer_int_catchup: - - /* Update the timer comparator for the next tick. */ - #ifdef XT_CLOCK_FREQ - movi a2, XT_TICK_DIVISOR /* a2 = comparator increment */ - #else - movi a3, _xt_tick_divisor - l32i a2, a3, 0 /* a2 = comparator increment */ - #endif - rsr a3, XT_CCOMPARE /* a3 = old comparator value */ - add a4, a3, a2 /* a4 = new comparator value */ - wsr a4, XT_CCOMPARE /* update comp. and clear interrupt */ - esync - - #ifdef __XTENSA_CALL0_ABI__ - /* Preserve a2 and a3 across C calls. */ - s32i a2, sp, 4 - s32i a3, sp, 8 - #endif - - /* Call the FreeRTOS tick handler (see port.c). */ - #ifdef __XTENSA_CALL0_ABI__ - call0 xPortSysTickHandler - #else - call4 xPortSysTickHandler - #endif - - #ifdef __XTENSA_CALL0_ABI__ - /* Restore a2 and a3. */ - l32i a2, sp, 4 - l32i a3, sp, 8 - #endif - - /* Check if we need to process more ticks to catch up. */ - esync /* ensure comparator update complete */ - rsr a4, CCOUNT /* a4 = cycle count */ - sub a4, a4, a3 /* diff = ccount - old comparator */ - blt a2, a4, .L_xt_timer_int_catchup /* repeat while diff > divisor */ - - RET(16) - - /* -********************************************************************************************************** -* _frxt_tick_timer_init -* void _frxt_tick_timer_init(void) -* -* Initialize timer and timer interrrupt handler (_xt_tick_divisor_init() has already been been called). -* Callable from C (obeys ABI conventions on entry). -* -********************************************************************************************************** -*/ - .globl _frxt_tick_timer_init - .type _frxt_tick_timer_init,@function - .align 4 -_frxt_tick_timer_init: - - ENTRY(16) - - /* Set up the periodic tick timer (assume enough time to complete init). */ - #ifdef XT_CLOCK_FREQ - movi a3, XT_TICK_DIVISOR - #else - movi a2, _xt_tick_divisor - l32i a3, a2, 0 - #endif - rsr a2, CCOUNT /* current cycle count */ - add a2, a2, a3 /* time of first timer interrupt */ - wsr a2, XT_CCOMPARE /* set the comparator */ - - /* - Enable the timer interrupt at the device level. Don't write directly - to the INTENABLE register because it may be virtualized. - */ - #ifdef __XTENSA_CALL0_ABI__ - movi a2, XT_TIMER_INTEN - call0 xt_ints_on - #else - movi a6, XT_TIMER_INTEN - call4 xt_ints_on - #endif - - RET(16) - /* ********************************************************************************************************** * DISPATCH THE HIGH READY TASK @@ -367,7 +245,7 @@ _frxt_dispatch: call4 vTaskSwitchContext // Get next TCB to resume #endif l32i a3, a2, 0 - l32i sp, a3, TOPOFSTACK_OFFS /* SP = next_TCB->pxTopOfStack; */ + l32i sp, a3, TOS_OFFSET /* SP = next_TCB->pxTopOfStack */ s32i a3, a2, 0 /* Determine the type of stack frame. */ @@ -402,10 +280,10 @@ _frxt_dispatch: #if XCHAL_CP_NUM > 0 /* Restore CPENABLE from task's co-processor save area. */ - movi a3, pxCurrentTCB /* cp_state = */ + movi a3, pxCurrentTCB l32i a3, a3, 0 - l32i a2, a3, CP_TOPOFSTACK_OFFS /* StackType_t *pxStack; */ - l16ui a3, a2, XT_CPENABLE /* CPENABLE = cp_state->cpenable; */ + l32i a2, a3, EOS_OFFSET /* a2 = base of coproc save area */ + l16ui a3, a2, XT_CPENABLE /* a3 = saved CPENABLE value */ wsr a3, CPENABLE #endif @@ -493,15 +371,15 @@ vPortYield: movi a3, 0 l32i a2, a2, 0 /* a2 = pxCurrentTCB */ s32i a3, sp, XT_SOL_EXIT /* 0 to flag as solicited frame */ - s32i sp, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */ + s32i sp, a2, TOS_OFFSET /* pxCurrentTCB->pxTopOfStack = SP */ #if XCHAL_CP_NUM > 0 /* Clear CPENABLE, also in task's co-processor state save area. */ - l32i a2, a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state */ + l32i a2, a2, EOS_OFFSET /* a2 = pxCurrentTCB->cp_state */ movi a3, 0 wsr a3, CPENABLE beqz a2, 1f - s16i a3, a2, XT_CPENABLE /* clear saved cpenable */ + s16i a3, a2, XT_CPENABLE /* clear saved cpenable */ 1: #endif @@ -540,10 +418,10 @@ vPortYieldFromInt: /* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */ movi a3, pxCurrentTCB /* cp_state = */ l32i a3, a3, 0 - l32i a2, a3, CP_TOPOFSTACK_OFFS + l32i a2, a3, EOS_OFFSET rsr a3, CPENABLE - s16i a3, a2, XT_CPENABLE /* cp_state->cpenable = CPENABLE; */ + s16i a3, a2, XT_CPENABLE /* cp_state->cpenable = CPENABLE; */ movi a3, 0 wsr a3, CPENABLE /* disable all co-processors */ #endif @@ -556,41 +434,66 @@ vPortYieldFromInt: RET(16) #endif +/* +-------------------------------------------------------------------------------- + Task entry wrapper. Set up as the resume address in the initial stack frame. +-------------------------------------------------------------------------------- +*/ + + .global _xt_task_start + .type _xt_task_start,@function + .align 4 + +_xt_task_start: + 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 + movi a3, pxCurrentTCB + l32i a3, a3, 0 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + s32i sp, a3, EOS_OFFSET /* TCB->pxEndOfStack = CP save area */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + /* ********************************************************************************************************** -* _frxt_task_coproc_state -* void _frxt_task_coproc_state(void) +* _xt_task_coproc_state +* void _xt_task_coproc_state(void) * * Implements the Xtensa RTOS porting layer's XT_RTOS_CP_STATE function for FreeRTOS. * * May only be called when a task is running, not within an interrupt handler (returns 0 in that case). * May only be called from assembly code by the 'call0' instruction. Does NOT obey ABI conventions. -* Returns in A15 a pointer to the base of the co-processor state save area for the current task. +* Returns in a15 a pointer to the base of the co-processor state save area for the current task. * See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. * ********************************************************************************************************** */ #if XCHAL_CP_NUM > 0 - .globl _frxt_task_coproc_state - .type _frxt_task_coproc_state,@function + .globl _xt_task_coproc_state + .type _xt_task_coproc_state,@function .align 4 -_frxt_task_coproc_state: - movi a15, port_xSchedulerRunning /* if (port_xSchedulerRunning */ +_xt_task_coproc_state: + + movi a15, port_xSchedulerRunning /* if (port_xSchedulerRunning */ l32i a15, a15, 0 - beqz a15, 1f - movi a15, port_interruptNesting /* && port_interruptNesting == 0 */ + beqz a15, 2f + movi a15, port_interruptNesting /* && port_interruptNesting == 0 */ l32i a15, a15, 0 bnez a15, 1f movi a15, pxCurrentTCB - l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */ + l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */ beqz a15, 2f - l32i a15, a15, CP_TOPOFSTACK_OFFS + l32i a15, a15, EOS_OFFSET /* a15 = pxCurrentTCB->pxEndOfStack */ + ret +1: + movi a15, 0 +2: ret - -1: movi a15, 0 -2: ret #endif /* XCHAL_CP_NUM > 0 */ diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/portclib.c b/lib/FreeRTOS/portable/XCC/Xtensa/portclib.c index b6021348c36..819103daa94 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/portclib.c +++ b/lib/FreeRTOS/portable/XCC/Xtensa/portclib.c @@ -122,6 +122,7 @@ vPortClibInit(void) void _reclaim_reent(void * ptr) { + (void ) ptr; /* Avoid compiler warning */ } #endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */ @@ -145,6 +146,9 @@ static uint32_t ulClibInitDone = 0; void __malloc_lock(struct _reent * ptr) { + // Suppress compiler warning. + (void) ptr; + if (!ulClibInitDone) return; @@ -157,6 +161,9 @@ __malloc_lock(struct _reent * ptr) void __malloc_unlock(struct _reent * ptr) { + // Suppress compiler warning. + (void) ptr; + if (!ulClibInitDone) return; diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/portmacro.h b/lib/FreeRTOS/portable/XCC/Xtensa/portmacro.h index e30db0b9f3b..5f90001eec6 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/portmacro.h +++ b/lib/FreeRTOS/portable/XCC/Xtensa/portmacro.h @@ -63,11 +63,7 @@ extern "C" { #include #include -#include #include /* required for XSHAL_CLIB */ -#include - -//#include "xtensa_context.h" /*----------------------------------------------------------- * Port specific definitions. @@ -105,22 +101,59 @@ typedef unsigned portBASE_TYPE UBaseType_t; // portbenchmark #include "portbenchmark.h" -/* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */ -// These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. -#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0) -#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0) +// Critical section management. These cannot be nested. They should be used +// with a lot of care and cannot be called from interrupt context. +static inline void +portDISABLE_INTERRUPTS(void) +{ +#if XCHAL_HAVE_INTERRUPTS + XT_RSIL (15); +#endif + portbenchmarkINTERRUPT_DISABLE (); +} + +static inline void +portENABLE_INTERRUPTS(void) +{ + portbenchmarkINTERRUPT_RESTORE (0); +#if XCHAL_HAVE_INTERRUPTS + XT_RSIL (0); +#endif +} + +// Nested critical sections. Nesting managed by FreeRTOS. +#define portCRITICAL_NESTING_IN_TCB 1 -// These can be nested -#define portCRITICAL_NESTING_IN_TCB 1 // For now, let FreeRTOS' (tasks.c) manage critical nesting -void vTaskEnterCritical(void); -void vTaskExitCritical(void); +extern void vTaskEnterCritical(void); +extern void vTaskExitCritical(void); #define portENTER_CRITICAL() vTaskEnterCritical() #define portEXIT_CRITICAL() vTaskExitCritical() -// Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack. -// They can be called from interrupts too. -static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); return state; } -#define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0) +// These allow nested interrupt disabling and restoring via local registers or stack. +// They can be called from interrupts context. +static inline uint32_t +portENTER_CRITICAL_NESTED(void) +{ + uint32_t state; + +#if XCHAL_HAVE_INTERRUPTS + state = XT_RSIL (15); +#else + state = 0; +#endif + portbenchmarkINTERRUPT_DISABLE (); + return state; +} + +static inline void +portEXIT_CRITICAL_NESTED(uint32_t state) +{ + portbenchmarkINTERRUPT_RESTORE (state); +#if XCHAL_HAVE_INTERRUPTS + XT_WSR_PS (state); + XT_RSYNC (); +#endif +} // These FreeRTOS versions are similar to the nested versions above #define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED() @@ -147,44 +180,20 @@ void _frxt_setup_switch( void ); _frxt_setup_switch(); \ } +/* Tickless idle */ +#if ( configUSE_TICKLESS_IDLE != 0 ) +#ifndef portSUPPRESS_TICKS_AND_SLEEP +extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); +#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +#endif + /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) -// When coprocessors are defined, we to maintain a pointer to coprocessors area. -// We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: -// MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. -// The field is normally used for memory protection. FreeRTOS should create another general purpose field. -typedef struct { - #if XCHAL_CP_NUM > 0 - volatile StackType_t* coproc_area; // Pointer to coprocessor save area; MUST BE FIRST - #endif - - #if portUSING_MPU_WRAPPERS - // Define here mpu_settings, which is port dependent - int mpu_setting; // Just a dummy example here; MPU not ported to Xtensa yet - #endif - - #if configUSE_TRACE_FACILITY_2 - struct { - // Cf. porttraceStamp() - int taskstamp; /* Stamp from inside task to see where we are */ - int taskstampcount; /* A counter usually incremented when we restart the task's loop */ - } porttrace; - #endif -} xMPU_SETTINGS; - -// Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) -#if (XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2) && !portUSING_MPU_WRAPPERS // If MPU wrappers not used, we still need to allocate coproc area - #undef portUSING_MPU_WRAPPERS - #define portUSING_MPU_WRAPPERS 1 // Enable it to allocate coproc area - #define MPU_WRAPPERS_H // Override mpu_wrapper.h to disable unwanted code - #define PRIVILEGED_FUNCTION - #define PRIVILEGED_DATA -#endif - // porttrace #if configUSE_TRACE_FACILITY_2 #include "porttrace.h" diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/readme_xtensa.txt b/lib/FreeRTOS/portable/XCC/Xtensa/readme_xtensa.txt index 56228093b7f..29b382fc99e 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/readme_xtensa.txt +++ b/lib/FreeRTOS/portable/XCC/Xtensa/readme_xtensa.txt @@ -1,17 +1,13 @@ - FreeRTOS Port for Xtensa Configurable and Diamond Processors - ============================================================ - FreeRTOS Kernel Version 10.0.0 + FreeRTOS Port for Xtensa Configurable Processors + ================================================ Introduction ------------ -This document describes the Xtensa port for FreeRTOS multitasking RTOS. -For an introduction to FreeRTOS itself, please refer to FreeRTOS -documentation. - -This port currently works with FreeRTOS kernel version 10.0.0. +This document describes the Xtensa port of the Amazon FreeRTOS embedded RTOS. +Please refer to FreeRTOS documentation for an overview of FreeRTOS itself. Xtensa Configuration Requirements and Restrictions @@ -33,11 +29,6 @@ This port includes optional reentrancy support for the 'newlib' and thread-safety on a per task basis (for use in tasks only, not interrupt handlers). -NOTE: At this time only 'newlib' and 'xclib' C libraries are supported -for thread safety. The 'uclibc' library is not reentrant and does not -provide thread safety at this time. However, if you are not concerned -with reentrancy then you can use any of these libraries. - This port also includes a simple example application that may run on a supported board or the Xtensa instruction set simulator (ISS). There are also a couple of test programs used in maintaining the port, which @@ -45,12 +36,10 @@ serve as additional examples. FreeRTOS for Xtensa configurable processors requires the following minimum processor configuration options: + - Timer interrupt option with at least one interruptible timer. - Interrupt option (implied by the timer interrupt option). -- Exception Architecture 2 (XEA2). Please note that XEA1 is NOT supported. - All 'Diamond', 'Xtensa 6', 'Xtensa LX' and 'Xtensa LX2' processors and - most 'Xtensa T1050' processors are configured with XEA2. -All Diamond processor cores meet these requirements and are supported. +- Exception Architecture 2 (XEA2) (Neither XEA1 nor XEA3 is supported). Minimal support for certain evaluation boards is provided via a board independent XTBSP API implemented by a board specific library distributed @@ -58,7 +47,7 @@ with the Xtensa Tools. This provides the board clock frequency and basic polled drivers for the display and console device. Note that XTBSP is not a tradtional RTOS "board support package" with RTOS specific interrupt-driven drivers - it is not specific to any RTOS. Note that -FreeRTOS can run on any Xtensa or Diamond board without this board support +FreeRTOS can run on any Xtensa board without this board support (a "raw" platform), but you will have to provide the clock frequency and drivers for any on-board devices you want to use. @@ -76,7 +65,8 @@ version 1.0.0 or later from this location: https://github.com/aws/amazon-freertos -The Xtensa port files are currently not included in the official package. +The Xtensa port files are included in the official package but may not be +the latest versions available. All source is provided along with a Makefile that works for any host platform supported by Xtensa Tools (Windows, Linux). These instructions @@ -212,7 +202,7 @@ parameters based on what you specified. You can override the default compilation options by specifying the new options via CFLAGS. For example: -> xt-make all TARGET=sim CFLAGS="-O2 -Os -g" +> xt-make all TARGET=sim CFLAGS="-Os -g" This compiles the examples and links them with the FreeRTOS library libfreertos.a and the appropriate linker-support package (LSP) for your @@ -235,17 +225,8 @@ to a nonzero value either in xtensa_config.h or on the compiler's command line. Note that the default xtensa_config.h provided with this port does define this to 1 if either newlib or xclib is detected. -Then, you must also make sure to allocate extra space on the stack for -each task that will use the C library reentrant functions. This extra -space is to be allocated over and above the actual stack space required -by the task itself. The define - - XT_STACK_EXTRA_CLIB - -specifies the amount of extra space to be added on to the stack to allow -saving the context for the C library as well as the coprocessors if any. -E.g. if your task requires 2000 bytes of stack space, you must allocate -(2000 + XT_STACK_EXTRA_CLIB) bytes for the stack. +The space for the per-thread C library context data is allocated within +the FreeRTOS TCB structure. IMPORTANT NOTE @@ -267,11 +248,13 @@ Running or Debugging an Application To execute the example application on the simulator: -> xt-run [--turbo] example.exe +> xt-run [options] example.exe + +Consult the Xtensa simulator user manual for more information on options. -The option --turbo provides much faster, but non-cycle-accurate simulation -(the --turbo option is only available with Xtensa Tools version 7 or later). +To execute the example using the command line debugger: +> xt-gdb example.exe To execute on the simulator using the Xplorer GUI based debugger: @@ -292,7 +275,7 @@ any Xtensa platform, including simulator and any board, but you will not see any behavior specific to the platform (eg. display, printed output, stopping simulation at end of program). You can, while debugging, use a debugger mechanism called GDBIO to obtain basic I/O. To use GDBIO, link -with the gdbio LSP. Refer to Xtensa tools documentation for details. +with the gdbio library. Refer to Xtensa tools documentation for details. Task Stack Sizes @@ -495,11 +478,8 @@ frames differentiates solicited and interrupt stack frames. Improving Performance, Footprint, or Ease of Debugging ------------------------------------------------------ -By default FreeRTOS for Xtensa is built with debug (-g) and without -compiler optimizations (-O0). This makes debugging easier. Of course, --O0 costs performance and usually also increases stack usage. To make -FreeRTOS run faster you can change the Makefile to enable the desired -optimizations or set a predefined optimization level (-O) . +To make FreeRTOS run faster you can change the Makefile to enable the +desired optimizations or set a predefined optimization level (-O). Maximum performance is achieved with -O3 -ipa, but that might increase the footprint substantially. A good compromise is -O2. See the compiler @@ -615,9 +595,7 @@ User Exception and Interrupt Handler (Low/Medium Priority): default handler will be called, which will terminate the program. If the interrupt is for the system timer, it calls a special interrupt - handler for the system timer tick, which calls _frxt_timer_int then - clears its bit from the mask. This interrupt cannot be hooked by the - user-defined handler. + handler for the system timer tick, which handles timer tick processing. Finally, the handler calls _frxt_int_exit to allow FreeRTOS to perform any scheduling necessary and return either to the interrupted task diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/relnotes.txt b/lib/FreeRTOS/portable/XCC/Xtensa/relnotes.txt new file mode 100644 index 00000000000..c741c605ba7 --- /dev/null +++ b/lib/FreeRTOS/portable/XCC/Xtensa/relnotes.txt @@ -0,0 +1,123 @@ + +Notes for version 2.0 +--------------------- + +- Extensive refactor of code to eliminate use of MPU struct for saving + coprocessor state. Coprocessor exception handling has been redone. + +- Low power sleep support (tickless idle) added. + +- Removed use of XTOS header files and macros. Renamed port macros to + avoid name conflicts with XTOS macros. + +- More compiler warnings enabled for build (-Werror -Wextra -std=c99). + +- Interrupt and exception API reworked. Timer setup and handling mostly + converted to C code and simplified. + + +Notes for version 1.7 +--------------------- + +- portSTACK_TYPE changed to uint32_t from uint8_t. Stack size definitions + adjusted accordingly. + +- portYIELD_FROM_ISR changed to call _frxt_setup_switch conditionally. + +- Tick handler calls xTaskIncrementTick inside critical region to prevent + interrupt nesting issues. + + +Notes for version 1.6 +--------------------- + +- This version supports FreeRTOS version 10.0.0. + +- The directory structure and makefiles have been reorganized to conform + to the structure of FreeRTOS version 10.0.0. + + +Notes for version 1.5 +--------------------- + +- This version supports FreeRTOS version 9.0.0. + +- This version supports thread safe operation with the Xtensa C Library + (xclib) in addition to the Newlib C library (newlib). + The xtensa_config.h file is set up to enable thread safe operation by + default if xclib or newlib is detected. Use -D XT_USE_THREAD_SAFE_CLIB=0 + on the command line or in the project definition to disable this. + +- Incorrect function prototypes for xt_ints_on/xt_ints_off have been fixed. + + +Notes for version 1.4.2 +----------------------- + +- This version implements a bugfix. The bug was that even when the + config parameter "configUSE_TIME_SLICING" was set to zero, time + slicing would still occur due to a problem in the Xtensa interrupt + processing code. + +- The "small_test" test has been added to illustrate how FreeRTOS + can be configured to reduce the memory footprint. + + +Notes for version 1.4 +--------------------- + +- This version supports FreeRTOS version 8.2.0. + +- This version adds a new test xt_intr.c for interrupts testing. + +- This version separates the trace and benchmark facilities into a + separate downloadable. + + +Notes for version 1.3 +--------------------- + +- This version implements a separate interrupt stack. The interrupt + dispatch code saves the current task's state on to the task's own + stack and then switches to the interrupt stack for the interrupt + processing. Nested interrupts will continue to use the interrupt + stack. This helps to reduce the sizes of task stacks, since task + stacks no longer have to account for space to accommodate possible + nested interrupts. The size of the interrupt stack is controlled + by a config parameter. + + +Notes for version 1.2 +--------------------- + +- This version supports FreeRTOS version 8.1.2. + +- This version supports both CALL0 and windowed Xtensa configurations. + +- This version supports thread safe operation for the Newlib C library. + +- This version introduces an API for installing low/medium priority + interrupt handlers and exception handlers, which can be written in C. + See xtensa_api.h for details. + +- This version supports software prioritization of interrupts at the + same level. Define XT_USE_SWPRI to use this feature. Higher-numbered + interrupts are handled at a higher priority than lower-numbered ones. + +- The FreeRTOS demo application requires a stack size of at least 4 KB. + The standalone tests should be able to run with smaller stack sizes. + The minimum stack size depends on the specific Xtensa configuration. + Adjust the stack size of your application as required. + +- The examples are all defined with a heap size of 256 KB. This could + be a problem with Xtensa configurations that have only small amounts + of memory. Adjust the heap size to suit your platform and application. + There is an example of a small-footprint configuration in the directory + Xtensa_XCC_small. + +- NOTE: Code overlay support is not yet enabled for this port, even though + the support code is present. This feature is not enabled nor tested. + Do not define XT_USE_OVLY when building. + +-End- + diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_api.h b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_api.h index 8e2d8c96570..8a0ff3d9fbc 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_api.h +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_api.h @@ -1,4 +1,3 @@ - /* * Copyright (c) 2015-2019 Cadence Design Systems, Inc. * @@ -22,13 +21,14 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Xtensa-specific API for RTOS ports. - */ +/****************************************************************************** + Xtensa-specific API for RTOS ports. +******************************************************************************/ #ifndef __XTENSA_API_H__ #define __XTENSA_API_H__ +#include #include #include "xtensa_context.h" @@ -57,7 +57,7 @@ typedef void (*xt_exc_handler)(XtExcFrame *); of the exception frame structure see xtensa_context.h. ------------------------------------------------------------------------------- */ -extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f); +extern xt_exc_handler xt_set_exception_handler( uint32_t n, xt_exc_handler f ); /* @@ -69,54 +69,78 @@ extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f); arg - Argument to be passed to handler. ------------------------------------------------------------------------------- */ -extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg); +extern xt_handler xt_set_interrupt_handler( uint32_t n, xt_handler f, void * arg ); /* ------------------------------------------------------------------------------- - Call this function to enable the specified interrupts. + Call this function to enable the specified interrupt. - mask - Bit mask of interrupts to be enabled. + intnum - Interrupt number to be enabled. - Returns the previous state of the interrupt enables. + Returns: Nothing. ------------------------------------------------------------------------------- */ -extern unsigned int xt_ints_on(unsigned int mask); +extern void xt_interrupt_enable( uint32_t intnum ); /* ------------------------------------------------------------------------------- - Call this function to disable the specified interrupts. + Call this function to disable the specified interrupt. - mask - Bit mask of interrupts to be disabled. + intnum - Interrupt number to be disabled. - Returns the previous state of the interrupt enables. + Returns: Nothing. ------------------------------------------------------------------------------- */ -extern unsigned int xt_ints_off(unsigned int mask); +extern void xt_interrupt_disable( uint32_t intnum ); /* ------------------------------------------------------------------------------- - Call this function to set the specified (s/w) interrupt. + Call this function to check the enable state of the specified interrupt. + + intnum - Interrupt number to be checked. + + Returns: 1 if the specified interrupt is enabled, zero if the interrupt is + disabled, zero if the interrupt number is invalid. ------------------------------------------------------------------------------- */ -static inline void xt_set_intset(unsigned int arg) -{ - xthal_set_intset(arg); -} +uint32_t +xt_interrupt_enabled( uint32_t intnum ); + + +/* +------------------------------------------------------------------------------- + Call this function to trigger the specified (s/w) interrupt. + + intnum - Interrupt number to be triggered. + + Returns: Nothing. +------------------------------------------------------------------------------- +*/ +extern void xt_interrupt_trigger( uint32_t intnum ); /* ------------------------------------------------------------------------------- Call this function to clear the specified (s/w or edge-triggered) interrupt. + + intnum - Interrupt number to be cleared. + +Returns: Nothing. ------------------------------------------------------------------------------- */ -static inline void xt_set_intclear(unsigned int arg) -{ - xthal_set_intclear(arg); -} +extern void xt_interrupt_clear( uint32_t intnum ); + + +/* + * These map directly to HAL functions. + */ +#define xt_get_ccount xthal_get_ccount +#define xt_get_ccompare(t) xthal_get_ccompare(t) +#define xt_set_ccompare(t,v) xthal_set_ccompare(t,v) #endif /* __XTENSA_API_H__ */ diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_config.h b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_config.h index 43f3daaf92d..d79c200f77b 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_config.h +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_config.h @@ -49,16 +49,13 @@ extern "C" { * STACK REQUIREMENTS * * This section defines the minimum stack size, and the extra space required to -* be allocated for saving coprocessor state and/or C library state information -* (if thread safety is enabled for the C library). The sizes are in bytes. +* be allocated for saving coprocessor state on the stack when needed. The sizes +* are in bytes. * * Stack sizes for individual tasks should be derived from these minima based on -* the maximum call depth of the task and the maximum level of interrupt nesting. -* A minimum stack size is defined by XT_STACK_MIN_SIZE. This minimum is based -* on the requirement for a task that calls nothing else but can be interrupted. -* This assumes that interrupt handlers do not call more than a few levels deep. -* If this is not true, i.e. one or more interrupt handlers make deep calls then -* the minimum must be increased. +* the maximum call depth of the task. A minimum stack size is defined by the +* XT_STACK_MIN_SIZE value. This minimum is based on the requirement for a task +* that calls nothing else but can be interrupted. * * If the Xtensa processor configuration includes coprocessors, then space is * allocated to save the coprocessor state on the stack. @@ -72,9 +69,7 @@ extern "C" { * Usage: * * XT_USE_THREAD_SAFE_CLIB -- Define this to a nonzero value to enable thread-safe -* use of the C library. This will require extra stack -* space to be allocated for tasks that use the C library -* reentrant functions. See below for more information. +* use of the C library. * * NOTE: The Xtensa toolchain supports multiple C libraries and not all of them * support thread safety. Check your core configuration to see which C library @@ -86,12 +81,13 @@ extern "C" { * size, you must verify that the smaller size(s) will work * under all operating conditions. * -* XT_STACK_EXTRA -- The amount of extra stack space to allocate for a task -* that does not make C library reentrant calls. Add this -* to the amount of stack space required by the task itself. -* -* XT_STACK_EXTRA_CLIB -- The amount of space to allocate for C library state. +* XT_STACK_EXTRA -- The amount of extra stack space to be allocated for the +* system overhead (coprocessor state, exception frame etc.). +* Add this to the amount of stack space required by the +* task itself. * +* XT_SYSTEM_STACK_SIZE -- The size of the system interrupt stack. You will need to +* size this according to your system requirements. -----------------------------------------------------------------------------*/ /* Extra space required for interrupt/exception hooks. */ @@ -170,10 +166,11 @@ extern "C" { /* Minimum recommended stack size. */ #define XT_STACK_MIN_SIZE ((XT_XTRA_SIZE + XT_USER_SIZE) / sizeof(unsigned char)) -/* OS overhead with and without C library thread context. */ -#define XT_STACK_EXTRA (XT_XTRA_SIZE) -#define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE) +/* OS overhead. */ +#define XT_STACK_EXTRA (XT_XTRA_SIZE) +/* Default system (interrupt) stack size */ +#define XT_SYSTEM_STACK_SIZE 0x400 #ifdef __cplusplus } diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_context.S b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_context.S index d3748c79da1..8fa24bd14bb 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_context.S +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_context.S @@ -401,225 +401,11 @@ _xt_coproc_release: 2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */ bltu a3, a4, 1b /* repeat until end of array */ -3: wsr a6, PS /* restore interrupts */ +3: + wsr a6, PS /* restore interrupts */ + rsync RET0 #endif - -/******************************************************************************* -_xt_coproc_savecs - -If there is a current thread and it has a coprocessor state save area, then -save all callee-saved state into this area. This function is called from the -solicited context switch handler. It calls a system-specific function to get -the coprocessor save area base address. - -Entry conditions: - - The thread being switched out is still the current thread. - - CPENABLE state reflects which coprocessors are active. - - Registers have been saved/spilled already. - -Exit conditions: - - All necessary CP callee-saved state has been saved. - - Registers a2-a7, a13-a15 have been trashed. - -Must be called from assembly code only, using CALL0. -*******************************************************************************/ -#if XCHAL_CP_NUM > 0 - - .extern _xt_coproc_sa_offset /* external reference */ - - .global _xt_coproc_savecs - .type _xt_coproc_savecs,@function - .align 4 -_xt_coproc_savecs: - - /* At entry, CPENABLE should be showing which CPs are enabled. */ - - rsr a2, CPENABLE /* a2 = which CPs are enabled */ - beqz a2, .Ldone /* quick exit if none */ - mov a14, a0 /* save return address */ - call0 XT_RTOS_CP_STATE /* get address of CP save area */ - mov a0, a14 /* restore return address */ - beqz a15, .Ldone /* if none then nothing to do */ - s16i a2, a15, XT_CP_CS_ST /* save mask of CPs being stored */ - movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ - l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ - -#if XCHAL_CP0_SA_SIZE - bbci.l a2, 0, 2f /* CP 0 not enabled */ - l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ - add a3, a14, a15 /* a3 = save area for CP 0 */ - xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP1_SA_SIZE - bbci.l a2, 1, 2f /* CP 1 not enabled */ - l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ - add a3, a14, a15 /* a3 = save area for CP 1 */ - xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP2_SA_SIZE - bbci.l a2, 2, 2f - l32i a14, a13, 8 - add a3, a14, a15 - xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP3_SA_SIZE - bbci.l a2, 3, 2f - l32i a14, a13, 12 - add a3, a14, a15 - xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP4_SA_SIZE - bbci.l a2, 4, 2f - l32i a14, a13, 16 - add a3, a14, a15 - xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP5_SA_SIZE - bbci.l a2, 5, 2f - l32i a14, a13, 20 - add a3, a14, a15 - xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP6_SA_SIZE - bbci.l a2, 6, 2f - l32i a14, a13, 24 - add a3, a14, a15 - xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP7_SA_SIZE - bbci.l a2, 7, 2f - l32i a14, a13, 28 - add a3, a14, a15 - xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -.Ldone: - ret -#endif - - -/******************************************************************************* -_xt_coproc_restorecs - -Restore any callee-saved coprocessor state for the incoming thread. -This function is called from coprocessor exception handling, when giving -ownership to a thread that solicited a context switch earlier. It calls a -system-specific function to get the coprocessor save area base address. - -Entry conditions: - - The incoming thread is set as the current thread. - - CPENABLE is set up correctly for all required coprocessors. - - a2 = mask of coprocessors to be restored. - -Exit conditions: - - All necessary CP callee-saved state has been restored. - - CPENABLE - unchanged. - - Registers a2-a7, a13-a15 have been trashed. - -Must be called from assembly code only, using CALL0. -*******************************************************************************/ -#if XCHAL_CP_NUM > 0 - - .global _xt_coproc_restorecs - .type _xt_coproc_restorecs,@function - .align 4 -_xt_coproc_restorecs: - - mov a14, a0 /* save return address */ - call0 XT_RTOS_CP_STATE /* get address of CP save area */ - mov a0, a14 /* restore return address */ - beqz a15, .Ldone2 /* if none then nothing to do */ - l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */ - xor a3, a3, a2 /* clear the ones being restored */ - s32i a3, a15, XT_CP_CS_ST /* update saved CP mask */ - movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ - l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ - -#if XCHAL_CP0_SA_SIZE - bbci.l a2, 0, 2f /* CP 0 not enabled */ - l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ - add a3, a14, a15 /* a3 = save area for CP 0 */ - xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP1_SA_SIZE - bbci.l a2, 1, 2f /* CP 1 not enabled */ - l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ - add a3, a14, a15 /* a3 = save area for CP 1 */ - xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP2_SA_SIZE - bbci.l a2, 2, 2f - l32i a14, a13, 8 - add a3, a14, a15 - xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP3_SA_SIZE - bbci.l a2, 3, 2f - l32i a14, a13, 12 - add a3, a14, a15 - xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP4_SA_SIZE - bbci.l a2, 4, 2f - l32i a14, a13, 16 - add a3, a14, a15 - xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP5_SA_SIZE - bbci.l a2, 5, 2f - l32i a14, a13, 20 - add a3, a14, a15 - xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP6_SA_SIZE - bbci.l a2, 6, 2f - l32i a14, a13, 24 - add a3, a14, a15 - xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -#if XCHAL_CP7_SA_SIZE - bbci.l a2, 7, 2f - l32i a14, a13, 28 - add a3, a14, a15 - xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL -2: -#endif - -.Ldone2: - ret - -#endif - diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_coproc_handler.S b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_coproc_handler.S new file mode 100644 index 00000000000..0fa1b855b8e --- /dev/null +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_coproc_handler.S @@ -0,0 +1,535 @@ + +/* + * Copyright (c) 2015-2019 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_coproc_handler.S - Xtensa coprocessor exception handler. + +#include +#include + +#include "xtensa_context.h" +#include "xtensa_rtos.h" + + +#if XCHAL_CP_NUM > 0 + +//----------------------------------------------------------------------------- +// Coprocessor related state and precomputed values. +//----------------------------------------------------------------------------- + +// Table of coprocessor owners, identified by thread's CP save area pointer. +// Zero means coprocessor is not owned. + + .data + .global _xt_coproc_owner_sa + .align 16,,XCHAL_CP_MAX << 2 // minimize crossing cache boundaries +_xt_coproc_owner_sa: + .rept XCHAL_CP_MAX + .word 0 + .endr + +// Bitmask table for CP n's enable bit, indexed by coprocessor number. + + .section .rodata, "a" + .global _xt_coproc_mask + .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< 0 + diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_init.c b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_init.c deleted file mode 100644 index 2de1116a500..00000000000 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_init.c +++ /dev/null @@ -1,66 +0,0 @@ - -/* - * Copyright (c) 2015-2019 Cadence Design Systems, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * XTENSA INITIALIZATION ROUTINES CODED IN C - * - * This file contains miscellaneous Xtensa RTOS-generic initialization functions - * that are implemented in C. - */ - - -#ifdef XT_BOARD -#include -#endif - -#include "xtensa_rtos.h" - -#ifdef XT_RTOS_TIMER_INT - -unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */ - -/* -Compute and initialize at run-time the tick divisor (the number of -processor clock cycles in an RTOS tick, used to set the tick timer). -Called when the processor clock frequency is not known at compile-time. -*/ -void _xt_tick_divisor_init(void) -{ -#ifdef XT_CLOCK_FREQ - - _xt_tick_divisor = (XT_CLOCK_FREQ / XT_TICK_PER_SEC); - -#else - - #ifdef XT_BOARD - _xt_tick_divisor = xtbsp_clock_freq_hz() / XT_TICK_PER_SEC; - #else - #error "No way to obtain processor clock frequency" - #endif /* XT_BOARD */ - -#endif /* XT_CLOCK_FREQ */ -} - -#endif /* XT_RTOS_TIMER_INT */ - diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr.c b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr.c index 524ebf6f65a..114bbe68b10 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr.c +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr.c @@ -1,4 +1,3 @@ - /* * Copyright (c) 2015-2019 Cadence Design Systems, Inc. * @@ -22,14 +21,15 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Xtensa-specific interrupt and exception functions for RTOS ports. - * Also see xtensa_intr_asm.S. - */ +/****************************************************************************** + Xtensa-specific interrupt and exception functions for RTOS ports. + Also see xtensa_intr_asm.S. +******************************************************************************/ #include #include +#include #include "xtensa_api.h" @@ -37,63 +37,81 @@ #if XCHAL_HAVE_EXCEPTIONS /* Handler table is in xtensa_intr_asm.S */ - -extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM]; +extern xt_exc_handler xt_exception_table[XCHAL_EXCCAUSE_NUM]; /* Default handler for unhandled exceptions. */ -void xt_unhandled_exception(XtExcFrame *frame) +void +xt_unhandled_exception( XtExcFrame * frame ) { - exit(-1); + (void) frame; + exit( -1 ); } /* This function registers a handler for the specified exception. The function returns the address of the previous handler. - On error, it returns 0. + On error, it returns NULL. */ -xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f) +xt_exc_handler +xt_set_exception_handler( uint32_t n, xt_exc_handler f ) { xt_exc_handler old; - if( n < 0 || n >= XCHAL_EXCCAUSE_NUM ) - return 0; /* invalid exception number */ + if ( n >= (uint32_t) XCHAL_EXCCAUSE_NUM ) + { + // Invalid exception number. + return NULL; + } - old = _xt_exception_table[n]; + old = xt_exception_table[n]; - if (f) { - _xt_exception_table[n] = f; + if ( f != NULL ) + { + xt_exception_table[n] = f; } - else { - _xt_exception_table[n] = &xt_unhandled_exception; + else + { + xt_exception_table[n] = &xt_unhandled_exception; } - return ((old == &xt_unhandled_exception) ? 0 : old); + return old; } #endif #if XCHAL_HAVE_INTERRUPTS -/* Handler table is in xtensa_intr_asm.S */ +#if XCHAL_HAVE_XEA2 +/* Defined in xtensa_intr_asm.S */ +extern uint32_t xt_intenable; +extern uint32_t xt_vpri_mask; +#endif +/* Handler table is in xtensa_intr_asm.S */ typedef struct xt_handler_table_entry { void * handler; void * arg; } xt_handler_table_entry; -extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS]; +#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3) +extern xt_handler_table_entry xt_interrupt_table[XCHAL_NUM_INTERRUPTS + 1]; +#else +extern xt_handler_table_entry xt_interrupt_table[XCHAL_NUM_INTERRUPTS]; +#endif /* Default handler for unhandled interrupts. */ -void xt_unhandled_interrupt(void * arg) +void +xt_unhandled_interrupt( void * arg ) { - exit(-1); + (void) arg; + exit( -1 ); } @@ -101,31 +119,134 @@ void xt_unhandled_interrupt(void * arg) This function registers a handler for the specified interrupt. The "arg" parameter specifies the argument to be passed to the handler when it is invoked. The function returns the address of the previous handler. - On error, it returns 0. + On error, it returns NULL. */ -xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) +xt_handler +xt_set_interrupt_handler( uint32_t n, xt_handler f, void * arg ) { xt_handler_table_entry * entry; xt_handler old; - if( n < 0 || n >= XCHAL_NUM_INTERRUPTS ) - return 0; /* invalid interrupt number */ - if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL ) - return 0; /* priority level too high to safely handle in C */ + if ( n >= (uint32_t) XCHAL_NUM_INTERRUPTS ) + { + // Invalid interrupt number. + return NULL; + } + +#if XCHAL_HAVE_XEA2 + if ( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL ) + { + // Priority level too high to safely handle in C. + return NULL; + } +#endif - entry = _xt_interrupt_table + n; +#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3) + entry = xt_interrupt_table + n + 1; +#else + entry = xt_interrupt_table + n; +#endif old = entry->handler; - if (f) { + if ( f != NULL ) + { entry->handler = f; entry->arg = arg; } - else { + else + { entry->handler = &xt_unhandled_interrupt; entry->arg = (void*)n; } - return ((old == &xt_unhandled_interrupt) ? 0 : old); + return old; +} + + +/* + This function enables the interrupt whose number is specified as + the argument. +*/ +void +xt_interrupt_enable( uint32_t intnum ) +{ +#if XCHAL_HAVE_XEA2 + if ( intnum < (uint32_t) XCHAL_NUM_INTERRUPTS ) + { + uint32_t ps = XT_RSIL( 15 ); + + // New INTENABLE = (xt_intenable | mask) & xt_vpri_mask. + xt_intenable |= ( 1U << intnum ); + XT_WSR_INTENABLE( xt_intenable & xt_vpri_mask ); + XT_WSR_PS( ps ); + XT_RSYNC(); + } +#else + xthal_interrupt_enable( intnum ); +#endif +} + + +/* + This function disables the interrupt whose number is specified as + the argument. +*/ +void +xt_interrupt_disable( uint32_t intnum ) +{ +#if XCHAL_HAVE_XEA2 + if ( intnum < (uint32_t) XCHAL_NUM_INTERRUPTS ) + { + uint32_t ps = XT_RSIL( 15 ); + + // New INTENABLE = (xt_intenable & ~mask) & xt_vpri_mask. + xt_intenable &= ~( 1U << intnum ); + XT_WSR_INTENABLE( xt_intenable & xt_vpri_mask ); + XT_WSR_PS( ps ); + XT_RSYNC(); + } +#else + xthal_interrupt_disable( intnum ); +#endif +} + + +/* + This function returns : 1 if the specified interrupt is enabled, zero + if the interrupt is disabled, zero if the interrupt number is invalid. +*/ +uint32_t +xt_interrupt_enabled( uint32_t intnum ) +{ +#if XCHAL_HAVE_XEA2 + if ( intnum < (uint32_t) XCHAL_NUM_INTERRUPTS ) + { + return ( (xt_intenable & (1U << intnum)) != 0 ) ? 1U : 0; + } + return 0; +#else + return xthal_interrupt_enabled( intnum ); +#endif +} + + +/* + This function triggers the specified interrupt. +*/ +void +xt_interrupt_trigger( uint32_t intnum ) +{ + xthal_interrupt_trigger( intnum ); +} + + +/* + This function clears the specified interrupt. +*/ +void +xt_interrupt_clear( uint32_t intnum ) +{ + xthal_interrupt_clear( intnum ); } diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr_asm.S b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr_asm.S index bf3017daf5a..884b1b6c07e 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr_asm.S +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_intr_asm.S @@ -1,4 +1,3 @@ - /* * Copyright (c) 2015-2019 Cadence Design Systems, Inc. * @@ -22,15 +21,16 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Xtensa interrupt handling data and assembly routines. - * Also see xtensa_intr.c and xtensa_vectors.S. - */ +/****************************************************************************** + Xtensa interrupt handling data and assembly routines. + Also see xtensa_intr.c and xtensa_vectors.S. +******************************************************************************/ #include #include #include "xtensa_context.h" +#include "xtensa_config.h" #if XCHAL_HAVE_INTERRUPTS @@ -40,141 +40,106 @@ ------------------------------------------------------------------------------- */ +#if XCHAL_HAVE_XEA2 + .data - .global _xt_intdata + .global xt_intdata .align 8 -_xt_intdata: - .global _xt_intenable - .type _xt_intenable,@object - .size _xt_intenable,4 - .global _xt_vpri_mask - .type _xt_vpri_mask,@object - .size _xt_vpri_mask,4 +xt_intdata: + .global xt_intenable + .type xt_intenable,@object + .size xt_intenable,4 + .global xt_vpri_mask + .type xt_vpri_mask,@object + .size xt_vpri_mask,4 -_xt_intenable: .word 0 /* Virtual INTENABLE */ -_xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */ +xt_intenable: .word 0 /* Virtual INTENABLE */ +xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */ +#endif /* ------------------------------------------------------------------------------- - Table of C-callable interrupt handlers for each interrupt. Note that not all - slots can be filled, because interrupts at level > EXCM_LEVEL will not be - dispatched to a C handler by default. + System interrupt stack. ------------------------------------------------------------------------------- */ +#if (XCHAL_HAVE_XEA2 || XCHAL_HAVE_ISB) .data - .global _xt_interrupt_table - .align 8 - -_xt_interrupt_table: - - .set i, 0 - .rept XCHAL_NUM_INTERRUPTS - .word xt_unhandled_interrupt /* handler address */ - .word i /* handler arg (default: intnum) */ - .set i, i+1 - .endr +#else + .section .intr.top, "aw" +#endif -#endif /* XCHAL_HAVE_INTERRUPTS */ + .global xt_interrupt_stack + .global xt_interrupt_stack_top + .align 16 +xt_interrupt_stack: + .space XT_SYSTEM_STACK_SIZE +xt_interrupt_stack_top: -#if XCHAL_HAVE_EXCEPTIONS /* ------------------------------------------------------------------------------- - Table of C-callable exception handlers for each exception. Note that not all - slots will be active, because some exceptions (e.g. coprocessor exceptions) - are always handled by the OS and cannot be hooked by user handlers. + Table of C-callable interrupt handlers for each interrupt. For XEA2 configs, + not all slots can be filled, because interrupts at level > EXCM_LEVEL will + not be dispatched to a C handler by default. ------------------------------------------------------------------------------- */ +#if (XCHAL_HAVE_XEA2 || XCHAL_HAVE_ISB) .data - .global _xt_exception_table - .align 4 - -_xt_exception_table: - .rept XCHAL_EXCCAUSE_NUM - .word xt_unhandled_exception /* handler address */ - .endr - +#else + .section .intr.data, "aw" #endif + .global xt_interrupt_table + .align 16 + +xt_interrupt_table: /* ------------------------------------------------------------------------------- - unsigned int xt_ints_on ( unsigned int mask ) - - Enables a set of interrupts. Does not simply set INTENABLE directly, but - computes it as a function of the current virtual priority. - Can be called from interrupt handlers. + If using the interrupt wrapper, make the first entry in the interrupt table + point to the wrapper (XEA3) or leave it empty (XEA2). ------------------------------------------------------------------------------- */ +#if XCHAL_HAVE_XEA3 + .word xt_interrupt_wrapper + .word 0 +#elif XT_USE_INT_WRAPPER + .word 0 + .word 0 +#endif - .text - .align 4 - .global xt_ints_on - .type xt_ints_on,@function - -xt_ints_on: + .set i, 0 + .rept XCHAL_NUM_INTERRUPTS + .word xt_unhandled_interrupt /* handler address */ + .word i /* handler arg (default: intnum) */ + .set i, i+1 + .endr - ENTRY0 -#if XCHAL_HAVE_INTERRUPTS - movi a3, 0 - movi a4, _xt_intdata - xsr a3, INTENABLE /* Disables all interrupts */ - rsync - l32i a3, a4, 0 /* a3 = _xt_intenable */ - l32i a6, a4, 4 /* a6 = _xt_vpri_mask */ - or a5, a3, a2 /* a5 = _xt_intenable | mask */ - s32i a5, a4, 0 /* _xt_intenable |= mask */ - and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */ - wsr a5, INTENABLE /* Reenable interrupts */ - mov a2, a3 /* Previous mask */ -#else - movi a2, 0 /* Return zero */ -#endif - RET0 +#endif /* XCHAL_HAVE_INTERRUPTS */ - .size xt_ints_on, . - xt_ints_on +#if XCHAL_HAVE_EXCEPTIONS /* ------------------------------------------------------------------------------- - unsigned int xt_ints_off ( unsigned int mask ) - - Disables a set of interrupts. Does not simply set INTENABLE directly, - but computes it as a function of the current virtual priority. - Can be called from interrupt handlers. + Table of C-callable exception handlers for each exception. Note that not all + slots will be active, because some exceptions (e.g. coprocessor exceptions) + are always handled by the OS and cannot be hooked by user handlers. ------------------------------------------------------------------------------- */ - .text + .data + .global xt_exception_table .align 4 - .global xt_ints_off - .type xt_ints_off,@function -xt_ints_off: +xt_exception_table: + .rept XCHAL_EXCCAUSE_NUM + .word xt_unhandled_exception /* handler address */ + .endr - ENTRY0 -#if XCHAL_HAVE_INTERRUPTS - movi a3, 0 - movi a4, _xt_intdata - xsr a3, INTENABLE /* Disables all interrupts */ - rsync - l32i a3, a4, 0 /* a3 = _xt_intenable */ - l32i a6, a4, 4 /* a6 = _xt_vpri_mask */ - or a5, a3, a2 /* a5 = _xt_intenable | mask */ - xor a5, a5, a2 /* a5 = _xt_intenable & ~mask */ - s32i a5, a4, 0 /* _xt_intenable &= ~mask */ - and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */ - wsr a5, INTENABLE /* Reenable interrupts */ - mov a2, a3 /* Previous mask */ -#else - movi a2, 0 /* return zero */ #endif - RET0 - - .size xt_ints_off, . - xt_ints_off - diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_rtos.h b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_rtos.h index ecf6b6129ab..a9a00feea22 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_rtos.h +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_rtos.h @@ -70,7 +70,7 @@ However these can still be overridden from the command line. #endif #ifndef XT_BOARD - #if configXT_BOARD + #if defined (configXT_BOARD) && (configXT_BOARD != 0) #define XT_BOARD 1 /* Board mode */ #endif #endif @@ -160,7 +160,7 @@ and by the 'call0' instruction. A result of 0 indicates an unrecoverable error. The implementation may use only a2-4, a15 (all other regs must be preserved). */ // void* XT_RTOS_CP_STATE(void) -#define XT_RTOS_CP_STATE _frxt_task_coproc_state +#define XT_RTOS_CP_STATE _xt_task_coproc_state /******************************************************************************* @@ -227,8 +227,8 @@ Xtensa Port Version. *******************************************************************************/ -#define XTENSA_PORT_VERSION 1.7 -#define XTENSA_PORT_VERSION_STRING "1.7" +#define XTENSA_PORT_VERSION 2.0 +#define XTENSA_PORT_VERSION_STRING "2.0" #endif /* XTENSA_RTOS_H */ diff --git a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_vectors.S b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_vectors.S index 953205c46de..b07311e0be4 100644 --- a/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_vectors.S +++ b/lib/FreeRTOS/portable/XCC/Xtensa/xtensa_vectors.S @@ -95,6 +95,8 @@ #include "xtensa_rtos.h" +#if XCHAL_HAVE_XEA2 + /* Enable stack backtrace across exception/interrupt - see below */ #define XT_DEBUG_BACKTRACE 1 @@ -218,13 +220,10 @@ 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 + 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__ @@ -239,53 +238,31 @@ #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&: +8: /* - 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). + Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from + virtual _xt_intenable which _could_ have changed during interrupt + processing. But before that, raise the interrupt level back again. */ - #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. */ - + rsil a3, \level 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 */ + #else + j .L_xt_user_int_&level& /* check for more interrupts */ #endif 9: /* done */ + #if XCHAL_HAVE_EXCLUSIVE + /* Clear any local exclusive monitors. */ + clrex + #endif + .endm @@ -526,7 +503,7 @@ _xt_user_exc: /* If level 1 interrupt then jump to the dispatcher */ rsr a0, EXCCAUSE - beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1 + beqi a0, EXCCAUSE_LEVEL1_INTERRUPT, _xt_lowint1 /* Handle any coprocessor exceptions. Rely on the fact that exception numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors. @@ -614,7 +591,7 @@ _xt_user_exc: #endif rsr a2, EXCCAUSE /* recover exc cause */ - movi a3, _xt_exception_table + 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__ @@ -730,222 +707,6 @@ _xt_syscall_exc: 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<