From: gaurav-aws Date: Tue, 2 Oct 2018 23:54:51 +0000 (+0000) Subject: Fix Xtensa project file and some documentation improvements. X-Git-Tag: V10.2.0~55 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6f10ab38ac99ba57632fe4bf73ddf8ddb554857c;p=freertos Fix Xtensa project file and some documentation improvements. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2587 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.cproject b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.cproject deleted file mode 100644 index a574d0e62..000000000 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.cproject +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.project b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.project index e885f1a70..51db76b71 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.project +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/.project @@ -58,6 +58,11 @@ 1 PARENT-1-PROJECT_LOC/Common/Minimal/GenQTest.c + + CommonDemoTasks/IntQueue.c + 1 + PARENT-1-PROJECT_LOC/Common/Minimal/IntQueue.c + CommonDemoTasks/IntSemTest.c 1 @@ -133,11 +138,6 @@ 1 PARENT-1-PROJECT_LOC/Common/Minimal/death.c - - CommonDemoTasks/dynamic.c - 1 - PARENT-1-PROJECT_LOC/Common/Minimal/dynamic.c - CommonDemoTasks/flop.c 1 @@ -291,92 +291,92 @@ FreeRTOS_Source/portable/XCC/port.c 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/port.c + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/port.c FreeRTOS_Source/portable/XCC/portasm.S 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/portasm.S + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/portasm.S FreeRTOS_Source/portable/XCC/portbenchmark.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/portbenchmark.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/portbenchmark.h FreeRTOS_Source/portable/XCC/portclib.c 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/portclib.c + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/portclib.c FreeRTOS_Source/portable/XCC/portmacro.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/portmacro.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/portmacro.h FreeRTOS_Source/portable/XCC/porttrace.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/porttrace.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/porttrace.h FreeRTOS_Source/portable/XCC/readme_xtensa.txt 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/readme_xtensa.txt + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/readme_xtensa.txt FreeRTOS_Source/portable/XCC/xtensa_api.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_api.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_api.h FreeRTOS_Source/portable/XCC/xtensa_config.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_config.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_config.h FreeRTOS_Source/portable/XCC/xtensa_context.S 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_context.S + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_context.S FreeRTOS_Source/portable/XCC/xtensa_context.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_context.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_context.h FreeRTOS_Source/portable/XCC/xtensa_init.c 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_init.c + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_init.c FreeRTOS_Source/portable/XCC/xtensa_intr.c 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_intr.c + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_intr.c FreeRTOS_Source/portable/XCC/xtensa_intr_asm.S 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_intr_asm.S + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_intr_asm.S FreeRTOS_Source/portable/XCC/xtensa_overlay_os_hook.c 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_overlay_os_hook.c + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_overlay_os_hook.c FreeRTOS_Source/portable/XCC/xtensa_rtos.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_rtos.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_rtos.h FreeRTOS_Source/portable/XCC/xtensa_timer.h 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_timer.h + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_timer.h FreeRTOS_Source/portable/XCC/xtensa_vectors.S 1 - PARENT-2-PROJECT_LOC/Source/portable/XCC/Xtensa/xtensa_vectors.S + PARENT-2-PROJECT_LOC/Source/portable/ThirdParty/XCC/Xtensa/xtensa_vectors.S diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/FreeRTOSConfig.h b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/FreeRTOSConfig.h index 397c404a4..0af2ca0bf 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/FreeRTOSConfig.h +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/FreeRTOSConfig.h @@ -71,182 +71,192 @@ #define FREERTOS_CONFIG_H -/* Required for configuration-dependent settings */ +/* Required for configuration-dependent settings. */ #include "xtensa_config.h" -/*----------------------------------------------------------- +/*--------------------------------------------------------------------------- * Application specific definitions. * * These definitions should be adjusted for your particular hardware and * application requirements. * - * Note that the default heap size is deliberately kept small so that - * the build is more likely to succeed for configurations with limited - * memory. - * * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - *----------------------------------------------------------*/ + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + *--------------------------------------------------------------------------- + */ -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 0 +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 #ifdef SMALL_TEST -#define configUSE_TICK_HOOK 0 + #define configUSE_TICK_HOOK 0 #else -#define configUSE_TICK_HOOK 1 + #define configUSE_TICK_HOOK 1 #endif -#define configTICK_RATE_HZ ( 1000 ) +#define configTICK_RATE_HZ ( 1000 ) /* Default clock rate for simulator */ -#define configCPU_CLOCK_HZ 10000000 //_RB_ was 2MHz +#define configCPU_CLOCK_HZ 10000000 -/* This has impact on speed of search for highest priority */ -#ifdef SMALL_TEST -#define configMAX_PRIORITIES ( 7 ) -#else -#define configMAX_PRIORITIES ( 7 ) //_RB_ -#endif +/* Max possible priorities. */ +#define configMAX_PRIORITIES ( 7 ) -/* Minimal stack size. This may need to be increased for your application */ -/* NOTE: The FreeRTOS demos may not work reliably with stack size < 4KB. */ -/* The Xtensa-specific examples should be fine with XT_STACK_MIN_SIZE. */ -/* NOTE: the size is defined in terms of StackType_t units not bytes. */ -#if !(defined XT_STACK_MIN_SIZE) -#error XT_STACK_MIN_SIZE not defined, did you include xtensa_config.h ? +/** + * Minimal stack size. This may need to be increased for your application. + * + * @note: The FreeRTOS demos may not work reliably with stack size < 4KB. The + * Xtensa-specific examples should be fine with XT_STACK_MIN_SIZE. + * + * @note: The size is defined in terms of StackType_t units not bytes. + */ +#if !( defined XT_STACK_MIN_SIZE ) + #error XT_STACK_MIN_SIZE not defined, did you include xtensa_config.h ? #endif #ifdef SMALL_TEST -#define configMINIMAL_STACK_SIZE (XT_STACK_MIN_SIZE / sizeof(StackType_t)) + #define configMINIMAL_STACK_SIZE ( XT_STACK_MIN_SIZE / sizeof( StackType_t ) ) #else -#define configMINIMAL_STACK_SIZE (XT_STACK_MIN_SIZE > 1024 ? XT_STACK_MIN_SIZE : 1024) + #define configMINIMAL_STACK_SIZE ( XT_STACK_MIN_SIZE > 1024 ? XT_STACK_MIN_SIZE : 1024 ) #endif -/* The Xtensa port uses a separate interrupt stack. Adjust the stack size */ -/* to suit the needs of your specific application. */ -/* NOTE: the size is defined in bytes. */ +/** + * The Xtensa port uses a separate interrupt stack. Adjust the stack size to + * suit the needs of your specific application. + * + * @note: the size is defined in bytes. + */ #ifndef configISR_STACK_SIZE -#define configISR_STACK_SIZE 2048 + #define configISR_STACK_SIZE 2048 #endif -/* Minimal heap size to make sure examples can run on memory limited - configs. Adjust this to suit your system. */ +/** + * Minimal heap size to make sure examples can run on memory limited configs. + * Adjust this to suit your system. + */ #ifdef SMALL_TEST -#define configTOTAL_HEAP_SIZE ( ( size_t ) (16 * 1024) ) + #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16 * 1024 ) ) #else -#define configTOTAL_HEAP_SIZE ( ( size_t ) (512 * 1024) ) + #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 512 * 1024 ) ) #endif -#define configMAX_TASK_NAME_LEN ( 8 ) -#define configUSE_TRACE_FACILITY 0 /* Used by vTaskList in main.c */ -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 /* Used by vTaskList in main.c */ -#define configUSE_TRACE_FACILITY_2 0 /* Provided by Xtensa port patch */ -#define configBENCHMARK 0 /* Provided by Xtensa port patch */ -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 0 -#define configQUEUE_REGISTRY_SIZE 0 +#define configMAX_TASK_NAME_LEN ( 8 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#define configUSE_TRACE_FACILITY_2 0 /* Provided by Xtensa port patch. */ +#define configBENCHMARK 0 /* Provided by Xtensa port patch. */ +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configQUEUE_REGISTRY_SIZE 0 #ifdef SMALL_TEST -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configCHECK_FOR_STACK_OVERFLOW 0 + #define configUSE_MUTEXES 1 + #define configUSE_RECURSIVE_MUTEXES 1 + #define configUSE_COUNTING_SEMAPHORES 1 + #define configCHECK_FOR_STACK_OVERFLOW 0 #else -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configCHECK_FOR_STACK_OVERFLOW 2 + #define configUSE_MUTEXES 1 + #define configUSE_RECURSIVE_MUTEXES 1 + #define configUSE_COUNTING_SEMAPHORES 1 + #define configCHECK_FOR_STACK_OVERFLOW 2 #endif /* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) - -/* Set the following definitions to 1 to include the API function, or zero - to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskCleanUpResources 0 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 1 -#define INCLUDE_xTaskAbortDelay 1 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xSemaphoreGetMutexHolder 1 - -/* The priority at which the tick interrupt runs. This should probably be - kept at 1. */ -#define configKERNEL_INTERRUPT_PRIORITY 1 - -/* The maximum interrupt priority from which FreeRTOS.org API functions can - be called. Only API functions that end in ...FromISR() can be used within - interrupts. */ -#define configMAX_SYSCALL_INTERRUPT_PRIORITY XCHAL_EXCM_LEVEL - -/* XT_USE_THREAD_SAFE_CLIB is defined in xtensa_config.h and can be - overridden from the compiler/make command line. The small test - however always disables C lib thread safety to minimize size. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/** + * Set the following definitions to 1 to include the API function, or zero to + * exclude the API function. + */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/** + * The priority at which the tick interrupt runs. This should probably be kept + * at 1. + */ +#define configKERNEL_INTERRUPT_PRIORITY 1 + +/** + * The maximum interrupt priority from which FreeRTOS.org API functions can be + * called. Only API functions that end in ...FromISR() can be used within + * interrupts. + */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY XCHAL_EXCM_LEVEL + +/** + * XT_USE_THREAD_SAFE_CLIB is defined in xtensa_config.h and can be overridden + * from the compiler/make command line. The small test however always disables C + * lib thread safety to minimize size. + */ #ifdef SMALL_TEST - #define configUSE_NEWLIB_REENTRANT 0 -#else -#if (XT_USE_THREAD_SAFE_CLIB > 0u) - #if XT_HAVE_THREAD_SAFE_CLIB - #define configUSE_NEWLIB_REENTRANT 0 //_RB_ 1 - #else - #error "Error: thread-safe C library support not available for this C library." - #endif + #define configUSE_NEWLIB_REENTRANT 0 #else - #define configUSE_NEWLIB_REENTRANT 0 -#endif + #if ( XT_USE_THREAD_SAFE_CLIB > 0u ) + #if XT_HAVE_THREAD_SAFE_CLIB + #define configUSE_NEWLIB_REENTRANT 0 + #else + #error "Error: thread-safe C library support not available for this C library." + #endif + #else + #define configUSE_NEWLIB_REENTRANT 0 + #endif #endif /* Test FreeRTOS timers (with timer task) and more. */ -/* Some files don't compile if this flag is disabled */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) -#define configTIMER_QUEUE_LENGTH 10 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE #ifdef SMALL_TEST -#define INCLUDE_xTimerPendFunctionCall 0 -#define INCLUDE_eTaskGetState 0 -#define configUSE_QUEUE_SETS 0 + #define INCLUDE_xTimerPendFunctionCall 0 + #define INCLUDE_eTaskGetState 0 + #define configUSE_QUEUE_SETS 0 #else -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_eTaskGetState 1 -#define configUSE_QUEUE_SETS 1 + #define INCLUDE_xTimerPendFunctionCall 1 + #define INCLUDE_eTaskGetState 1 + #define configUSE_QUEUE_SETS 1 #endif -/* Specific config for XTENSA (these can be deleted and they will take default values) */ - -#if (!defined XT_SIMULATOR) && (!defined XT_BOARD) -#define configXT_SIMULATOR 1 /* Simulator mode */ -#define configXT_BOARD 0 /* Board mode */ +/** + * Specific config for XTENSA (these can be deleted and they will take default + * values). + */ +#if ( !defined XT_SIMULATOR ) && ( !defined XT_BOARD ) + #define configXT_SIMULATOR 1 /* Simulator mode. */ + #define configXT_BOARD 0 /* Board mode. */ #endif #ifndef SMALL_TEST + #if ( !defined XT_INTEXC_HOOKS ) + #define configXT_INTEXC_HOOKS 1 /* Exception hooks used by certain tests. */ + #endif -#if (!defined XT_INTEXC_HOOKS) -#define configXT_INTEXC_HOOKS 1 /* Exception hooks used by certain tests */ -#endif - -#if configUSE_TRACE_FACILITY_2 -#define configASSERT_2 1 /* Specific to Xtensa port */ + #if configUSE_TRACE_FACILITY_2 + #define configASSERT_2 1 /* Specific to Xtensa port. */ + #endif #endif -#endif - -/* It is a good idea to define configASSERT() while developing. configASSERT() -uses the same semantics as the standard C assert() macro. */ +/** + * It is a good idea to define configASSERT() while developing. configASSERT() + * uses the same semantics as the standard C assert() macro. + */ #if !defined __ASSEMBLER__ extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); #endif #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __LINE__, __FILE__ ) -#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN ( 2 ) +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN ( 2 ) /* Used by stream buffer tests. */ #endif /* FREERTOS_CONFIG_H */ - diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.c b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.c index 8e1194511..d413d99d4 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.c +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.c @@ -43,32 +43,38 @@ /* Check if Timer1 is available. */ #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED - #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL - #define SECOND_TIMER_AVAILABLE 1 + #if XCHAL_INT_LEVEL( XCHAL_TIMER1_INTERRUPT ) <= XCHAL_EXCM_LEVEL + #define SECOND_TIMER_AVAILABLE 1 #endif #endif #ifndef SECOND_TIMER_AVAILABLE - #define SECOND_TIMER_AVAILABLE 0 + #define SECOND_TIMER_AVAILABLE 0 #endif -/* Timer0 is used to drive systick and therefore we use Timer1 +/** + * Timer0 is used to drive systick and therefore we use Timer1 * as second interrupt which runs on a higher priority than * Timer0. This ensures that systick will get interrupted by - * this timer and hence we can test interrupt nesting. */ -#define SECOND_TIMER_INDEX 1 + * this timer and hence we can test interrupt nesting. + */ +#define SECOND_TIMER_INDEX 1 -/* Frequency of the second timer - This timer is configured at - * a frequency offset of 17 from the systick timer. */ -#define SECOND_TIMER_TICK_RATE_HZ ( configTICK_RATE_HZ + 17 ) -#define SECOND_TIMER_TICK_DIVISOR ( configCPU_CLOCK_HZ / SECOND_TIMER_TICK_RATE_HZ ) +/** + * Frequency of the second timer - This timer is configured at + * a frequency offset of 17 from the systick timer. + */ +#define SECOND_TIMER_TICK_RATE_HZ ( configTICK_RATE_HZ + 17 ) +#define SECOND_TIMER_TICK_DIVISOR ( configCPU_CLOCK_HZ / SECOND_TIMER_TICK_RATE_HZ ) /*-----------------------------------------------------------*/ /* Defined in main_full.c. */ extern BaseType_t xTimerForQueueTestInitialized; /*-----------------------------------------------------------*/ -/* Interrupt handler for timer interrupt. */ +/** + * Interrupt handler for timer interrupt. + */ #if( SECOND_TIMER_AVAILABLE == 1 ) static void prvTimer2Handler( void *arg ); #endif /* SECOND_TIMER_AVAILABLE */ @@ -103,13 +109,15 @@ unsigned currentCycleCount, firstComparatorValue; /*-----------------------------------------------------------*/ /* - * 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). + * 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++; diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.h b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.h index b7b4a842b..8a9c5b8be 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.h +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/IntQueueTimer.h @@ -29,8 +29,9 @@ #ifndef INT_QUEUE_TIMER_H #define INT_QUEUE_TIMER_H +/** + * The function called from interrupt tests to initialise timer. + */ void vInitialiseTimerForIntQueueTest( void ); -void vTimer2Handler_C( void ); #endif /* INT_QUEUE_TIMER_H */ - diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main.c b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main.c index 57c96c9b0..7b6423b8e 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main.c +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main.c @@ -26,15 +26,17 @@ */ /****************************************************************************** - * This project provides two demo applications. A simple blinky style project, - * and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two. - * The simply blinky demo is implemented and described in main_blinky.c. The - * more comprehensive test and demo application is implemented and described in - * main_full.c. + * This project provides two demo applications: + * - A simple blinky style demo application. + * - A more comprehensive test and demo application. + * The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY macro is used to select between the two. * - * This file implements the code that is not demo specific, including the - * hardware setup and FreeRTOS hook functions. + * The simply blinky demo is implemented and described in the file main_blinky.c. + * The more comprehensive test and demo application is implemented and described + * in the file main_full.c. + * + * This file implements the code that is not demo specific, including the FreeRTOS + * hook functions. * ******************************************************************************* */ @@ -47,48 +49,60 @@ #include "FreeRTOS.h" #include "task.h" -/* This project provides two demo applications. A simple blinky style demo -application, and a more comprehensive test and demo application. The -mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two. - -If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built. -The blinky demo is implemented and described in main_blinky.c. - -If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and -demo application will be built. The comprehensive test and demo application is -implemented and described in main_full.c. */ +/** + * This project provides two demo applications: + * - A simple blinky style demo application. + * - A more comprehensive test and demo application. + * The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY macro is used to select between the two. + * + * If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 then the blinky demo will be + * built. The blinky demo is implemented and described in main_blinky.c. + * + * If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0 then the comprehensive test + * and demo application will be built. The comprehensive test and demo application + * is implemented and described in main_full.c. + */ #define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0 - /*-----------------------------------------------------------*/ -/* - * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. - * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. +/** + * The entry function for the blinky demo application. + * + * This is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. */ extern void main_blinky( void ); + +/** + * The entry function for the comprehensive test and demo application. + * + * This is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. + */ extern void main_full( void ); -/* +/** * Prototypes for the standard FreeRTOS application hook (callback) functions - * implemented within this file. See http://www.freertos.org/a00016.html . + * implemented within this file. + * + * @see http://www.freertos.org/a00016.html */ void vApplicationMallocFailedHook( void ); void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); void vApplicationTickHook( void ); -/* - * Only the comprehensive demo uses application hook (callback) functions. See - * http://www.freertos.org/a00016.html for more information. +/** + * The function called from the tick hook. + * + * @note Only the comprehensive demo uses application hook (callback) functions. + * + * @see http://www.freertos.org/a00016.html */ void vFullDemoTickHookFunction( void ); - - /*-----------------------------------------------------------*/ int main( void ) { /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top - of this file. */ + * of this file. */ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) { main_blinky(); @@ -106,17 +120,17 @@ int main( void ) void vApplicationMallocFailedHook( void ) { /* vApplicationMallocFailedHook() will only be called if - configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook - function that will get called if a call to pvPortMalloc() fails. - pvPortMalloc() is called internally by the kernel whenever a task, queue, - timer or semaphore is created. It is also called by various parts of the - demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the - size of the heap available to pvPortMalloc() is defined by - configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize() - API function can be used to query the size of free heap space that remains - (although it does not provide information on how the remaining heap might be - fragmented). See http://www.freertos.org/a00111.html for more - information. */ + * configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook + * function that will get called if a call to pvPortMalloc() fails. + * pvPortMalloc() is called internally by the kernel whenever a task, queue, + * timer or semaphore is created. It is also called by various parts of the + * demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then + * the size of the heap available to pvPortMalloc() is defined by + * configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize() + * API function can be used to query the size of free heap space that remains + * (although it does not provide information on how the remaining heap might be + * fragmented). See http://www.freertos.org/a00111.html for more information. + */ vAssertCalled( __LINE__, __FILE__ ); } /*-----------------------------------------------------------*/ @@ -127,10 +141,8 @@ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ) ( void ) pxTask; /* Run time stack overflow checking is performed if - configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook - function is called if a stack overflow is detected. This function is - provided as an example only as stack overflow checking does not function - when running the FreeRTOS Windows port. */ + * configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook + * function is called if a stack overflow is detected. */ vAssertCalled( __LINE__, __FILE__ ); } /*-----------------------------------------------------------*/ @@ -138,11 +150,10 @@ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ) void vApplicationTickHook( void ) { /* This function will be called by each tick interrupt if - configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be - added here, but the tick hook is called from an interrupt context, so - code must not attempt to block, and only the interrupt safe FreeRTOS API - functions can be used (those that end in FromISR()). */ - + * configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be + * added here, but the tick hook is called from an interrupt context, so + * code must not attempt to block, and only the interrupt safe FreeRTOS API + * functions can be used (those that end in FromISR()). */ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) { vFullDemoTickHookFunction(); @@ -157,19 +168,17 @@ static BaseType_t xPrinted = pdFALSE; volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0; /* Called if an assertion passed to configASSERT() fails. See - http://www.freertos.org/a00110.html#configASSERT for more information. */ + * http://www.freertos.org/a00110.html#configASSERT for more information. */ /* Parameters are not used. */ ( void ) ulLine; ( void ) pcFileName; - printf( "ASSERT! Line %ld, file %s\r\n", ulLine, pcFileName ); - - taskENTER_CRITICAL(); + taskENTER_CRITICAL(); { /* You can step out of this function to debug the assertion by using - the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero - value. */ + * the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero + * value. */ while( ulSetToNonZeroInDebuggerToContinue == 0 ) { __asm volatile( "NOP" ); diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_blinky.c b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_blinky.c index a0a7bf72d..7edb6e905 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_blinky.c +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_blinky.c @@ -26,33 +26,18 @@ */ /****************************************************************************** - * NOTE 1: Windows will not be running the FreeRTOS demo threads continuously, so - * do not expect to get real time behaviour from the FreeRTOS Windows port, or - * this demo application. Also, the timing information in the FreeRTOS+Trace - * logs have no meaningful units. See the documentation page for the Windows - * port for further information: - * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html - * - * NOTE 2: This project provides two demo applications. A simple blinky style - * project, and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select - * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY - * in main.c. This file implements the simply blinky version. Console output - * is used in place of the normal LED toggling. - * - * NOTE 3: This file only contains the source code that is specific to the + * NOTE: This file only contains the source code that is specific to the * basic demo. Generic functions, such FreeRTOS hook functions, are defined * in main.c. ****************************************************************************** * - * main_blinky() creates one queue, one software timer, and two tasks. It then + * main_blinky() creates one queue, one software timer, and two tasks. It then * starts the scheduler. * * The Queue Send Task: * The queue send task is implemented by the prvQueueSendTask() function in * this file. It uses vTaskDelayUntil() to create a periodic task that sends - * the value 100 to the queue every 200 milliseconds (please read the notes - * above regarding the accuracy of timing under Windows). + * the value 100 to the queue every 200 milliseconds. * * The Queue Send Software Timer: * The timer is an auto-reload timer with a period of two seconds. The timer's @@ -66,19 +51,13 @@ * message to indicate if the data came from the queue send task or the queue * send software timer. * - * Expected Behaviour: + * Expected Behavior: * - The queue send task writes to the queue every 200ms, so every 200ms the * queue receive task will output a message indicating that data was received * on the queue from the queue send task. - * - The queue send software timer has a period of two seconds, and is reset - * each time a key is pressed. So if two seconds expire without a key being - * pressed then the queue receive task will output a message indicating that - * data was received on the queue from the queue send software timer. - * - * NOTE: Console input and output relies on Windows system calls, which can - * interfere with the execution of the FreeRTOS Windows port. This demo only - * uses Windows system call occasionally. Heavier use of Windows system calls - * can crash the port. + * - The queue send software timer has a period of two seconds, so every two + * seconds the queue receive task will output a message indicating that data + * was received on the queue from the queue send software timer. */ /* Standard includes. */ @@ -90,47 +69,55 @@ #include "timers.h" #include "semphr.h" -/* Priorities at which the tasks are created. */ +/** + * Priorities at which the tasks are created. + */ #define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) -/* The rate at which data is sent to the queue. The times are converted from -milliseconds to ticks using the pdMS_TO_TICKS() macro. */ +/** + * The rate at which data is sent to the queue. The times are converted from + * milliseconds to ticks using the pdMS_TO_TICKS() macro. + */ #define mainTASK_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200UL ) #define mainTIMER_SEND_FREQUENCY_MS pdMS_TO_TICKS( 2000UL ) -/* The number of items the queue can hold at once. */ +/** + * The number of items the queue can hold at once. + */ #define mainQUEUE_LENGTH ( 2 ) -/* The values sent to the queue receive task from the queue send task and the -queue send software timer respectively. */ +/** + * The values sent to the queue receive task from the queue send task and the + * queue send software timer respectively. + */ #define mainVALUE_SENT_FROM_TASK ( 100UL ) #define mainVALUE_SENT_FROM_TIMER ( 200UL ) - /*-----------------------------------------------------------*/ -/* +/** * The tasks as described in the comments at the top of this file. */ static void prvQueueReceiveTask( void *pvParameters ); static void prvQueueSendTask( void *pvParameters ); -/* +/** * The callback function executed when the software timer expires. */ static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle ); - /*-----------------------------------------------------------*/ -/* The queue used by both tasks. */ +/** + * The queue used by both tasks. + */ static QueueHandle_t xQueue = NULL; -/* A software timer that is started from the tick hook. */ +/** + * A software timer that is started from the tick hook. + */ static TimerHandle_t xTimer = NULL; - /*-----------------------------------------------------------*/ -/*** SEE THE COMMENTS AT THE TOP OF THIS FILE ***/ void main_blinky( void ) { const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS; @@ -141,7 +128,7 @@ const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS; if( xQueue != NULL ) { /* Start the two tasks as described in the comments at the top of this - file. */ + * file. */ xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */ "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ @@ -168,10 +155,10 @@ const TickType_t xTimerPeriod = mainTIMER_SEND_FREQUENCY_MS; } /* If all is well, the scheduler will now be running, and the following - line will never be reached. If the following line does execute, then - there was insufficient FreeRTOS heap memory available for the idle and/or - timer tasks to be created. See the memory management section on the - FreeRTOS web site for more details. */ + * line will never be reached. If the following line does execute, then + * there was insufficient FreeRTOS heap memory available for the idle and/or + * timer tasks to be created. See the memory management section on the + * FreeRTOS web site for more details. */ for( ;; ); } /*-----------------------------------------------------------*/ @@ -191,15 +178,15 @@ const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TASK; for( ;; ) { /* Place this task in the blocked state until it is time to run again. - The block time is specified in ticks, pdMS_TO_TICKS() was used to - convert a time specified in milliseconds into a time specified in ticks. - While in the Blocked state this task will not consume any CPU time. */ + * The block time is specified in ticks, pdMS_TO_TICKS() was used to + * convert a time specified in milliseconds into a time specified in ticks. + * While in the Blocked state this task will not consume any CPU time. */ vTaskDelayUntil( &xNextWakeTime, xBlockTime ); /* Send to the queue - causing the queue receive task to unblock and - write to the console. 0 is used as the block time so the send operation - will not block - it shouldn't need to block as the queue should always - have at least one space at this point in the code. */ + * write to the console. 0 is used as the block time so the send operation + * will not block - it shouldn't need to block as the queue should always + * have at least one space at this point in the code. */ xQueueSend( xQueue, &ulValueToSend, 0U ); } } @@ -210,16 +197,16 @@ static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle ) const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TIMER; /* This is the software timer callback function. The software timer has a - period of two seconds and is reset each time a key is pressed. This - callback function will execute if the timer expires, which will only happen - if a key is not pressed for two seconds. */ + * period of two seconds and is reset each time a key is pressed. This + * callback function will execute if the timer expires, which will only happen + * if a key is not pressed for two seconds. */ /* Avoid compiler warnings resulting from the unused parameter. */ ( void ) xTimerHandle; /* Send to the queue - causing the queue receive task to unblock and - write out a message. This function is called from the timer/daemon task, so - must not block. Hence the block time is set to 0. */ + * write out a message. This function is called from the timer/daemon task, + * so must not block. Hence the block time is set to 0. */ xQueueSend( xQueue, &ulValueToSend, 0U ); } /*-----------------------------------------------------------*/ @@ -234,17 +221,14 @@ uint32_t ulReceivedValue; for( ;; ) { /* Wait until something arrives in the queue - this task will block - indefinitely provided INCLUDE_vTaskSuspend is set to 1 in - FreeRTOSConfig.h. It will not use any CPU time while it is in the - Blocked state. */ + * indefinitely provided INCLUDE_vTaskSuspend is set to 1 in + * FreeRTOSConfig.h. It will not use any CPU time while it is in the + * Blocked state. */ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); /* To get here something must have been received from the queue, but - is it an expected value? Normally calling printf() from a task is not - a good idea. Here there is lots of stack space and only one task is - using console IO so it is ok. However, note the comments at the top of - this file about the risks of making Windows system calls (such as - console output) from a FreeRTOS task. */ + * is it an expected value? This is the only task that uses stdout so its + * ok to call printf() directly. Do not call printf from any other task. */ if( ulReceivedValue == mainVALUE_SENT_FROM_TASK ) { printf( "Message received from task\r\n" ); @@ -262,4 +246,3 @@ uint32_t ulReceivedValue; } } /*-----------------------------------------------------------*/ - diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_full.c b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_full.c index d8e2561f9..be46ea8df 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_full.c +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/main_full.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.0.1 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -25,8 +25,13 @@ * 1 tab == 4 spaces! */ -/* - * main() creates all the demo application tasks, then starts the scheduler. +/****************************************************************************** + * NOTE: This file only contains the source code that is specific to the + * basic demo. Generic functions, such FreeRTOS hook functions, are defined + * in main.c. + ****************************************************************************** + * + * main_full() creates all the demo application tasks, then starts the scheduler. * The web documentation provides more details of the standard demo application * tasks, which provide no particular functionality but do provide a good * example of how to use the FreeRTOS API. @@ -34,13 +39,21 @@ * In addition to the standard demo tasks, the following tasks and tests are * defined and/or created within this file: * - * "Check" task - This only executes every five seconds but has a high priority - * to ensure it gets processor time. Its main function is to check that all the - * standard demo tasks are still operational. While no errors have been - * discovered the check task will print out "OK" and the current simulated tick - * time. If an error is discovered in the execution of a task then the check - * task will print out an appropriate error message. + * "Register tests": + * prvRegTest1Task and prvRegTest2Task implement register tests. These functions + * are just entry points and actual tests are written in the assembler file + * regtest_xtensa.S. These tests populate core registers with a known set of + * values and keep verifying them in a loop. Any corruption will indicate an + * error in context switching mechanism. * + * "Check" task: + * This only executes every five seconds but has a high priority to ensure it + * gets processor time. Its main function is to check that all the standard demo + * tasks are still operational. While no errors have been discovered the check + * task will print out "No errors", the current simulated tick time, free heap + * size and the minimum free heap size so far. If an error is discovered in the + * execution of a task then the check task will print out an appropriate error + * message. */ @@ -67,7 +80,6 @@ #include "TimerDemo.h" #include "countsem.h" #include "death.h" -#include "dynamic.h" #include "QueueSet.h" #include "QueueOverwrite.h" #include "EventGroupsDemo.h" @@ -81,7 +93,9 @@ #include "StreamBufferDemo.h" #include "StreamBufferInterrupt.h" -/* Priorities at which the tasks are created. */ +/** + * Priorities at which the tasks are created. + */ #define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) @@ -93,18 +107,74 @@ #define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY ) #define mainQUEUE_OVERWRITE_PRIORITY ( tskIDLE_PRIORITY ) +/** + * Period used in timer tests. + */ #define mainTIMER_TEST_PERIOD ( 50 ) -/* The task that periodically checks that all the standard demo tasks are +/** + * Parameters that are passed into the register check tasks solely for the + * purpose of ensuring parameters are passed into tasks correctly. + */ +#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 ) +#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 ) + +/** + * Determines whether to enable interrupt queue tests. + * + * Interrupt queue tests are used to test interrupt nesting and enabling them + * interferes with proper functioning of other tests. This macro controls + * whether to enable interrupt queue tests or all other tests: + * + * * When mainENABLE_INT_QUEUE_TESTS is set to 1, interrupt queue tests are + * enabled and every other test is disabled. + * * When mainENABLE_INT_QUEUE_TESTS is set to 0, interrupt queue tests are + * disabled and every other test is enabled. + */ +#define mainENABLE_INT_QUEUE_TESTS ( 0 ) +/*-----------------------------------------------------------*/ + +/** + * The task that periodically checks that all the standard demo tasks are * still executing and error free. */ static void prvCheckTask( void *pvParameters ); +/** + * Tasks that implement register tests. + */ +static void prvRegTest1Task( void *pvParameters ); +static void prvRegTest2Task( void *pvParameters ); + +/** + * Functions that implement register tests. + * + * These are implemented in assembler file regtest_xtensa.S. + */ +extern void vRegTest1( void ); +extern void vRegTest2( void ); /*-----------------------------------------------------------*/ -/* The variable into which error messages are latched. */ +/** + * The variable into which error messages are latched. + */ static char *pcStatusMessage = "No errors"; +/** + * The following two variables are used to communicate the status of the + * register check tasks to the check task. If the variables keep incrementing, + * then the register check tasks have not discovered any errors. If a variable + * stops incrementing, then an error has been found. + */ +volatile unsigned long ulRegTest1Counter = 0UL, ulRegTest2Counter = 0UL; + +/** + * The following variable is used to communicate whether the timers for the + * IntQueue tests have been Initialized. This is needed to ensure that the queues + * are accessed from the tick hook only after they have been created in the + * interrupt queue test. + */ +volatile BaseType_t xTimerForQueueTestInitialized = pdFALSE; /*-----------------------------------------------------------*/ int main_full( void ) @@ -112,51 +182,63 @@ int main_full( void ) /* Start the check task as described at the top of this file. */ xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); - /* Create the standard demo tasks. */ - vStartTaskNotifyTask(); - vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); - vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); - vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); - vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); - vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); - - vStartQueuePeekTasks(); - vStartMathTasks( mainFLOP_TASK_PRIORITY ); - vStartRecursiveMutexTasks(); - vStartCountingSemaphoreTasks(); - vStartDynamicPriorityTasks(); - vStartQueueSetTasks(); - - vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); - vStartEventGroupTasks(); - vStartInterruptSemaphoreTasks(); - vStartQueueSetPollingTask(); - vCreateBlockTimeTasks(); - - vCreateAbortDelayTasks(); - vStartMessageBufferTasks( configMINIMAL_STACK_SIZE ); - - vStartStreamBufferTasks(); - vStartStreamBufferInterruptDemo(); - - #if( configUSE_PREEMPTION != 0 ) + #if( mainENABLE_INT_QUEUE_TESTS == 0 ) { - /* Don't expect these tasks to pass when preemption is not used. */ - vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); - } - #endif + /* Create the standard demo tasks. */ + vStartTaskNotifyTask(); + vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); + vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); + vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); + vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); + vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); + + vStartQueuePeekTasks(); + vStartMathTasks( mainFLOP_TASK_PRIORITY ); + vStartRecursiveMutexTasks(); + vStartCountingSemaphoreTasks(); + vStartQueueSetTasks(); + + vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY ); + vStartEventGroupTasks(); + vStartInterruptSemaphoreTasks(); + vStartQueueSetPollingTask(); + vCreateBlockTimeTasks(); + + #if( configUSE_PREEMPTION != 0 ) + { + /* Don't expect these tasks to pass when preemption is not used. */ + vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); + } + #endif + + vCreateAbortDelayTasks(); + vStartMessageBufferTasks( configMINIMAL_STACK_SIZE ); - /* The suicide tasks must be created last as they need to know how many - tasks were running prior to their creation. This then allows them to - ascertain whether or not the correct/expected number of tasks are running at - any given time. */ - vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + vStartStreamBufferTasks(); + vStartStreamBufferInterruptDemo(); + + /* Create the register check tasks, as described at the top of this file */ + xTaskCreate( prvRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL ); + + /* The suicide tasks must be created last as they need to know how many + * tasks were running prior to their creation. This then allows them to + * ascertain whether or not the correct/expected number of tasks are + * running at any given time. */ + vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + } + #else /* mainENABLE_INT_QUEUE_TESTS */ + { + /* Start interrupt queue test tasks. */ + vStartInterruptQueueTasks(); + } + #endif /* mainENABLE_INT_QUEUE_TESTS */ /* Start the scheduler itself. */ vTaskStartScheduler(); /* Should never get here unless there was not enough heap space to create - the idle and other system tasks. */ + * the idle and other system tasks. */ return 0; } /*-----------------------------------------------------------*/ @@ -165,6 +247,7 @@ static void prvCheckTask( void *pvParameters ) { TickType_t xNextWakeTime; const TickType_t xCycleFrequency = pdMS_TO_TICKS( 5000UL ); +static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0; /* Just to remove compiler warning. */ ( void ) pvParameters; @@ -177,108 +260,127 @@ const TickType_t xCycleFrequency = pdMS_TO_TICKS( 5000UL ); /* Place this task in the blocked state until it is time to run again. */ vTaskDelayUntil( &xNextWakeTime, xCycleFrequency ); - /* Check the standard demo tasks are running without error. */ - #if( configUSE_PREEMPTION != 0 ) + #if( mainENABLE_INT_QUEUE_TESTS == 0 ) { - /* These tasks are only created when preemption is used. */ - if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE ) + /* Check the standard demo tasks are running without error. */ + #if( configUSE_PREEMPTION != 0 ) { - pcStatusMessage = "Error: TimerDemo"; + /* These tasks are only created when preemption is used. */ + if( xAreTimerDemoTasksStillRunning( xCycleFrequency ) != pdTRUE ) + { + pcStatusMessage = "Error: TimerDemo"; + } } - } - #endif + #endif - if( xAreTaskNotificationTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: Notification"; - } - else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: IntMath"; - } - else if( xAreGenericQueueTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: GenQueue"; - } - else if( xAreBlockingQueuesStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: BlockQueue"; - } - else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: SemTest"; - } - else if( xArePollingQueuesStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: PollQueue"; - } - else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: QueuePeek"; - } - else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: RecMutex"; - } - else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: CountSem"; - } - else if( xAreDynamicPriorityTasksStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Dynamic"; - } - else if( xAreQueueSetTasksStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Queue set"; - } - else if( xAreEventGroupTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: EventGroup"; - } - else if( xIsQueueOverwriteTaskStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Queue overwrite"; - } - else if( xAreQueueSetPollTasksStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Queue set polling"; - } - else if( xAreBlockTimeTestTasksStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Block time"; - } - else if( xAreMessageBufferTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: MessageBuffer"; - } - else if( xAreAbortDelayTestTasksStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Abort delay"; - } - else if( xAreStreamBufferTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: StreamBuffer"; - } - else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS ) - { - pcStatusMessage = "Error: Stream buffer interrupt"; - } - else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: IntSem"; - } - else if( xIsCreateTaskStillRunning() != pdTRUE ) - { - pcStatusMessage = "Error: Death"; + if( xAreTaskNotificationTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: Notification"; + } + else if( xAreBlockingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: BlockQueue"; + } + else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: SemTest"; + } + else if( xArePollingQueuesStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: PollQueue"; + } + else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: IntMath"; + } + else if( xAreGenericQueueTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: GenQueue"; + } + else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: QueuePeek"; + } + else if( xAreMathsTaskStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Flop"; + } + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: RecMutex"; + } + else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: CountSem"; + } + else if( xAreQueueSetTasksStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Queue set"; + } + else if( xIsQueueOverwriteTaskStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Queue overwrite"; + } + else if( xAreEventGroupTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: EventGroup"; + } + else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: IntSem"; + } + else if( xAreQueueSetPollTasksStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Queue set polling"; + } + else if( xAreBlockTimeTestTasksStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Block time"; + } + else if( xAreAbortDelayTestTasksStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Abort delay"; + } + else if( xAreMessageBufferTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: MessageBuffer"; + } + else if( xAreStreamBufferTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: StreamBuffer"; + } + else if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS ) + { + pcStatusMessage = "Error: Stream buffer interrupt"; + } + else if( xIsCreateTaskStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: Death"; + } + else if( ulLastRegTest1Value == ulRegTest1Counter ) + { + pcStatusMessage = "Error: Reg Test 1"; + } + else if( ulLastRegTest2Value == ulRegTest2Counter ) + { + pcStatusMessage = "Error: Reg Test 2"; + } + + /* Update register test counters. */ + ulLastRegTest1Value = ulRegTest1Counter; + ulLastRegTest2Value = ulRegTest2Counter; } - else if( xAreMathsTaskStillRunning() != pdPASS ) + #else /* mainENABLE_INT_QUEUE_TESTS */ { - pcStatusMessage = "Error: Flop"; + if( xAreIntQueueTasksStillRunning() != pdTRUE ) + { + pcStatusMessage = "Error: IntQueue"; + } } + #endif /* mainENABLE_INT_QUEUE_TESTS */ /* This is the only task that uses stdout so its ok to call printf() - directly. */ + * directly. Do not call printf from any other task. */ printf( "%s - tick count %zu - free heap %zu - min free heap %zu\r\n", pcStatusMessage, xTaskGetTickCount(), xPortGetFreeHeapSize(), @@ -292,39 +394,89 @@ void vFullDemoTickHookFunction( void ) { TaskHandle_t xTimerTask; - /* Call the periodic timer test, which tests the timer API functions that - can be called from an ISR. */ - #if( configUSE_PREEMPTION != 0 ) + #if( mainENABLE_INT_QUEUE_TESTS == 0 ) { - /* Only created when preemption is used. */ - vTimerPeriodicISRTests(); - } - #endif + /* Exercise using task notifications from an interrupt. */ + xNotifyTaskFromISR(); + + /* Write to a queue that is in use as part of the queue set demo to + * demonstrate using queue sets from an ISR. */ + vQueueSetAccessQueueSetFromISR(); - /* Call the periodic queue overwrite from ISR demo. */ - vQueueOverwritePeriodicISRDemo(); + /* Call the periodic queue overwrite from ISR demo. */ + vQueueOverwritePeriodicISRDemo(); - /* Write to a queue that is in use as part of the queue set demo to - demonstrate using queue sets from an ISR. */ - vQueueSetAccessQueueSetFromISR(); - vQueueSetPollingInterruptAccess(); + /* Exercise event groups from interrupts. */ + vPeriodicEventGroupsProcessing(); - /* Exercise event groups from interrupts. */ - vPeriodicEventGroupsProcessing(); + /* Exercise giving mutexes from an interrupt. */ + vInterruptSemaphorePeriodicTest(); + + /* Queue set access from interrupt. */ + vQueueSetPollingInterruptAccess(); + + /* Call the periodic timer test, which tests the timer API functions that + * can be called from an ISR. */ + #if( configUSE_PREEMPTION != 0 ) + { + /* Only created when preemption is used. */ + vTimerPeriodicISRTests(); + } + #endif - /* Exercise giving mutexes from an interrupt. */ - vInterruptSemaphorePeriodicTest(); + /* Writes to stream buffer byte by byte to test the stream buffer trigger + * level functionality. */ + vPeriodicStreamBufferProcessing(); - /* Exercise using task notifications from an interrupt. */ - xNotifyTaskFromISR(); + /* Writes a string to a string buffer four bytes at a time to demonstrate + * a stream being sent from an interrupt to a task. */ + vBasicStreamBufferSendFromISR(); + } + #else /* mainENABLE_INT_QUEUE_TESTS */ + { + /* Access queues from interrupt. Make sure to access after the queues have + * been created. */ + if( xTimerForQueueTestInitialized == pdTRUE ) + { + portYIELD_FROM_ISR( xFirstTimerHandler() ); + } + } + #endif /* mainENABLE_INT_QUEUE_TESTS */ +} +/*-----------------------------------------------------------*/ - /* Writes to stream buffer byte by byte to test the stream buffer trigger - level functionality. */ - vPeriodicStreamBufferProcessing(); +static void prvRegTest1Task( void *pvParameters ) +{ + /* Although the regtest task is written in assembly, its entry point is + * written in C for convenience of checking the task parameter is being + * passed in correctly. */ + if( pvParameters == mainREG_TEST_TASK_1_PARAMETER ) + { + /* Start the part of the test that is written in assembly. */ + vRegTest1(); + } - /* Writes a string to a string buffer four bytes at a time to demonstrate - a stream being sent from an interrupt to a task. */ - vBasicStreamBufferSendFromISR(); + /* The following line will only execute if the task parameter is found to + * be incorrect. The check task will detect that the regtest loop counter is + * not being incremented and flag an error. */ + vTaskDelete( NULL ); } /*-----------------------------------------------------------*/ +static void prvRegTest2Task( void *pvParameters ) +{ + /* Although the regtest task is written in assembly, its entry point is + * written in C for convenience of checking the task parameter is being + * passed in correctly. */ + if( pvParameters == mainREG_TEST_TASK_2_PARAMETER ) + { + /* Start the part of the test that is written in assembly. */ + vRegTest2(); + } + + /* The following line will only execute if the task parameter is found to + * be incorrect. The check task will detect that the regtest loop counter is + * not being incremented and flag an error. */ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/regtest_xtensa.S b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/regtest_xtensa.S index bd700f09a..aea934090 100644 --- a/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/regtest_xtensa.S +++ b/FreeRTOS/Demo/Tensilica_Simulator_Xplorer_XCC/regtest_xtensa.S @@ -43,15 +43,15 @@ vRegTest1: - /* Set initial values into the general purpose registers. */ - /* a0 = return address, a1 = stack pointer. */ + /* Set initial values into the general purpose registers. + * a0 = return address, a1 = stack pointer. */ #ifdef __XTENSA_WINDOWED_ABI__ entry a1, 64 - s32i a0, a1, 0 /* Save return address */ + s32i a0, a1, 0 /* Save return address. */ #else addi a1, a1, -64 - s32i a0, a1, 0 /* Save return address */ - s32i a12, a1, 4 /* Save callee-saved regs if call0 ABI */ + s32i a0, a1, 0 /* Save return address. */ + s32i a12, a1, 4 /* Save callee-saved regs if call0 ABI. */ s32i a13, a1, 8 s32i a14, a1, 12 s32i a15, a1, 16 @@ -74,7 +74,7 @@ vRegTest1: _RegTest1Loop: /* Loop checking the values originally loaded into the general purpose - registers remain through the life of the task. */ + * registers remain through the life of the task. */ movi a0, 0x11111111 bne a0, a2, _RegTest1Error movi a0, 0x22222222 @@ -105,7 +105,7 @@ _RegTest1Loop: bne a0, a15, _RegTest1Error /* Incrememnt the loop counter to prove this task has not gone into the - error null loop. */ + * error null loop. */ s32i a2, a1, 20 movi a2, ulRegTest1Counter l32i a0, a2, 0 @@ -127,15 +127,15 @@ _RegTest1Error: vRegTest2: - /* Set initial values into the general purpose registers. */ - /* a0 = return address, a1 = stack pointer. */ + /* Set initial values into the general purpose registers. + * a0 = return address, a1 = stack pointer. */ #ifdef __XTENSA_WINDOWED_ABI__ entry a1, 64 - s32i a0, a1, 0 /* Save return address */ + s32i a0, a1, 0 /* Save return address. */ #else addi a1, a1, -64 - s32i a0, a1, 0 /* Save return address */ - s32i a12, a1, 4 /* Save callee-saved regs if call0 ABI */ + s32i a0, a1, 0 /* Save return address. */ + s32i a12, a1, 4 /* Save callee-saved regs if call0 ABI. */ s32i a13, a1, 8 s32i a14, a1, 12 s32i a15, a1, 16 @@ -161,7 +161,7 @@ _ReInit: _RegTest2Loop: /* Loop checking the values originally loaded into the general purpose - registers remain through the life of the task. */ + * registers remain through the life of the task. */ movi a0, 0x01010101 bne a0, a2, _RegTest1Error movi a0, 0x02020202 @@ -191,9 +191,9 @@ _RegTest2Loop: movi a0, 0x0e0e0e0e bne a0, a15, _RegTest1Error - /* Force a yield from one of the reg test tasks to increase coverage. */ - /* IMPORTANT: this call will trash some number of registers. Branch */ - /* to _ReInit to set things up again. */ + /* Force a yield from one of the reg test tasks to increase coverage. + * IMPORTANT: this call will trash some number of registers. Branch + * to _ReInit to set things up again. */ #ifdef __XTENSA_WINDOWED_ABI__ call8 vPortYield #else @@ -201,7 +201,7 @@ _RegTest2Loop: #endif /* Increment the loop counter to prove this task has not gone into the - error null loop. */ + * error null loop. */ s32i a2, a1, 20 movi a2, ulRegTest2Counter l32i a0, a2, 0 @@ -210,10 +210,8 @@ _RegTest2Loop: l32i a2, a1, 20 /* Loop again. */ - j _ReInit /* See comments above */ - /* j _RegTest2Loop */ + j _ReInit /* See comments above about not using j _RegTest2Loop. */ _RegTest2Error: .L2: j .L2 -