+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ------- -------- ---------------------------------------------------
+* 1.00a ecm/sdm 10/20/09 Initial version
+* 3.05a sdm 02/02/12 Save lr when profiling is enabled
+* 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
+* 'xil_errata.h' for errata description
+*
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+
+#include "xil_errata.h"
+
+.org 0
+.text
+.arm
+
+.global _boot
+.global _freertos_vector_table
+
+.global FIQInterrupt
+.global DataAbortInterrupt
+.global PrefetchAbortInterrupt
+.global vPortInstallFreeRTOSVectorTable
+
+.extern FreeRTOS_IRQ_Handler
+.extern FreeRTOS_SWI_Handler
+
+.section .freertos_vectors
+_freertos_vector_table:
+ B _boot
+ B FreeRTOS_Undefined
+ ldr pc, _swi
+ B FreeRTOS_PrefetchAbortHandler
+ B FreeRTOS_DataAbortHandler
+ NOP /* Placeholder for address exception vector*/
+ LDR PC, _irq
+ B FreeRTOS_FIQHandler
+
+_irq: .word FreeRTOS_IRQ_Handler
+_swi: .word FreeRTOS_SWI_Handler
+
+
+.align 4
+FreeRTOS_FIQHandler: /* FIQ vector handler */
+ stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */
+FIQLoop:
+ blx FIQInterrupt /* FIQ vector */
+ ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
+ subs pc, lr, #4 /* adjust return */
+
+.align 4
+FreeRTOS_Undefined: /* Undefined handler */
+ b .
+
+.align 4
+FreeRTOS_DataAbortHandler: /* Data Abort handler */
+#ifdef CONFIG_ARM_ERRATA_775420
+ dsb
+#endif
+ stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */
+ blx DataAbortInterrupt /*DataAbortInterrupt :call C function here */
+ ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
+ subs pc, lr, #4 /* adjust return */
+
+.align 4
+FreeRTOS_PrefetchAbortHandler: /* Prefetch Abort handler */
+#ifdef CONFIG_ARM_ERRATA_775420
+ dsb
+#endif
+ stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code */
+ blx PrefetchAbortInterrupt /* PrefetchAbortInterrupt: call C function here */
+ ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
+ subs pc, lr, #4 /* adjust return */
+
+.align 4
+.type vPortInstallFreeRTOSVectorTable, %function
+vPortInstallFreeRTOSVectorTable:
+
+ /* Set VBAR to the vector table that contains the FreeRTOS handlers. */
+ ldr r0, =_freertos_vector_table
+ mcr p15, 0, r0, c12, c0, 0
+ dsb
+ isb
+ bx lr
+
+
+.end
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/FreeRTOS_tick_config.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/FreeRTOS_tick_config.c
new file mode 100644
index 0000000000..8db41eee1e
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/FreeRTOS_tick_config.c
@@ -0,0 +1,136 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Xilinx includes. */
+#include "xscutimer.h"
+#include "xscugic.h"
+
+#define XSCUTIMER_CLOCK_HZ ( XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 2UL )
+
+static XScuTimer xTimer;
+XScuGic xInterruptController; /* Interrupt controller instance */
+
+/*
+ * The application must provide a function that configures a peripheral to
+ * create the FreeRTOS tick interrupt, then define configSETUP_TICK_INTERRUPT()
+ * in FreeRTOSConfig.h to call the function. This file contains a function
+ * that is suitable for use on the Zynq SoC.
+ */
+void vConfigureTickInterrupt( void )
+{
+BaseType_t xStatus;
+extern void FreeRTOS_Tick_Handler( void );
+XScuTimer_Config *pxTimerConfig;
+XScuGic_Config *pxGICConfig;
+const uint8_t ucRisingEdge = 3;
+
+ /* This function is called with the IRQ interrupt disabled, and the IRQ
+ interrupt should be left disabled. It is enabled automatically when the
+ scheduler is started. */
+
+ /* Ensure XScuGic_CfgInitialize() has been called. In this demo it has
+ already been called from prvSetupHardware() in main(). */
+ pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
+ xStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* The priority must be the lowest possible. */
+ XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_SCUTIMER_INTR, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucRisingEdge );
+
+ /* Install the FreeRTOS tick handler. */
+ xStatus = XScuGic_Connect( &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, ( void * ) &xTimer );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* Initialise the timer. */
+ pxTimerConfig = XScuTimer_LookupConfig( XPAR_SCUTIMER_DEVICE_ID );
+ xStatus = XScuTimer_CfgInitialize( &xTimer, pxTimerConfig, pxTimerConfig->BaseAddr );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* Enable Auto reload mode. */
+ XScuTimer_EnableAutoReload( &xTimer );
+
+ /* Ensure there is no prescale. */
+ XScuTimer_SetPrescaler( &xTimer, 0 );
+
+ /* Load the timer counter register. */
+ XScuTimer_LoadTimer( &xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ );
+
+ /* Start the timer counter and then wait for it to timeout a number of
+ times. */
+ XScuTimer_Start( &xTimer );
+
+ /* Enable the interrupt for the xTimer in the interrupt controller. */
+ XScuGic_Enable( &xInterruptController, XPAR_SCUTIMER_INTR );
+
+ /* Enable the interrupt in the xTimer itself. */
+ vClearTickInterrupt();
+ XScuTimer_EnableInterrupt( &xTimer );
+}
+/*-----------------------------------------------------------*/
+
+void vClearTickInterrupt( void )
+{
+ XScuTimer_ClearInterruptStatus( &xTimer );
+}
+/*-----------------------------------------------------------*/
+
+/* This is the callback function which is called by the FreeRTOS Cortex-A port
+layer in response to an interrupt. If the function is called
+vApplicationFPUSafeIRQHandler() then it is called after the floating point
+registers have been saved. If the function is called vApplicationIRQHandler()
+then it will be called without first having saved the FPU registers. See
+http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html for
+more information */
+void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
+{
+extern const XScuGic_Config XScuGic_ConfigTable[];
+static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable;
+uint32_t ulInterruptID;
+const XScuGic_VectorTableEntry *pxVectorEntry;
+
+ /* Re-enable interrupts. */
+ __asm ( "cpsie i" );
+
+ /* The ID of the interrupt is obtained by bitwise anding the ICCIAR value
+ with 0x3FF. */
+ ulInterruptID = ulICCIAR & 0x3FFUL;
+ if( ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS )
+ {
+ /* Call the function installed in the array of installed handler functions. */
+ pxVectorEntry = &( pxVectorTable[ ulInterruptID ] );
+ pxVectorEntry->Handler( pxVectorEntry->CallBackRef );
+ }
+}
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/ParTest.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/ParTest.c
new file mode 100644
index 0000000000..5383bd603c
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/ParTest.c
@@ -0,0 +1,100 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*-----------------------------------------------------------
+ * Simple IO routines to control the LEDs.
+ * This file is called ParTest.c for historic reasons. Originally it stood for
+ * PARallel port TEST.
+ *-----------------------------------------------------------*/
+
+/* Standard includes for printing messages when QEMU is used (as LEDs can't be
+seen). */
+#include
+#include "xil_printf.h"
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Demo includes. */
+#include "partest.h"
+
+/* Xilinx includes. */
+#include "xgpiops.h"
+
+#define partstNUM_LEDS ( 1 )
+#define partstDIRECTION_OUTPUT ( 1 )
+#define partstOUTPUT_ENABLED ( 1 )
+#define partstLED_OUTPUT ( 10 ) /* Change to 47 for MicroZed. */
+
+/*-----------------------------------------------------------*/
+
+static XGpioPs xGpio;
+
+/*-----------------------------------------------------------*/
+
+void vParTestInitialise( void )
+{
+XGpioPs_Config *pxConfigPtr;
+BaseType_t xStatus;
+
+ /* Initialise the GPIO driver. */
+ pxConfigPtr = XGpioPs_LookupConfig( XPAR_XGPIOPS_0_DEVICE_ID );
+ xStatus = XGpioPs_CfgInitialize( &xGpio, pxConfigPtr, pxConfigPtr->BaseAddr );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* Enable outputs and set low. */
+ XGpioPs_SetDirectionPin( &xGpio, partstLED_OUTPUT, partstDIRECTION_OUTPUT );
+ XGpioPs_SetOutputEnablePin( &xGpio, partstLED_OUTPUT, partstOUTPUT_ENABLED );
+ XGpioPs_WritePin( &xGpio, partstLED_OUTPUT, 0x0 );
+}
+/*-----------------------------------------------------------*/
+
+void vParTestSetLED( UBaseType_t uxLED, BaseType_t xValue )
+{
+ ( void ) uxLED;
+ XGpioPs_WritePin( &xGpio, partstLED_OUTPUT, xValue );
+}
+/*-----------------------------------------------------------*/
+
+void vParTestToggleLED( unsigned portBASE_TYPE uxLED )
+{
+BaseType_t xLEDState;
+
+ ( void ) uxLED;
+
+ xLEDState = XGpioPs_ReadPin( &xGpio, partstLED_OUTPUT );
+ XGpioPs_WritePin( &xGpio, partstLED_OUTPUT, !xLEDState );
+
+ #if( configUSING_QEMU == 1 )
+ /* Can't see the LED blink when using QEMU, so print a message as well. */
+ xil_printf( "blink\n" );
+ #endif
+}
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/Xilinx.spec b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/Xilinx.spec
new file mode 100644
index 0000000000..9c27dcadce
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/Xilinx.spec
@@ -0,0 +1,2 @@
+*startfile:
+crti%O%s crtbegin%O%s
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/blinky_demo/main_blinky.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/blinky_demo/main_blinky.c
new file mode 100644
index 0000000000..69d5fd6ed2
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/blinky_demo/main_blinky.c
@@ -0,0 +1,195 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/******************************************************************************
+ * NOTE 1: 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 three. See the notes on using
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY in main.c. This file implements the
+ * simply blinky style version.
+ *
+ * NOTE 2: This file only contains the source code that is specific to the
+ * basic demo. Generic functions, such FreeRTOS hook functions, and functions
+ * required to configure the hardware are defined in main.c.
+ ******************************************************************************
+ *
+ * Set configUSING_QEMU to 1 in FreeRTOS.org to have the demo output to the
+ * QEMU UART. Not simulated time is much slower than calendar time when using
+ * QEMU, so three seconds of simulated time is a lot longer than three seconds
+ * of emulated time.
+ *
+ * main_blinky() creates one queue, 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. prvQueueSendTask() sits in a loop that causes it to repeatedly
+ * block for 200 milliseconds, before sending the value 100 to the queue that
+ * was created within main_blinky(). Once the value is sent, the task loops
+ * back around to block for another 200 milliseconds...and so on.
+ *
+ * The Queue Receive Task:
+ * The queue receive task is implemented by the prvQueueReceiveTask() function
+ * in this file. prvQueueReceiveTask() sits in a loop where it repeatedly
+ * blocks on attempts to read data from the queue that was created within
+ * main_blinky(). When data is received, the task checks the value of the
+ * data, and if the value equals the expected 100, toggles an LED (writes "blink"
+ * to the UART when using QEMU). The 'block time' parameter passed to the queue
+ * receive function specifies that the task should be held in the Blocked state
+ * indefinitely to wait for data to be available on the queue. The queue
+ * receive task will only leave the Blocked state when the queue send task
+ * writes to the queue. As the queue send task writes to the queue every 200
+ * milliseconds, the queue receive task leaves the Blocked state every 200
+ * milliseconds, and therefore toggles the LED (or writes "blink" to the UART)
+ * every 200 milliseconds. Note when using QEMU the emulated 200ms is much
+ * longer than a real 200ms of calendar time.
+ */
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Standard demo includes. */
+#include "partest.h"
+
+/* 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 200ms value is converted
+to ticks using the portTICK_PERIOD_MS constant. */
+#define mainQUEUE_SEND_FREQUENCY_MS ( 200 / portTICK_PERIOD_MS )
+
+/* The number of items the queue can hold. This is 1 as the receive task
+will remove items as they are added, meaning the send task should always find
+the queue empty. */
+#define mainQUEUE_LENGTH ( 1 )
+
+/* The LED toggled by the Rx task. */
+#define mainTASK_LED ( 0 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The tasks as described in the comments at the top of this file.
+ */
+static void prvQueueReceiveTask( void *pvParameters );
+static void prvQueueSendTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* The queue used by both tasks. */
+static QueueHandle_t xQueue = NULL;
+
+/*-----------------------------------------------------------*/
+
+void main_blinky( void )
+{
+ /* Create the queue. */
+ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
+
+ if( xQueue != NULL )
+ {
+ /* Start the two tasks as described in the comments at the top of this
+ 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. */
+ NULL, /* The parameter passed to the task - not used in this case. */
+ mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
+ NULL ); /* The task handle is not required, so NULL is passed. */
+
+ xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
+
+ /* Start the tasks and timer running. */
+ vTaskStartScheduler();
+ }
+
+ /* 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 either insufficient FreeRTOS heap memory available for the idle
+ and/or timer tasks to be created, or vTaskStartScheduler() was called from
+ User mode. See the memory management section on the FreeRTOS web site for
+ more details on the FreeRTOS heap http://www.freertos.org/a00111.html. The
+ mode from which main() is called is set in the C start up code and must be
+ a privileged mode (not user mode). */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueSendTask( void *pvParameters )
+{
+TickType_t xNextWakeTime;
+const unsigned long ulValueToSend = 100UL;
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ /* Initialise xNextWakeTime - this only needs to be done once. */
+ xNextWakeTime = xTaskGetTickCount();
+
+ for( ;; )
+ {
+ /* Place this task in the blocked state until it is time to run again. */
+ vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
+
+ /* Send to the queue - causing the queue receive task to unblock and
+ toggle the LED. 0 is used as the block time so the sending operation
+ will not block - it shouldn't need to block as the queue should always
+ be empty at this point in the code. */
+ xQueueSend( xQueue, &ulValueToSend, 0U );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueReceiveTask( void *pvParameters )
+{
+unsigned long ulReceivedValue;
+const unsigned long ulExpectedValue = 100UL;
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Wait until something arrives in the queue - this task will block
+ indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
+ FreeRTOSConfig.h. */
+ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
+
+ /* To get here something must have been received from the queue, but
+ is it the expected value? If it is, toggle the LED. */
+ if( ulReceivedValue == ulExpectedValue )
+ {
+ vParTestToggleLED( mainTASK_LED );
+ ulReceivedValue = 0U;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/IntQueueTimer.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/IntQueueTimer.c
new file mode 100644
index 0000000000..c49b217e19
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/IntQueueTimer.c
@@ -0,0 +1,270 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*
+ * This file initialises three timers as follows:
+ *
+ * Timer 0 and Timer 1 provide the interrupts that are used with the IntQ
+ * standard demo tasks, which test interrupt nesting and using queues from
+ * interrupts. Both these interrupts operate below the maximum syscall
+ * interrupt priority.
+ *
+ * Timer 2 is a much higher frequency timer that tests the nesting of interrupts
+ * that execute above the maximum syscall interrupt priority.
+ *
+ * All the timers can nest with the tick interrupt - creating a maximum
+ * interrupt nesting depth of 4.
+ *
+ * For convenience, the high frequency timer is also used to provide the time
+ * base for the run time stats.
+ */
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+
+/* Demo includes. */
+#include "IntQueueTimer.h"
+#include "IntQueue.h"
+
+/* Xilinx includes. */
+#include "xttcps.h"
+#include "xscugic.h"
+
+/* The frequencies at which the first two timers expire are slightly offset to
+ensure they don't remain synchronised. The frequency of the interrupt that
+operates above the max syscall interrupt priority is 10 times faster so really
+hammers the interrupt entry and exit code. */
+#define tmrTIMERS_USED 3
+#define tmrTIMER_0_FREQUENCY ( 2000UL )
+#define tmrTIMER_1_FREQUENCY ( 2001UL )
+#define tmrTIMER_2_FREQUENCY ( 20000UL )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The single interrupt service routines that is used to service all three
+ * timers.
+ */
+static void prvTimerHandler( void *CallBackRef );
+
+/*-----------------------------------------------------------*/
+
+/* Hardware constants. */
+static const BaseType_t xDeviceIDs[ tmrTIMERS_USED ] = { XPAR_XTTCPS_0_DEVICE_ID, XPAR_XTTCPS_1_DEVICE_ID, XPAR_XTTCPS_2_DEVICE_ID };
+static const BaseType_t xInterruptIDs[ tmrTIMERS_USED ] = { XPAR_XTTCPS_0_INTR, XPAR_XTTCPS_1_INTR, XPAR_XTTCPS_2_INTR };
+
+/* Timer configuration settings. */
+typedef struct
+{
+ uint32_t OutputHz; /* Output frequency. */
+ uint16_t Interval; /* Interval value. */
+ uint8_t Prescaler; /* Prescaler value. */
+ uint16_t Options; /* Option settings. */
+} TmrCntrSetup;
+
+static TmrCntrSetup xTimerSettings[ tmrTIMERS_USED ] =
+{
+ { tmrTIMER_0_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE },
+ { tmrTIMER_1_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE },
+ { tmrTIMER_2_FREQUENCY, 0, 0, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE }
+};
+
+/* Lower priority number means higher logical priority, so
+configMAX_API_CALL_INTERRUPT_PRIORITY - 1 is above the maximum system call
+interrupt priority. */
+static const UBaseType_t uxInterruptPriorities[ tmrTIMERS_USED ] =
+{
+ configMAX_API_CALL_INTERRUPT_PRIORITY + 1,
+ configMAX_API_CALL_INTERRUPT_PRIORITY,
+ configMAX_API_CALL_INTERRUPT_PRIORITY - 1
+};
+
+static XTtcPs xTimerInstances[ tmrTIMERS_USED ];
+
+/* Used to provide a means of ensuring the intended interrupt nesting depth is
+actually being reached. */
+extern uint32_t ulPortInterruptNesting; /* From the Cortex-A9 port layer. */
+static volatile uint32_t ulMaxRecordedNesting = 0;
+volatile uint32_t ulNestingCount = 0;
+
+/* Used to ensure the high frequency timer is running at the expected
+frequency. */
+static volatile uint32_t ulHighFrequencyTimerCounts = 0;
+
+/*-----------------------------------------------------------*/
+
+void vInitialiseTimerForIntQueueTest( void )
+{
+BaseType_t xStatus;
+TmrCntrSetup *pxTimerSettings;
+extern XScuGic xInterruptController;
+BaseType_t xTimer;
+XTtcPs *pxTimerInstance;
+XTtcPs_Config *pxTimerConfiguration;
+const uint8_t ucRisingEdge = 3;
+
+ for( xTimer = 0; xTimer < tmrTIMERS_USED; xTimer++ )
+ {
+ /* Look up the timer's configuration. */
+ pxTimerInstance = &( xTimerInstances[ xTimer ] );
+ pxTimerConfiguration = XTtcPs_LookupConfig( xDeviceIDs[ xTimer ] );
+ configASSERT( pxTimerConfiguration );
+
+ pxTimerSettings = &( xTimerSettings[ xTimer ] );
+
+ /* Initialise the device. */
+ xStatus = XTtcPs_CfgInitialize( pxTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress );
+ if( xStatus != XST_SUCCESS )
+ {
+ /* Not sure how to do this before XTtcPs_CfgInitialize is called
+ as pxTimerInstance is set within XTtcPs_CfgInitialize(). */
+ XTtcPs_Stop( pxTimerInstance );
+ xStatus = XTtcPs_CfgInitialize( pxTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress );
+ configASSERT( xStatus == XST_SUCCESS );
+ }
+
+ /* Set the options. */
+ XTtcPs_SetOptions( pxTimerInstance, pxTimerSettings->Options );
+
+ /* The timer frequency is preset in the pxTimerSettings structure.
+ Derive the values for the other structure members. */
+ XTtcPs_CalcIntervalFromFreq( pxTimerInstance, pxTimerSettings->OutputHz, &( pxTimerSettings->Interval ), &( pxTimerSettings->Prescaler ) );
+
+ /* Set the interval and prescale. */
+ XTtcPs_SetInterval( pxTimerInstance, pxTimerSettings->Interval );
+ XTtcPs_SetPrescaler( pxTimerInstance, pxTimerSettings->Prescaler );
+
+ /* The priority must be the lowest possible. */
+ XScuGic_SetPriorityTriggerType( &xInterruptController, xInterruptIDs[ xTimer ], uxInterruptPriorities[ xTimer ] << portPRIORITY_SHIFT, ucRisingEdge );
+
+ /* Connect to the interrupt controller. */
+ xStatus = XScuGic_Connect( &xInterruptController, xInterruptIDs[ xTimer ], ( Xil_InterruptHandler ) prvTimerHandler, ( void * ) pxTimerInstance );
+ configASSERT( xStatus == XST_SUCCESS);
+
+ /* Enable the interrupt in the GIC. */
+ XScuGic_Enable( &xInterruptController, xInterruptIDs[ xTimer ] );
+
+ /* Enable the interrupts in the timer. */
+ XTtcPs_EnableInterrupts( pxTimerInstance, XTTCPS_IXR_INTERVAL_MASK );
+
+ /* Start the timer. */
+ XTtcPs_Start( pxTimerInstance );
+ }
+}
+/*-----------------------------------------------------------*/
+volatile uint32_t ulUnexpectedInterrupts = 0;
+static void prvTimerHandler( void *pvCallBackRef )
+{
+uint32_t ulInterruptStatus;
+XTtcPs *pxTimer = ( XTtcPs * ) pvCallBackRef;
+BaseType_t xYieldRequired = pdFALSE;
+
+#if( configASSERT_DEFINED == 1 )
+ /* Test floating point access within nested interrupts. */
+ volatile long double d1, d2;
+#endif
+
+ /* If this is the only interrupt executing then the nesting count will be 1. */
+ if( ulPortInterruptNesting > 1UL )
+ {
+ ulNestingCount++;
+ }
+
+ /* Read the interrupt status, then write it back to clear the interrupt. */
+ ulInterruptStatus = XTtcPs_GetInterruptStatus( pxTimer );
+ XTtcPs_ClearInterruptStatus( pxTimer, ulInterruptStatus );
+
+ /* Only one interrupt event type is expected. */
+ if( ulInterruptStatus != 0 )
+ {
+ configASSERT( ( XTTCPS_IXR_INTERVAL_MASK & ulInterruptStatus ) != 0 );
+
+ /* Check the device ID to know which IntQueue demo to call. */
+ if( pxTimer->Config.DeviceId == xDeviceIDs[ 0 ] )
+ {
+ #if( configASSERT_DEFINED == 1 )
+ {
+ /* Test floating point access within nested interrupts. */
+ d1 = 1.5L;
+ d2 = 5.25L;
+ }
+ #endif /* configASSERT_DEFINED */
+
+ xYieldRequired = xFirstTimerHandler();
+
+ /* Will fail eventually if flop context switch is not correct in
+ interrupts. Keep calculation simple so the answer is exact even when
+ using flop. */
+ configASSERT( ( d1 * d2 ) == ( 1.5L * 5.25L ) );
+ }
+ else if( pxTimer->Config.DeviceId == xDeviceIDs[ 1 ] )
+ {
+ #if( configASSERT_DEFINED == 1 )
+ {
+ /* Test floating point access within nested interrupts. */
+ d1 = 10.5L;
+ d2 = 5.5L;
+ }
+ #endif /* configASSERT_DEFINED */
+
+ xYieldRequired = xSecondTimerHandler();
+
+ /* Will fail eventually if flop context switch is not correct in
+ interrupts. Keep calculation simple so the answer is exact even when
+ using flop. */
+ configASSERT( ( d1 / d2 ) == ( 10.5L / 5.5L ) );
+ }
+ else
+ {
+ configASSERT( pxTimer->Config.DeviceId == xDeviceIDs[ 2 ] );
+
+ /* Used to check the timer is running at the expected frequency. */
+ ulHighFrequencyTimerCounts++;
+
+ /* Latch the highest interrupt nesting count detected for viewing
+ in the debugger (for test purposes). */
+ if( ulPortInterruptNesting > ulMaxRecordedNesting )
+ {
+ ulMaxRecordedNesting = ulPortInterruptNesting;
+ }
+
+ xYieldRequired = pdFALSE;
+ }
+
+ /* If xYieldRequired is not pdFALSE then calling either xFirstTimerHandler()
+ or xSecondTimerHandler() resulted in a task leaving the blocked state and
+ the task that left the blocked state had a priority higher than the currently
+ running task (the task this interrupt interrupted) - so a context switch
+ should be performed so the interrupt returns directly to the higher priority
+ task. xYieldRequired is tested inside the following macro. */
+ portYIELD_FROM_ISR( xYieldRequired );
+ }
+ else
+ {
+ ulUnexpectedInterrupts++;
+ }
+}
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/IntQueueTimer.h b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/IntQueueTimer.h
new file mode 100644
index 0000000000..f4e8873dc5
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/IntQueueTimer.h
@@ -0,0 +1,35 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+#ifndef INT_QUEUE_TIMER_H
+#define INT_QUEUE_TIMER_H
+
+void vInitialiseTimerForIntQueueTest( void );
+portBASE_TYPE xTimer0Handler( void );
+portBASE_TYPE xTimer1Handler( void );
+
+#endif
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/main_full.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/main_full.c
new file mode 100644
index 0000000000..9fc2b1439a
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/main_full.c
@@ -0,0 +1,528 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/******************************************************************************
+ * NOTE 1: This project provides two demo applications. A simple blinky
+ * style project and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLILNKY_DEMO_ONLY setting in main.c is used to select
+ * between the two. See the notes on using mainCREATE_SIMPLE_BLILNKY_DEMO_ONLY
+ * in main.c. This file implements the comprehensive version.
+ *
+ * NOTE 2: This file only contains the source code that is specific to the
+ * full demo. Generic functions, such FreeRTOS hook functions, and functions
+ * required to configure the hardware, are defined in main.c.
+ *
+ ******************************************************************************
+ *
+ * Set configUSING_QEMU to 1 in FreeRTOS.org to have the demo output to the
+ * QEMU UART. Not simulated time is much slower than calendar time when using
+ * QEMU, so three seconds of simulated time is a lot longer than three seconds
+ * of emulated time.
+ *
+ * main_full() creates all the demo application tasks and software timers, 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.
+ *
+ * In addition to the standard demo tasks, the following tasks and tests are
+ * defined and/or created within this file:
+ *
+ * "Reg test" tasks - These fill both the core and floating point registers with
+ * known values, then check that each register maintains its expected value for
+ * the lifetime of the task. Each task uses a different set of values. The reg
+ * test tasks execute with a very low priority, so get preempted very
+ * frequently. A register containing an unexpected value is indicative of an
+ * error in the context switching mechanism.
+ *
+ * "Check" task - The check task period is initially set to three seconds. The
+ * task checks that all the standard demo tasks, and the register check tasks,
+ * are not only still executing, but are executing without reporting any errors.
+ * If the check task discovers that a task has either stalled, or reported an
+ * error, then it changes its own execution period from the initial three
+ * seconds, to just 200ms. The check task also toggles an LED each time it is
+ * called (or prints "blink" to the UART when using QEMU). This provides a
+ * visual indication of the system status: If the LED toggles every three
+ * seconds (or "blink" is printed every emulated 3 seconds when using QEMU),
+ * then no issues have been discovered. If the LED toggles every 200ms, then an
+ * issue has been discovered with at least one task. If building for QEMU then
+ * a status message of the form "AAAA - StatusMessage:X - BB" is printed to the
+ * UART where AAAA is the tick count and StatusMessage:X is a human readable
+ * status message along with a bitwise error code to help identify which test
+ * failed in the case of an error, and BB is the number of times the interrupt
+ * nesting test has found interrupts to be nested.
+ */
+
+/* Standard includes. */
+#include
+#include "xil_printf.h"
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Standard demo application includes. */
+#include "flop.h"
+#include "semtest.h"
+#include "dynamic.h"
+#include "BlockQ.h"
+#include "blocktim.h"
+#include "countsem.h"
+#include "GenQTest.h"
+#include "recmutex.h"
+#include "death.h"
+#include "partest.h"
+#include "TimerDemo.h"
+#include "QueueOverwrite.h"
+#include "IntQueue.h"
+#include "EventGroupsDemo.h"
+#include "TaskNotify.h"
+#include "IntSemTest.h"
+#include "StaticAllocation.h"
+#include "AbortDelay.h"
+#include "MessageBufferDemo.h"
+#include "StreamBufferDemo.h"
+#include "StreamBufferInterrupt.h"
+#include "MessageBufferAMP.h"
+#include "QueueSet.h"
+
+
+/* Priorities for the demo application tasks. */
+#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1UL )
+#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2UL )
+#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3UL )
+#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )
+#define mainUART_COMMAND_CONSOLE_STACK_SIZE ( configMINIMAL_STACK_SIZE * 3UL )
+#define mainCOM_TEST_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
+#define mainQUEUE_OVERWRITE_PRIORITY ( tskIDLE_PRIORITY )
+
+/* The LED used by the check timer. */
+#define mainCHECK_LED ( 0 )
+
+/* A block time of zero simply means "don't block". */
+#define mainDONT_BLOCK ( 0UL )
+
+/* The period after which the check timer will expire, in ms, provided no errors
+have been reported by any of the standard demo tasks. ms are converted to the
+equivalent in ticks using the portTICK_PERIOD_MS constant. */
+#define mainNO_ERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 3000UL )
+
+/* The period at which the check timer will expire, in ms, if an error has been
+reported in one of the standard demo tasks. ms are converted to the equivalent
+in ticks using the portTICK_PERIOD_MS constant. */
+#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 200UL )
+
+/* 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 )
+
+/* The base period used by the timer test tasks. */
+#define mainTIMER_TEST_PERIOD ( 50 )
+
+/* Base stack size of tasks created in the message buffer demos. */
+#define mainMESSAGE_BUFFER_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The check task, as described at the top of this file.
+ */
+static void prvCheckTask( void *pvParameters );
+
+/*
+ * Register check tasks, and the tasks used to write over and check the contents
+ * of the FPU registers, as described at the top of this file. The nature of
+ * these files necessitates that they are written in an assembly file, but the
+ * entry points are kept in the C file for the convenience of checking the task
+ * parameter.
+ */
+static void prvRegTestTaskEntry1( void *pvParameters );
+extern void vRegTest1Implementation( void );
+static void prvRegTestTaskEntry2( void *pvParameters );
+extern void vRegTest2Implementation( void );
+
+/*
+ * Register commands that can be used with FreeRTOS+CLI. The commands are
+ * defined in CLI-Commands.c and File-Related-CLI-Command.c respectively.
+ */
+extern void vRegisterSampleCLICommands( void );
+
+/*
+ * The task that manages the FreeRTOS+CLI input and output.
+ */
+extern void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority );
+
+/*
+ * A high priority task that does nothing other than execute at a pseudo random
+ * time to ensure the other test tasks don't just execute in a repeating
+ * pattern.
+ */
+static void prvPseudoRandomiser( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* 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 ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
+
+/* String for display in the web server. It is set to an error message if the
+check task detects an error. */
+char *pcStatusMessage = "All tasks running without error";
+/*-----------------------------------------------------------*/
+
+void main_full( void )
+{
+ /* Start all the other standard demo/test tasks. They have no particular
+ functionality, but do demonstrate how to use the FreeRTOS API and test the
+ kernel port. */
+ vStartInterruptQueueTasks();
+ vStartDynamicPriorityTasks();
+ vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
+ vCreateBlockTimeTasks();
+ vStartCountingSemaphoreTasks();
+ vStartGenericQueueTasks( tskIDLE_PRIORITY );
+ vStartRecursiveMutexTasks();
+ vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
+ vStartMathTasks( mainFLOP_TASK_PRIORITY );
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
+ vStartQueueOverwriteTask( mainQUEUE_OVERWRITE_PRIORITY );
+ vStartEventGroupTasks();
+ vStartTaskNotifyTask();
+ vStartInterruptSemaphoreTasks();
+ vStartStaticallyAllocatedTasks();
+ vCreateAbortDelayTasks();
+ vStartMessageBufferTasks( mainMESSAGE_BUFFER_STACK_SIZE );
+ vStartStreamBufferTasks();
+ vStartStreamBufferInterruptDemo();
+ vStartMessageBufferAMPTasks( mainMESSAGE_BUFFER_STACK_SIZE );
+
+ #if( configUSE_QUEUE_SETS == 1 )
+ {
+ vStartQueueSetTasks();
+ }
+ #endif
+
+ /* Create the register check tasks, as described at the top of this file */
+ xTaskCreate( prvRegTestTaskEntry1, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL );
+ xTaskCreate( prvRegTestTaskEntry2, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
+
+ /* Create the task that just adds a little random behaviour. */
+ xTaskCreate( prvPseudoRandomiser, "Rnd", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
+
+ /* Create the task that performs the 'check' functionality, as described at
+ the top of this file. */
+ xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
+
+ /* The set of tasks created by the following function call have to be
+ created last as they keep account of the number of tasks they expect to see
+ running. */
+ vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
+
+ /* Start the scheduler. */
+ vTaskStartScheduler();
+
+ /* 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 either insufficient FreeRTOS heap memory available for the idle
+ and/or timer tasks to be created, or vTaskStartScheduler() was called from
+ User mode. See the memory management section on the FreeRTOS web site for
+ more details on the FreeRTOS heap http://www.freertos.org/a00111.html. The
+ mode from which main() is called is set in the C start up code and must be
+ a privileged mode (not user mode). */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTask( void *pvParameters )
+{
+TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD;
+TickType_t xLastExecutionTime;
+static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
+unsigned long ulErrorFound = pdFALSE;
+extern volatile uint32_t ulNestingCount;
+
+ /* Just to stop compiler warnings. */
+ ( void ) pvParameters;
+
+ /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()
+ works correctly. */
+ xLastExecutionTime = xTaskGetTickCount();
+
+ /* Cycle for ever, delaying then checking all the other tasks are still
+ operating without error. The onboard LED is toggled on each iteration.
+ If an error is detected then the delay period is decreased from
+ mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the
+ effect of increasing the rate at which the onboard LED toggles, and in so
+ doing gives visual feedback of the system status. */
+ for( ;; )
+ {
+ /* Delay until it is time to execute again. */
+ vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod );
+
+ /* Check all the demo tasks (other than the flash tasks) to ensure
+ that they are all still running, and that none have detected an error. */
+ if( xAreIntQueueTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 0UL;
+ }
+
+ if( xAreMathsTaskStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 1UL;
+ }
+
+ if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 2UL;
+ }
+
+ if( xAreBlockingQueuesStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 3UL;
+ }
+
+ if ( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 4UL;
+ }
+
+ if ( xAreGenericQueueTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 5UL;
+ }
+
+ if ( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 6UL;
+ }
+
+ if( xIsCreateTaskStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 7UL;
+ }
+
+ if( xAreSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 8UL;
+ }
+
+ if( xAreTimerDemoTasksStillRunning( ( TickType_t ) mainNO_ERROR_CHECK_TASK_PERIOD ) != pdPASS )
+ {
+ ulErrorFound |= 1UL << 9UL;
+ }
+
+ if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 10UL;
+ }
+
+ if( xIsQueueOverwriteTaskStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 11UL;
+ }
+
+ if( xAreEventGroupTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 12UL;
+ }
+
+ if( xAreTaskNotificationTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 13UL;
+ }
+
+ if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 14UL;
+ }
+
+ if( xAreStaticAllocationTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 15UL;
+ }
+
+ if( xAreAbortDelayTestTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 16UL;
+ }
+
+ if( xAreStreamBufferTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 17UL;
+ }
+
+ if( xAreMessageBufferTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound |= 1UL << 18UL;
+ }
+
+ if( xIsInterruptStreamBufferDemoStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 19UL;
+ }
+
+ if( xAreMessageBufferAMPTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 20UL;
+ }
+
+ #if( configUSE_QUEUE_SETS == 1 )
+ {
+ if( xAreQueueSetTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound |= 1UL << 21UL;
+ }
+ }
+ #endif
+
+ /* Check that the register test 1 task is still running. */
+ if( ulLastRegTest1Value == ulRegTest1LoopCounter )
+ {
+ ulErrorFound |= 1UL << 22UL;
+ }
+ ulLastRegTest1Value = ulRegTest1LoopCounter;
+
+ /* Check that the register test 2 task is still running. */
+ if( ulLastRegTest2Value == ulRegTest2LoopCounter )
+ {
+ ulErrorFound |= 1UL << 23UL;
+ }
+ ulLastRegTest2Value = ulRegTest2LoopCounter;
+
+ /* Toggle the check LED to give an indication of the system status. If
+ the LED toggles every mainNO_ERROR_CHECK_TASK_PERIOD milliseconds then
+ everything is ok. A faster toggle indicates an error. */
+ vParTestToggleLED( mainCHECK_LED );
+
+ if( ulErrorFound != pdFALSE )
+ {
+ /* An error has been detected in one of the tasks - flash the LED
+ at a higher frequency to give visible feedback that something has
+ gone wrong (it might just be that the loop back connector required
+ by the comtest tasks has not been fitted). */
+ xDelayPeriod = mainERROR_CHECK_TASK_PERIOD;
+ pcStatusMessage = "Error found in at least one task (one bit set per detected error)";
+ }
+
+ #if( configUSING_QEMU == 1 )
+ xil_printf( "%u - %s:%xH - %d\n", xTaskGetTickCount(), pcStatusMessage, ulErrorFound, ulNestingCount );
+ #endif
+ }
+}
+/*-----------------------------------------------------------*/
+
+char *pcMainGetTaskStatusMessage( void )
+{
+ return pcStatusMessage;
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry1( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, 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 )
+ {
+ /* The reg test task also tests the floating point registers. Tasks
+ that use the floating point unit must call vPortTaskUsesFPU() before
+ any floating point instructions are executed. */
+ vPortTaskUsesFPU();
+
+ /* Start the part of the test that is written in assembler. */
+ vRegTest1Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check timer will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry2( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, 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 )
+ {
+ /* The reg test task also tests the floating point registers. Tasks
+ that use the floating point unit must call vPortTaskUsesFPU() before
+ any floating point instructions are executed. */
+ vPortTaskUsesFPU();
+
+ /* Start the part of the test that is written in assembler. */
+ vRegTest2Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check timer will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void prvPseudoRandomiser( void *pvParameters )
+{
+const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL, ulMinDelay = ( 35 / portTICK_PERIOD_MS );
+volatile uint32_t ulNextRand = ( uint32_t ) &pvParameters, ulValue;
+
+ /* This task does nothing other than ensure there is a little bit of
+ disruption in the scheduling pattern of the other tasks. Normally this is
+ done by generating interrupts at pseudo random times. */
+ for( ;; )
+ {
+ ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
+ ulValue = ( ulNextRand >> 16UL ) & 0xffUL;
+
+ if( ulValue < ulMinDelay )
+ {
+ ulValue = ulMinDelay;
+ }
+
+ vTaskDelay( ulValue );
+
+ while( ulValue > 0 )
+ {
+ __asm volatile( "NOP" );
+ __asm volatile( "NOP" );
+ __asm volatile( "NOP" );
+ __asm volatile( "NOP" );
+
+ ulValue--;
+ }
+ }
+}
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/reg_test.S b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/reg_test.S
new file mode 100644
index 0000000000..945b0cbe10
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/reg_test.S
@@ -0,0 +1,610 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+ .global vRegTest1Implementation
+ .global vRegTest2Implementation
+ .extern ulRegTest1LoopCounter
+ .extern ulRegTest2LoopCounter
+
+ .text
+ .arm
+
+ /* This function is explained in the comments at the top of main-full.c. */
+.type vRegTest1Implementation, %function
+vRegTest1Implementation:
+
+ /* Fill each general purpose register with a known value. */
+ mov r0, #0xFF
+ mov r1, #0x11
+ mov r2, #0x22
+ mov r3, #0x33
+ mov r4, #0x44
+ mov r5, #0x55
+ mov r6, #0x66
+ mov r7, #0x77
+ mov r8, #0x88
+ mov r9, #0x99
+ mov r10, #0xAA
+ mov r11, #0xBB
+ mov r12, #0xCC
+ mov r14, #0xEE
+
+ /* Fill each FPU register with a known value. */
+ vmov d0, r0, r1
+ vmov d1, r2, r3
+ vmov d2, r4, r5
+ vmov d3, r6, r7
+ vmov d4, r8, r9
+ vmov d5, r10, r11
+ vmov d6, r0, r1
+ vmov d7, r2, r3
+ vmov d8, r4, r5
+ vmov d9, r6, r7
+ vmov d10, r8, r9
+ vmov d11, r10, r11
+ vmov d12, r0, r1
+ vmov d13, r2, r3
+ vmov d14, r4, r5
+ vmov d15, r6, r7
+
+ vmov d16, r0, r1
+ vmov d17, r2, r3
+ vmov d18, r4, r5
+ vmov d19, r6, r7
+ vmov d20, r8, r9
+ vmov d21, r10, r11
+ vmov d22, r0, r1
+ vmov d23, r2, r3
+ vmov d24, r4, r5
+ vmov d25, r6, r7
+ vmov d26, r8, r9
+ vmov d27, r10, r11
+ vmov d28, r0, r1
+ vmov d29, r2, r3
+ vmov d30, r4, r5
+ vmov d31, r6, r7
+
+ /* Loop, checking each iteration that each register still contains the
+ expected value. */
+reg1_loop:
+ /* Yield to increase test coverage */
+ svc 0
+
+ /* Check all the VFP registers still contain the values set above.
+ First save registers that are clobbered by the test. */
+ push { r0-r1 }
+
+ vmov r0, r1, d0
+ cmp r0, #0xFF
+ bne reg1_error_loopf
+ cmp r1, #0x11
+ bne reg1_error_loopf
+ vmov r0, r1, d1
+ cmp r0, #0x22
+ bne reg1_error_loopf
+ cmp r1, #0x33
+ bne reg1_error_loopf
+ vmov r0, r1, d2
+ cmp r0, #0x44
+ bne reg1_error_loopf
+ cmp r1, #0x55
+ bne reg1_error_loopf
+ vmov r0, r1, d3
+ cmp r0, #0x66
+ bne reg1_error_loopf
+ cmp r1, #0x77
+ bne reg1_error_loopf
+ vmov r0, r1, d4
+ cmp r0, #0x88
+ bne reg1_error_loopf
+ cmp r1, #0x99
+ bne reg1_error_loopf
+ vmov r0, r1, d5
+ cmp r0, #0xAA
+ bne reg1_error_loopf
+ cmp r1, #0xBB
+ bne reg1_error_loopf
+ vmov r0, r1, d6
+ cmp r0, #0xFF
+ bne reg1_error_loopf
+ cmp r1, #0x11
+ bne reg1_error_loopf
+ vmov r0, r1, d7
+ cmp r0, #0x22
+ bne reg1_error_loopf
+ cmp r1, #0x33
+ bne reg1_error_loopf
+ vmov r0, r1, d8
+ cmp r0, #0x44
+ bne reg1_error_loopf
+ cmp r1, #0x55
+ bne reg1_error_loopf
+ vmov r0, r1, d9
+ cmp r0, #0x66
+ bne reg1_error_loopf
+ cmp r1, #0x77
+ bne reg1_error_loopf
+ vmov r0, r1, d10
+ cmp r0, #0x88
+ bne reg1_error_loopf
+ cmp r1, #0x99
+ bne reg1_error_loopf
+ vmov r0, r1, d11
+ cmp r0, #0xAA
+ bne reg1_error_loopf
+ cmp r1, #0xBB
+ bne reg1_error_loopf
+ vmov r0, r1, d12
+ cmp r0, #0xFF
+ bne reg1_error_loopf
+ cmp r1, #0x11
+ bne reg1_error_loopf
+ vmov r0, r1, d13
+ cmp r0, #0x22
+ bne reg1_error_loopf
+ cmp r1, #0x33
+ bne reg1_error_loopf
+ vmov r0, r1, d14
+ cmp r0, #0x44
+ bne reg1_error_loopf
+ cmp r1, #0x55
+ bne reg1_error_loopf
+ vmov r0, r1, d15
+ cmp r0, #0x66
+ bne reg1_error_loopf
+ cmp r1, #0x77
+ bne reg1_error_loopf
+
+ vmov r0, r1, d16
+ cmp r0, #0xFF
+ bne reg1_error_loopf
+ cmp r1, #0x11
+ bne reg1_error_loopf
+ vmov r0, r1, d17
+ cmp r0, #0x22
+ bne reg1_error_loopf
+ cmp r1, #0x33
+ bne reg1_error_loopf
+ vmov r0, r1, d18
+ cmp r0, #0x44
+ bne reg1_error_loopf
+ cmp r1, #0x55
+ bne reg1_error_loopf
+ vmov r0, r1, d19
+ cmp r0, #0x66
+ bne reg1_error_loopf
+ cmp r1, #0x77
+ bne reg1_error_loopf
+ vmov r0, r1, d20
+ cmp r0, #0x88
+ bne reg1_error_loopf
+ cmp r1, #0x99
+ bne reg1_error_loopf
+ vmov r0, r1, d21
+ cmp r0, #0xAA
+ bne reg1_error_loopf
+ cmp r1, #0xBB
+ bne reg1_error_loopf
+ vmov r0, r1, d22
+ cmp r0, #0xFF
+ bne reg1_error_loopf
+ cmp r1, #0x11
+ bne reg1_error_loopf
+ vmov r0, r1, d23
+ cmp r0, #0x22
+ bne reg1_error_loopf
+ cmp r1, #0x33
+ bne reg1_error_loopf
+ vmov r0, r1, d24
+ cmp r0, #0x44
+ bne reg1_error_loopf
+ cmp r1, #0x55
+ bne reg1_error_loopf
+ vmov r0, r1, d25
+ cmp r0, #0x66
+ bne reg1_error_loopf
+ cmp r1, #0x77
+ bne reg1_error_loopf
+ vmov r0, r1, d26
+ cmp r0, #0x88
+ bne reg1_error_loopf
+ cmp r1, #0x99
+ bne reg1_error_loopf
+ vmov r0, r1, d27
+ cmp r0, #0xAA
+ bne reg1_error_loopf
+ cmp r1, #0xBB
+ bne reg1_error_loopf
+ vmov r0, r1, d28
+ cmp r0, #0xFF
+ bne reg1_error_loopf
+ cmp r1, #0x11
+ bne reg1_error_loopf
+ vmov r0, r1, d29
+ cmp r0, #0x22
+ bne reg1_error_loopf
+ cmp r1, #0x33
+ bne reg1_error_loopf
+ vmov r0, r1, d30
+ cmp r0, #0x44
+ bne reg1_error_loopf
+ cmp r1, #0x55
+ bne reg1_error_loopf
+ vmov r0, r1, d31
+ cmp r0, #0x66
+ bne reg1_error_loopf
+ cmp r1, #0x77
+ bne reg1_error_loopf
+
+ /* Restore the registers that were clobbered by the test. */
+ pop {r0-r1}
+
+ /* VFP register test passed. Jump to the core register test. */
+ b reg1_loopf_pass
+
+reg1_error_loopf:
+ /* If this line is hit then a VFP register value was found to be
+ incorrect. */
+ b reg1_error_loopf
+
+reg1_loopf_pass:
+
+ /* Test each general purpose register to check that it still contains the
+ expected known value, jumping to reg1_error_loop if any register contains
+ an unexpected value. */
+ cmp r0, #0xFF
+ bne reg1_error_loop
+ cmp r1, #0x11
+ bne reg1_error_loop
+ cmp r2, #0x22
+ bne reg1_error_loop
+ cmp r3, #0x33
+ bne reg1_error_loop
+ cmp r4, #0x44
+ bne reg1_error_loop
+ cmp r5, #0x55
+ bne reg1_error_loop
+ cmp r6, #0x66
+ bne reg1_error_loop
+ cmp r7, #0x77
+ bne reg1_error_loop
+ cmp r8, #0x88
+ bne reg1_error_loop
+ cmp r9, #0x99
+ bne reg1_error_loop
+ cmp r10, #0xAA
+ bne reg1_error_loop
+ cmp r11, #0xBB
+ bne reg1_error_loop
+ cmp r12, #0xCC
+ bne reg1_error_loop
+ cmp r14, #0xEE
+ bne reg1_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ push { r0-r1 }
+ ldr r0, =ulRegTest1LoopCounter
+ ldr r1, [r0]
+ adds r1, r1, #1
+ str r1, [r0]
+ pop { r0-r1 }
+
+ /* Start again. */
+ b reg1_loop
+
+reg1_error_loop:
+ /* If this line is hit then there was an error in a core register value.
+ The loop ensures the loop counter stops incrementing. */
+ b reg1_error_loop
+ nop
+
+/*-----------------------------------------------------------*/
+
+.type vRegTest2Implementation, %function
+vRegTest2Implementation:
+
+ /* Put a known value in each register. */
+ mov r0, #0xFF000000
+ mov r1, #0x11000000
+ mov r2, #0x22000000
+ mov r3, #0x33000000
+ mov r4, #0x44000000
+ mov r5, #0x55000000
+ mov r6, #0x66000000
+ mov r7, #0x77000000
+ mov r8, #0x88000000
+ mov r9, #0x99000000
+ mov r10, #0xAA000000
+ mov r11, #0xBB000000
+ mov r12, #0xCC000000
+ mov r14, #0xEE000000
+
+ /* Likewise the floating point registers */
+ vmov d0, r0, r1
+ vmov d1, r2, r3
+ vmov d2, r4, r5
+ vmov d3, r6, r7
+ vmov d4, r8, r9
+ vmov d5, r10, r11
+ vmov d6, r0, r1
+ vmov d7, r2, r3
+ vmov d8, r4, r5
+ vmov d9, r6, r7
+ vmov d10, r8, r9
+ vmov d11, r10, r11
+ vmov d12, r0, r1
+ vmov d13, r2, r3
+ vmov d14, r4, r5
+ vmov d15, r6, r7
+
+ vmov d16, r0, r1
+ vmov d17, r2, r3
+ vmov d18, r4, r5
+ vmov d19, r6, r7
+ vmov d20, r8, r9
+ vmov d21, r10, r11
+ vmov d22, r0, r1
+ vmov d23, r2, r3
+ vmov d24, r4, r5
+ vmov d25, r6, r7
+ vmov d26, r8, r9
+ vmov d27, r10, r11
+ vmov d28, r0, r1
+ vmov d29, r2, r3
+ vmov d30, r4, r5
+ vmov d31, r6, r7
+
+ /* Loop, checking each iteration that each register still contains the
+ expected value. */
+reg2_loop:
+ /* Check all the VFP registers still contain the values set above.
+ First save registers that are clobbered by the test. */
+ push { r0-r1 }
+
+ vmov r0, r1, d0
+ cmp r0, #0xFF000000
+ bne reg2_error_loopf
+ cmp r1, #0x11000000
+ bne reg2_error_loopf
+ vmov r0, r1, d1
+ cmp r0, #0x22000000
+ bne reg2_error_loopf
+ cmp r1, #0x33000000
+ bne reg2_error_loopf
+ vmov r0, r1, d2
+ cmp r0, #0x44000000
+ bne reg2_error_loopf
+ cmp r1, #0x55000000
+ bne reg2_error_loopf
+ vmov r0, r1, d3
+ cmp r0, #0x66000000
+ bne reg2_error_loopf
+ cmp r1, #0x77000000
+ bne reg2_error_loopf
+ vmov r0, r1, d4
+ cmp r0, #0x88000000
+ bne reg2_error_loopf
+ cmp r1, #0x99000000
+ bne reg2_error_loopf
+ vmov r0, r1, d5
+ cmp r0, #0xAA000000
+ bne reg2_error_loopf
+ cmp r1, #0xBB000000
+ bne reg2_error_loopf
+ vmov r0, r1, d6
+ cmp r0, #0xFF000000
+ bne reg2_error_loopf
+ cmp r1, #0x11000000
+ bne reg2_error_loopf
+ vmov r0, r1, d7
+ cmp r0, #0x22000000
+ bne reg2_error_loopf
+ cmp r1, #0x33000000
+ bne reg2_error_loopf
+ vmov r0, r1, d8
+ cmp r0, #0x44000000
+ bne reg2_error_loopf
+ cmp r1, #0x55000000
+ bne reg2_error_loopf
+ vmov r0, r1, d9
+ cmp r0, #0x66000000
+ bne reg2_error_loopf
+ cmp r1, #0x77000000
+ bne reg2_error_loopf
+ vmov r0, r1, d10
+ cmp r0, #0x88000000
+ bne reg2_error_loopf
+ cmp r1, #0x99000000
+ bne reg2_error_loopf
+ vmov r0, r1, d11
+ cmp r0, #0xAA000000
+ bne reg2_error_loopf
+ cmp r1, #0xBB000000
+ bne reg2_error_loopf
+ vmov r0, r1, d12
+ cmp r0, #0xFF000000
+ bne reg2_error_loopf
+ cmp r1, #0x11000000
+ bne reg2_error_loopf
+ vmov r0, r1, d13
+ cmp r0, #0x22000000
+ bne reg2_error_loopf
+ cmp r1, #0x33000000
+ bne reg2_error_loopf
+ vmov r0, r1, d14
+ cmp r0, #0x44000000
+ bne reg2_error_loopf
+ cmp r1, #0x55000000
+ bne reg2_error_loopf
+ vmov r0, r1, d15
+ cmp r0, #0x66000000
+ bne reg2_error_loopf
+ cmp r1, #0x77000000
+ bne reg2_error_loopf
+
+ vmov r0, r1, d16
+ cmp r0, #0xFF000000
+ bne reg2_error_loopf
+ cmp r1, #0x11000000
+ bne reg2_error_loopf
+ vmov r0, r1, d17
+ cmp r0, #0x22000000
+ bne reg2_error_loopf
+ cmp r1, #0x33000000
+ bne reg2_error_loopf
+ vmov r0, r1, d18
+ cmp r0, #0x44000000
+ bne reg2_error_loopf
+ cmp r1, #0x55000000
+ bne reg2_error_loopf
+ vmov r0, r1, d19
+ cmp r0, #0x66000000
+ bne reg2_error_loopf
+ cmp r1, #0x77000000
+ bne reg2_error_loopf
+ vmov r0, r1, d20
+ cmp r0, #0x88000000
+ bne reg2_error_loopf
+ cmp r1, #0x99000000
+ bne reg2_error_loopf
+ vmov r0, r1, d21
+ cmp r0, #0xAA000000
+ bne reg2_error_loopf
+ cmp r1, #0xBB000000
+ bne reg2_error_loopf
+ vmov r0, r1, d22
+ cmp r0, #0xFF000000
+ bne reg2_error_loopf
+ cmp r1, #0x11000000
+ bne reg2_error_loopf
+ vmov r0, r1, d23
+ cmp r0, #0x22000000
+ bne reg2_error_loopf
+ cmp r1, #0x33000000
+ bne reg2_error_loopf
+ vmov r0, r1, d24
+ cmp r0, #0x44000000
+ bne reg2_error_loopf
+ cmp r1, #0x55000000
+ bne reg2_error_loopf
+ vmov r0, r1, d25
+ cmp r0, #0x66000000
+ bne reg2_error_loopf
+ cmp r1, #0x77000000
+ bne reg2_error_loopf
+ vmov r0, r1, d26
+ cmp r0, #0x88000000
+ bne reg2_error_loopf
+ cmp r1, #0x99000000
+ bne reg2_error_loopf
+ vmov r0, r1, d27
+ cmp r0, #0xAA000000
+ bne reg2_error_loopf
+ cmp r1, #0xBB000000
+ bne reg2_error_loopf
+ vmov r0, r1, d28
+ cmp r0, #0xFF000000
+ bne reg2_error_loopf
+ cmp r1, #0x11000000
+ bne reg2_error_loopf
+ vmov r0, r1, d29
+ cmp r0, #0x22000000
+ bne reg2_error_loopf
+ cmp r1, #0x33000000
+ bne reg2_error_loopf
+ vmov r0, r1, d30
+ cmp r0, #0x44000000
+ bne reg2_error_loopf
+ cmp r1, #0x55000000
+ bne reg2_error_loopf
+ vmov r0, r1, d31
+ cmp r0, #0x66000000
+ bne reg2_error_loopf
+ cmp r1, #0x77000000
+ bne reg2_error_loopf
+
+ /* Restore the registers that were clobbered by the test. */
+ pop {r0-r1}
+
+ /* VFP register test passed. Jump to the core register test. */
+ b reg2_loopf_pass
+
+reg2_error_loopf:
+ /* If this line is hit then a VFP register value was found to be
+ incorrect. */
+ b reg2_error_loopf
+
+reg2_loopf_pass:
+
+ cmp r0, #0xFF000000
+ bne reg2_error_loop
+ cmp r1, #0x11000000
+ bne reg2_error_loop
+ cmp r2, #0x22000000
+ bne reg2_error_loop
+ cmp r3, #0x33000000
+ bne reg2_error_loop
+ cmp r4, #0x44000000
+ bne reg2_error_loop
+ cmp r5, #0x55000000
+ bne reg2_error_loop
+ cmp r6, #0x66000000
+ bne reg2_error_loop
+ cmp r7, #0x77000000
+ bne reg2_error_loop
+ cmp r8, #0x88000000
+ bne reg2_error_loop
+ cmp r9, #0x99000000
+ bne reg2_error_loop
+ cmp r10, #0xAA000000
+ bne reg2_error_loop
+ cmp r11, #0xBB000000
+ bne reg2_error_loop
+ cmp r12, #0xCC000000
+ bne reg2_error_loop
+ cmp r14, #0xEE000000
+ bne reg2_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ push { r0-r1 }
+ ldr r0, =ulRegTest2LoopCounter
+ ldr r1, [r0]
+ adds r1, r1, #1
+ str r1, [r0]
+ pop { r0-r1 }
+
+ /* Start again. */
+ b reg2_loop
+
+reg2_error_loop:
+ /* If this line is hit then there was an error in a core register value.
+ The loop ensures the loop counter stops incrementing. */
+ b reg2_error_loop
+ nop
+
+
+ .end
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/serial.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/serial.c
new file mode 100644
index 0000000000..abf42488c5
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/full_demo/serial.c
@@ -0,0 +1,282 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*
+ BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER.
+
+ Note1: This driver is used specifically to provide an interface to the
+ FreeRTOS+CLI command interpreter. It is *not* intended to be a generic
+ serial port driver. Nor is it intended to be used as an example of an
+ efficient implementation. In particular, a queue is used to buffer
+ received characters, which is fine in this case as key presses arrive
+ slowly, but a DMA and/or RAM buffer should be used in place of the queue in
+ applications that expect higher throughput.
+
+ Note2: This driver does not attempt to handle UART errors.
+*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo application includes. */
+#include "serial.h"
+
+/* Xilinx includes. */
+#include "xuartps.h"
+#include "xscugic.h"
+#include "xil_exception.h"
+
+/* The UART interrupts of interest when receiving. */
+#define serRECEIVE_INTERRUPT_MASK ( XUARTPS_IXR_RXOVR | XUARTPS_IXR_RXFULL | XUARTPS_IXR_TOUT )
+
+/* The UART interrupts of interest when transmitting. */
+#define serTRANSMIT_IINTERRUPT_MASK ( XUARTPS_IXR_TXEMPTY )
+
+/*-----------------------------------------------------------*/
+
+/* The UART being used. */
+static XUartPs xUARTInstance;
+
+/* The interrupt controller, which is configred by the hardware setup routines
+defined in main(). */
+extern XScuGic xInterruptController;
+
+/* The queue into which received key presses are placed. NOTE THE COMMENTS AT
+THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPOSE. */
+static QueueHandle_t xRxQueue = NULL;
+
+/* The semaphore used to indicate the end of a transmission. */
+static SemaphoreHandle_t xTxCompleteSemaphore = NULL;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The UART interrupt handler is defined in this file to provide more control,
+ * but still uses parts of the Xilinx provided driver.
+ */
+void prvUART_Handler( void *pvNotUsed );
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See the serial2.h header file.
+ */
+xComPortHandle xSerialPortInitMinimal( uint32_t ulWantedBaud, UBaseType_t uxQueueLength )
+{
+BaseType_t xStatus;
+XUartPs_Config *pxConfig;
+
+ /* Create the queue used to hold received characters. NOTE THE COMMENTS AT
+ THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPOSE. */
+ xRxQueue = xQueueCreate( uxQueueLength, sizeof( char ) );
+ configASSERT( xRxQueue );
+
+ /* Create the semaphore used to signal the end of a transmission, then take
+ the semaphore so it is in the correct state the first time
+ xSerialSendString() is called. A block time of zero is used when taking
+ the semaphore as it is guaranteed to be available (it was just created). */
+ xTxCompleteSemaphore = xSemaphoreCreateBinary();
+ configASSERT( xTxCompleteSemaphore );
+ xSemaphoreTake( xTxCompleteSemaphore, 0 );
+
+ /* Look up the UART configuration then initialise the dirver. */
+ pxConfig = XUartPs_LookupConfig( XPAR_XUARTPS_0_DEVICE_ID );
+
+ /* Initialise the driver. */
+ xStatus = XUartPs_CfgInitialize( &xUARTInstance, pxConfig, XPAR_PS7_UART_1_BASEADDR );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* Misc. parameter configuration. */
+ XUartPs_SetBaudRate( &xUARTInstance, ulWantedBaud );
+ XUartPs_SetOperMode( &xUARTInstance, XUARTPS_OPER_MODE_NORMAL );
+
+ /* Install the interrupt service routine that is defined within this
+ file. */
+ xStatus = XScuGic_Connect( &xInterruptController, XPAR_XUARTPS_1_INTR, (Xil_ExceptionHandler) prvUART_Handler, (void *) &xUARTInstance );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* Ensure interrupts start clear. */
+ XUartPs_WriteReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_ISR_OFFSET, XUARTPS_IXR_MASK );
+
+ /* Enable the UART interrupt within the GIC. */
+ XScuGic_Enable( &xInterruptController, XPAR_XUARTPS_1_INTR );
+
+ /* Enable the interrupts of interest in the UART. */
+ XUartPs_SetInterruptMask( &xUARTInstance, XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT | XUARTPS_IXR_TXEMPTY );
+
+ /* Set the receive timeout. */
+ XUartPs_SetRecvTimeout( &xUARTInstance, 8 );
+
+ return ( xComPortHandle ) 0;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )
+{
+BaseType_t xReturn;
+
+ /* Only a single port is supported. */
+ ( void ) pxPort;
+
+ /* Obtain a received character from the queue - entering the Blocked state
+ (so not consuming any processing time) to wait for a character if one is not
+ already available. */
+ xReturn = xQueueReceive( xRxQueue, pcRxedChar, xBlockTime );
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )
+{
+const TickType_t xMaxWait = 200UL / portTICK_PERIOD_MS;
+
+ /* Only a single port is supported. */
+ ( void ) pxPort;
+
+ /* Start the transmission. The interrupt service routine will complete the
+ transmission if necessary. */
+ XUartPs_Send( &xUARTInstance, ( void * ) pcString, usStringLength );
+
+ /* Wait until the string has been transmitted before exiting this function,
+ otherwise there is a risk the calling function will overwrite the string
+ pointed to by the pcString parameter while it is still being transmitted.
+ The calling task will wait in the Blocked state (so not consuming any
+ processing time) until the semaphore is available. */
+ xSemaphoreTake( xTxCompleteSemaphore, xMaxWait );
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
+{
+ /* Only a single port is supported. */
+ ( void ) pxPort;
+
+ /* Send the character. */
+ XUartPs_Send( &xUARTInstance, ( void * ) &cOutChar, sizeof( cOutChar ) );
+
+ /* Wait for the transmission to be complete so the semaphore is left in the
+ correct state for the next time vSerialPutString() is called. */
+ xSemaphoreTake( xTxCompleteSemaphore, xBlockTime );
+
+ return pdPASS;
+}
+/*-----------------------------------------------------------*/
+
+void vSerialClose(xComPortHandle xPort)
+{
+ /* Not supported as not required by the demo application. */
+ ( void ) xPort;
+}
+/*-----------------------------------------------------------*/
+
+void prvUART_Handler( void *pvNotUsed )
+{
+extern unsigned int XUartPs_SendBuffer( XUartPs *InstancePtr );
+uint32_t ulActiveInterrupts, ulChannelStatusRegister;
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+char cChar;
+
+ configASSERT( pvNotUsed == &xUARTInstance );
+
+ /* Remove compile warnings if configASSERT() is not defined. */
+ ( void ) pvNotUsed;
+
+ /* Read the interrupt ID register to see which interrupt is active. */
+ ulActiveInterrupts = XUartPs_ReadReg(XPAR_PS7_UART_1_BASEADDR, XUARTPS_IMR_OFFSET);
+ ulActiveInterrupts &= XUartPs_ReadReg(XPAR_PS7_UART_1_BASEADDR, XUARTPS_ISR_OFFSET);
+
+ /* Are any receive events of interest active? */
+ if( ( ulActiveInterrupts & serRECEIVE_INTERRUPT_MASK ) != 0 )
+ {
+ /* Read the Channel Status Register to determine if there is any data in
+ the RX FIFO. */
+ ulChannelStatusRegister = XUartPs_ReadReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_SR_OFFSET );
+
+ /* Move data from the Rx FIFO to the Rx queue. NOTE THE COMMENTS AT THE
+ TOP OF THIS FILE ABOUT USING QUEUES FOR THIS PURPOSE. */
+ while( ( ulChannelStatusRegister & XUARTPS_SR_RXEMPTY ) == 0 )
+ {
+ cChar = XUartPs_ReadReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_FIFO_OFFSET );
+
+ /* If writing to the queue unblocks a task, and the unblocked task
+ has a priority above the currently running task (the task that this
+ interrupt interrupted), then xHigherPriorityTaskWoken will be set
+ to pdTRUE inside the xQueueSendFromISR() function.
+ xHigherPriorityTaskWoken is then passed to portYIELD_FROM_ISR() at
+ the end of this interrupt handler to request a context switch so the
+ interrupt returns directly to the (higher priority) unblocked
+ task. */
+ xQueueSendFromISR( xRxQueue, &cChar, &xHigherPriorityTaskWoken );
+ ulChannelStatusRegister = XUartPs_ReadReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_SR_OFFSET );
+ }
+ }
+
+ /* Are any transmit events of interest active? */
+ if( ( ulActiveInterrupts & serTRANSMIT_IINTERRUPT_MASK ) != 0 )
+ {
+ if( xUARTInstance.SendBuffer.RemainingBytes == 0 )
+ {
+ /* Give back the semaphore to indicate that the transmission is
+ complete. If giving the semaphore unblocks a task, and the
+ unblocked task has a priority above the currently running task (the
+ task that this interrupt interrupted), then xHigherPriorityTaskWoken
+ will be set to pdTRUE inside the xSemaphoreGiveFromISR() function.
+ xHigherPriorityTaskWoken is then passed to portYIELD_FROM_ISR() at
+ the end of this interrupt handler to request a context switch so the
+ interrupt returns directly to the (higher priority) unblocked
+ task. */
+ xSemaphoreGiveFromISR( xTxCompleteSemaphore, &xHigherPriorityTaskWoken );
+
+ /* No more data to transmit. */
+ XUartPs_WriteReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_IDR_OFFSET, XUARTPS_IXR_TXEMPTY );
+ }
+ else
+ {
+ /* More data to send. */
+ XUartPs_SendBuffer( &xUARTInstance );
+ }
+ }
+
+ /* portYIELD_FROM_ISR() will request a context switch if executing this
+ interrupt handler caused a task to leave the blocked state, and the task
+ that left the blocked state has a higher priority than the currently running
+ task (the task this interrupt interrupted). See the comment above the calls
+ to xSemaphoreGiveFromISR() and xQueueSendFromISR() within this function. */
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+
+ /* Clear the interrupt status. */
+ XUartPs_WriteReg( XPAR_PS7_UART_1_BASEADDR, XUARTPS_ISR_OFFSET, ulActiveInterrupts );
+}
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/lscript.ld b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/lscript.ld
new file mode 100644
index 0000000000..9d05fc61f5
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/lscript.ld
@@ -0,0 +1,293 @@
+/*******************************************************************/
+/* */
+/* This file is automatically generated by linker script generator.*/
+/* */
+/* Version: 2018.3 */
+/* */
+/* Copyright (c) 2010-2019 Xilinx, Inc. All rights reserved. */
+/* */
+/* Description : Cortex-A9 Linker Script */
+/* */
+/*******************************************************************/
+
+_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
+_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;
+
+_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
+_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
+_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
+_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
+_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
+
+/* Define Memories in the system */
+
+MEMORY
+{
+ ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x3FF00000
+ ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000
+ ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000
+ ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00
+}
+
+/* Specify the default entry point to the program */
+
+ENTRY(_vector_table)
+
+/* Define the sections, and where they are mapped in memory */
+
+SECTIONS
+{
+.text : {
+ *(.freertos_vectors)
+ KEEP (*(.vectors))
+ *(.boot)
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ *(.plt)
+ *(.gnu_warning)
+ *(.gcc_execpt_table)
+ *(.glue_7)
+ *(.glue_7t)
+ *(.vfp11_veneer)
+ *(.ARM.extab)
+ *(.gnu.linkonce.armextab.*)
+} > ps7_ddr_0
+
+.init : {
+ KEEP (*(.init))
+} > ps7_ddr_0
+
+.fini : {
+ KEEP (*(.fini))
+} > ps7_ddr_0
+
+.rodata : {
+ __rodata_start = .;
+ *(.rodata)
+ *(.rodata.*)
+ *(.gnu.linkonce.r.*)
+ __rodata_end = .;
+} > ps7_ddr_0
+
+.rodata1 : {
+ __rodata1_start = .;
+ *(.rodata1)
+ *(.rodata1.*)
+ __rodata1_end = .;
+} > ps7_ddr_0
+
+.sdata2 : {
+ __sdata2_start = .;
+ *(.sdata2)
+ *(.sdata2.*)
+ *(.gnu.linkonce.s2.*)
+ __sdata2_end = .;
+} > ps7_ddr_0
+
+.sbss2 : {
+ __sbss2_start = .;
+ *(.sbss2)
+ *(.sbss2.*)
+ *(.gnu.linkonce.sb2.*)
+ __sbss2_end = .;
+} > ps7_ddr_0
+
+.data : {
+ __data_start = .;
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+ *(.jcr)
+ *(.got)
+ *(.got.plt)
+ __data_end = .;
+} > ps7_ddr_0
+
+.data1 : {
+ __data1_start = .;
+ *(.data1)
+ *(.data1.*)
+ __data1_end = .;
+} > ps7_ddr_0
+
+.got : {
+ *(.got)
+} > ps7_ddr_0
+
+.note.gnu.build-id : {
+ KEEP (*(.note.gnu.build-id))
+} > ps7_ddr_0
+
+.ctors : {
+ __CTOR_LIST__ = .;
+ ___CTORS_LIST___ = .;
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ __CTOR_END__ = .;
+ ___CTORS_END___ = .;
+} > ps7_ddr_0
+
+.dtors : {
+ __DTOR_LIST__ = .;
+ ___DTORS_LIST___ = .;
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ __DTOR_END__ = .;
+ ___DTORS_END___ = .;
+} > ps7_ddr_0
+
+.fixup : {
+ __fixup_start = .;
+ *(.fixup)
+ __fixup_end = .;
+} > ps7_ddr_0
+
+.eh_frame : {
+ *(.eh_frame)
+} > ps7_ddr_0
+
+.eh_framehdr : {
+ __eh_framehdr_start = .;
+ *(.eh_framehdr)
+ __eh_framehdr_end = .;
+} > ps7_ddr_0
+
+.gcc_except_table : {
+ *(.gcc_except_table)
+} > ps7_ddr_0
+
+.mmu_tbl (ALIGN(16384)) : {
+ __mmu_tbl_start = .;
+ *(.mmu_tbl)
+ __mmu_tbl_end = .;
+} > ps7_ddr_0
+
+.ARM.exidx : {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ *(.gnu.linkonce.armexidix.*.*)
+ __exidx_end = .;
+} > ps7_ddr_0
+
+.preinit_array : {
+ __preinit_array_start = .;
+ KEEP (*(SORT(.preinit_array.*)))
+ KEEP (*(.preinit_array))
+ __preinit_array_end = .;
+} > ps7_ddr_0
+
+.init_array : {
+ __init_array_start = .;
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ __init_array_end = .;
+} > ps7_ddr_0
+
+.fini_array : {
+ __fini_array_start = .;
+ KEEP (*(SORT(.fini_array.*)))
+ KEEP (*(.fini_array))
+ __fini_array_end = .;
+} > ps7_ddr_0
+
+.ARM.attributes : {
+ __ARM.attributes_start = .;
+ *(.ARM.attributes)
+ __ARM.attributes_end = .;
+} > ps7_ddr_0
+
+.sdata : {
+ __sdata_start = .;
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s.*)
+ __sdata_end = .;
+} > ps7_ddr_0
+
+.sbss (NOLOAD) : {
+ __sbss_start = .;
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb.*)
+ __sbss_end = .;
+} > ps7_ddr_0
+
+.tdata : {
+ __tdata_start = .;
+ *(.tdata)
+ *(.tdata.*)
+ *(.gnu.linkonce.td.*)
+ __tdata_end = .;
+} > ps7_ddr_0
+
+.tbss : {
+ __tbss_start = .;
+ *(.tbss)
+ *(.tbss.*)
+ *(.gnu.linkonce.tb.*)
+ __tbss_end = .;
+} > ps7_ddr_0
+
+.bss (NOLOAD) : {
+ __bss_start = .;
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ __bss_end = .;
+} > ps7_ddr_0
+
+_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
+
+_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
+
+/* Generate Stack and Heap definitions */
+
+.heap (NOLOAD) : {
+ . = ALIGN(16);
+ _heap = .;
+ HeapBase = .;
+ _heap_start = .;
+ . += _HEAP_SIZE;
+ _heap_end = .;
+ HeapLimit = .;
+} > ps7_ddr_0
+
+.stack (NOLOAD) : {
+ . = ALIGN(16);
+ _stack_end = .;
+ . += _STACK_SIZE;
+ . = ALIGN(16);
+ _stack = .;
+ __stack = _stack;
+ . = ALIGN(16);
+ _irq_stack_end = .;
+ . += _IRQ_STACK_SIZE;
+ . = ALIGN(16);
+ __irq_stack = .;
+ _supervisor_stack_end = .;
+ . += _SUPERVISOR_STACK_SIZE;
+ . = ALIGN(16);
+ __supervisor_stack = .;
+ _abort_stack_end = .;
+ . += _ABORT_STACK_SIZE;
+ . = ALIGN(16);
+ __abort_stack = .;
+ _fiq_stack_end = .;
+ . += _FIQ_STACK_SIZE;
+ . = ALIGN(16);
+ __fiq_stack = .;
+ _undef_stack_end = .;
+ . += _UNDEF_STACK_SIZE;
+ . = ALIGN(16);
+ __undef_stack = .;
+} > ps7_ddr_0
+
+_end = .;
+}
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/main.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/main.c
new file mode 100644
index 0000000000..94044b1e26
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/main.c
@@ -0,0 +1,441 @@
+/*
+ * FreeRTOS V202111.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/******************************************************************************
+ *
+ * See http://www.freertos.org/RTOS-Xilinx-Zynq-QEMU.html for instructions.
+ *
+ * This project provides two demo applications. A simple blinky style
+ * project and a more comprehensive test and demo application.
+ * The mainCREATE_SIMPLY_BLINKY_DEMO_ONLY setting (defined in this file) 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 file implements the code that is not demo specific, including the
+ * hardware setup and FreeRTOS hook functions.
+ *
+ * !!! IMPORTANT NOTE !!!
+ * The GCC libraries that ship with the Xilinx SDK make use of the floating
+ * point registers. To avoid this causing corruption it is necessary to avoid
+ * their use unless a task has been given a floating point context. See
+ * http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
+ * for information on how to give a task a floating point context, and how to
+ * handle floating point operations in interrupts. As this demo does not give
+ * all tasks a floating point context main.c contains very basic C
+ * implementations of the standard C library functions memset(), memcpy() and
+ * memcmp(), which are are used by FreeRTOS itself. Defining these functions in
+ * the project prevents the linker pulling them in from the library. Any other
+ * standard C library functions that are used by the application must likewise
+ * be defined in C.
+ *
+ * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON
+ * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO
+ * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!
+ *
+ * Command to run in QEMU and wait for the debugger to attach:
+ * qemu-system-arm -M xilinx-zynq-a9 -smp 1 -nographic -kernel [path_to]/RTOSDemo.elf -nographic -serial stdio -semihosting -semihosting-config enable=on,target=native -s -S
+ *
+ * Omit the -s -S to run without waiting for the debugger.
+ *
+ */
+
+/* Standard includes. */
+#include
+#include
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Standard demo includes. */
+#include "partest.h"
+#include "TimerDemo.h"
+#include "QueueOverwrite.h"
+#include "EventGroupsDemo.h"
+#include "TaskNotify.h"
+#include "IntSemTest.h"
+#include "StreamBufferInterrupt.h"
+#include "StreamBufferDemo.h"
+#include "QueueSet.h"
+
+/* Xilinx includes. */
+#include "platform.h"
+#include "xparameters.h"
+#include "xscutimer.h"
+#include "xscugic.h"
+#include "xil_exception.h"
+#include "xuartps_hw.h"
+
+/* mainCREATE_SIMPLY_BLINKY_DEMO_ONLY is used to select between three demo
+ * applications, as described at the top of this file.
+ *
+ * When mainCREATE_SIMPLY_BLINKY_DEMO_ONLY is set to 1 the simple blinky example
+ * will be built.
+ *
+ * When mainCREATE_SIMPLY_BLINKY_DEMO_ONLY is set to 0 the comprehensive test
+ * and demo application will be built.
+ */
+#define mainCREATE_SIMPLY_BLINKY_DEMO_ONLY 1
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Configure the hardware as necessary to run this demo.
+ */
+static void prvSetupHardware( void );
+
+/*
+ * See the comments at the top of this file and above the
+ * mainCREATE_SIMPLY_BLINKY_DEMO_ONLY definition.
+ */
+#if ( mainCREATE_SIMPLY_BLINKY_DEMO_ONLY == 1 )
+ extern void main_blinky( void );
+#else
+ extern void main_full( void );
+#endif
+
+/*
+ * The Xilinx projects use a BSP that does not allow the start up code to be
+ * altered easily. Therefore the vector table used by FreeRTOS is defined in
+ * FreeRTOS_asm_vectors.S, which is part of this project. Switch to use the
+ * FreeRTOS vector table.
+ */
+extern void vPortInstallFreeRTOSVectorTable( void );
+
+/* Prototypes for the standard FreeRTOS callback/hook functions implemented
+within this file. */
+void vApplicationMallocFailedHook( void );
+void vApplicationIdleHook( void );
+
+/*-----------------------------------------------------------*/
+
+/* The interrupt controller is initialised in this file, and made available to
+other modules. */
+extern XScuGic xInterruptController;
+
+/*-----------------------------------------------------------*/
+
+int main( void )
+{
+ /* See http://www.freertos.org/RTOS-Xilinx-Zynq-QEMU.html for instructions. */
+
+ /* Configure the hardware ready to run the demo. */
+ prvSetupHardware();
+
+ /* The mainCREATE_SIMPLY_BLINKY_DEMO_ONLY setting is described at the top of this
+ file. */
+ #if( mainCREATE_SIMPLY_BLINKY_DEMO_ONLY == 1 )
+ {
+ main_blinky();
+ }
+ #else
+ {
+ main_full();
+ }
+ #endif
+
+ /* Don't expect to reach here as the scheduler should now be running the
+ individual tasks. If the code does reach here then it is likely there was
+ not enough heap space to allocate a stack to either the idle or timer task.
+ However as configSUPPORT_STATIC_ALLOCATION is set to 1 those stacks are
+ statically allocated so that should never happen.
+ See https://freertos.org/a00111.html */
+ return 0;
+}
+/*-----------------------------------------------------------*/
+
+static void prvSetupHardware( void )
+{
+BaseType_t xStatus;
+XScuGic_Config *pxGICConfig;
+
+ /* Ensure no interrupts execute while the scheduler is in an inconsistent
+ state. Interrupts are automatically enabled when the scheduler is
+ started. */
+ portDISABLE_INTERRUPTS();
+
+ /* Obtain the configuration of the GIC. */
+ pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
+
+ /* Sanity check the FreeRTOSConfig.h settings are correct for the
+ hardware. */
+ configASSERT( pxGICConfig );
+ configASSERT( pxGICConfig->CpuBaseAddress == ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) );
+ configASSERT( pxGICConfig->DistBaseAddress == configINTERRUPT_CONTROLLER_BASE_ADDRESS );
+
+ /* Install a default handler for each GIC interrupt. */
+ xStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
+ configASSERT( xStatus == XST_SUCCESS );
+ ( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
+
+ /* Initialise the LED port in case execution is on the real hardware rather
+ than in QEMU. */
+ vParTestInitialise();
+
+ /* The Xilinx projects use a BSP that does not allow the start up code to be
+ altered easily. Therefore the vector table used by FreeRTOS is defined in
+ FreeRTOS_asm_vectors.S, which is part of this project. Switch to use the
+ FreeRTOS vector table. */
+ vPortInstallFreeRTOSVectorTable();
+
+ /* Initialise UART for use with QEMU. */
+ XUartPs_ResetHw( 0xE0000000 );
+ XUartPs_WriteReg(0xE0000000, XUARTPS_CR_OFFSET, ((u32)XUARTPS_CR_RX_DIS | (u32)XUARTPS_CR_TX_EN | (u32)XUARTPS_CR_STOPBRK));
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationMallocFailedHook( void )
+{
+ /* Called if a call to pvPortMalloc() fails because there is insufficient
+ free memory available in the FreeRTOS heap. pvPortMalloc() is called
+ internally by FreeRTOS API functions that create tasks, queues, software
+ timers, and semaphores. The size of the FreeRTOS heap is set by the
+ configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
+ taskDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
+{
+ ( void ) 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. */
+ taskDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationIdleHook( void )
+{
+volatile size_t xFreeHeapSpace, xMinimumEverFreeHeapSpace;
+
+ /* This is just a trivial example of an idle hook. It is called on each
+ cycle of the idle task. It must *NOT* attempt to block. In this case the
+ idle task just queries the amount of FreeRTOS heap that remains. See the
+ memory management section on the http://www.FreeRTOS.org web site for memory
+ management options. If there is a lot of heap memory free then the
+ configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
+ RAM. */
+ xFreeHeapSpace = xPortGetFreeHeapSize();
+ xMinimumEverFreeHeapSpace = xPortGetMinimumEverFreeHeapSize();
+
+ /* Remove compiler warning about xFreeHeapSpace being set but never used. */
+ ( void ) xFreeHeapSpace;
+ ( void ) xMinimumEverFreeHeapSpace;
+}
+/*-----------------------------------------------------------*/
+
+void vAssertCalled( const char * pcFile, unsigned long ulLine )
+{
+volatile unsigned long ul = 0;
+
+ ( void ) pcFile;
+ ( void ) ulLine;
+
+ xil_printf( "ASSERT: %s:%d\n", pcFile, ( int ) ulLine );
+
+ taskENTER_CRITICAL();
+ {
+ /* Set ul to a non-zero value using the debugger to step out of this
+ function. */
+ while( ul == 0 )
+ {
+ portNOP();
+ }
+ }
+ taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationTickHook( void )
+{
+ #if( mainCREATE_SIMPLY_BLINKY_DEMO_ONLY == 0 )
+ {
+ /* The full demo includes a software timer demo/test that requires
+ prodding periodically from the tick interrupt. */
+ vTimerPeriodicISRTests();
+
+ /* Call the periodic queue overwrite from ISR demo. */
+ vQueueOverwritePeriodicISRDemo();
+
+ /* Call the periodic event group from ISR demo. */
+ vPeriodicEventGroupsProcessing();
+
+ /* Use task notifications from an interrupt. */
+ xNotifyTaskFromISR();
+
+ /* Use mutexes from interrupts. */
+ vInterruptSemaphorePeriodicTest();
+
+ /* Writes to stream buffer byte by byte to test the stream buffer trigger
+ level functionality. */
+ vPeriodicStreamBufferProcessing();
+
+ /* 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();
+
+ #if( configUSE_QUEUE_SETS == 1 )
+ {
+ vQueueSetAccessQueueSetFromISR();
+ }
+ #endif
+
+ /* Test flop alignment in interrupts - calling printf from an interrupt
+ is BAD! */
+ #if( configASSERT_DEFINED == 1 )
+ {
+ char cBuf[ 20 ];
+ UBaseType_t uxSavedInterruptStatus;
+
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+ {
+ sprintf( cBuf, "%1.3f", 1.234 );
+ }
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
+
+ configASSERT( strcmp( cBuf, "1.234" ) == 0 );
+ }
+ #endif /* configASSERT_DEFINED */
+ }
+ #endif
+}
+/*-----------------------------------------------------------*/
+
+void *memcpy( void *pvDest, const void *pvSource, size_t xBytes )
+{
+/* The compiler used during development seems to err unless these volatiles are
+included at -O3 optimisation. */
+volatile unsigned char *pcDest = ( volatile unsigned char * ) pvDest, *pcSource = ( volatile unsigned char * ) pvSource;
+size_t x;
+
+ /* Extremely crude standard library implementations in lieu of having a C
+ library. */
+ if( pvDest != pvSource )
+ {
+ for( x = 0; x < xBytes; x++ )
+ {
+ pcDest[ x ] = pcSource[ x ];
+ }
+ }
+
+ return pvDest;
+}
+/*-----------------------------------------------------------*/
+
+void *memset( void *pvDest, int iValue, size_t xBytes )
+{
+/* The compiler used during development seems to err unless these volatiles are
+included at -O3 optimisation. */
+volatile unsigned char * volatile pcDest = ( volatile unsigned char * volatile ) pvDest;
+volatile size_t x;
+
+ /* Extremely crude standard library implementations in lieu of having a C
+ library. */
+ for( x = 0; x < xBytes; x++ )
+ {
+ pcDest[ x ] = ( unsigned char ) iValue;
+ }
+
+ return pvDest;
+}
+/*-----------------------------------------------------------*/
+
+int memcmp( const void *pvMem1, const void *pvMem2, size_t xBytes )
+{
+const volatile unsigned char *pucMem1 = pvMem1, *pucMem2 = pvMem2;
+volatile size_t x;
+
+ /* Extremely crude standard library implementations in lieu of having a C
+ library. */
+ for( x = 0; x < xBytes; x++ )
+ {
+ if( pucMem1[ x ] != pucMem2[ x ] )
+ {
+ break;
+ }
+ }
+
+ return xBytes - x;
+}
+/*-----------------------------------------------------------*/
+
+/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
+implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
+used by the Idle task. */
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
+{
+/* If the buffers to be provided to the Idle task are declared inside this
+function then they must be declared static - otherwise they will be allocated on
+the stack and so not exists after this function exits. */
+static StaticTask_t xIdleTaskTCB;
+static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
+
+ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
+ state will be stored. */
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+
+ /* Pass out the array that will be used as the Idle task's stack. */
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
+/*-----------------------------------------------------------*/
+
+/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
+application must provide an implementation of vApplicationGetTimerTaskMemory()
+to provide the memory that is used by the Timer service task. */
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
+{
+/* If the buffers to be provided to the Timer task are declared inside this
+function then they must be declared static - otherwise they will be allocated on
+the stack and so not exists after this function exits. */
+static StaticTask_t xTimerTaskTCB;
+static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
+
+ /* Pass out a pointer to the StaticTask_t structure in which the Timer
+ task's state will be stored. */
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
+
+ /* Pass out the array that will be used as the Timer task's stack. */
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
+}
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform.c
new file mode 100644
index 0000000000..7902627a97
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform.c
@@ -0,0 +1,111 @@
+/******************************************************************************
+*
+* Copyright (C) 2010 - 2015 Xilinx, Inc. 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 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.
+*
+* Use of the Software is limited solely to applications:
+* (a) running on a Xilinx device, or
+* (b) that interact with a Xilinx device through a bus or interconnect.
+*
+* 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
+* XILINX 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.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+
+#include "xparameters.h"
+#include "xil_cache.h"
+
+#include "platform_config.h"
+
+/*
+ * Uncomment one of the following two lines, depending on the target,
+ * if ps7/psu init source files are added in the source directory for
+ * compiling example outside of SDK.
+ */
+/*#include "ps7_init.h"*/
+/*#include "psu_init.h"*/
+
+#ifdef STDOUT_IS_16550
+ #include "xuartns550_l.h"
+
+ #define UART_BAUD 9600
+#endif
+
+void
+enable_caches()
+{
+#ifdef __PPC__
+ Xil_ICacheEnableRegion(CACHEABLE_REGION_MASK);
+ Xil_DCacheEnableRegion(CACHEABLE_REGION_MASK);
+#elif __MICROBLAZE__
+#ifdef XPAR_MICROBLAZE_USE_ICACHE
+ Xil_ICacheEnable();
+#endif
+#ifdef XPAR_MICROBLAZE_USE_DCACHE
+ Xil_DCacheEnable();
+#endif
+#endif
+}
+
+void
+disable_caches()
+{
+#ifdef __MICROBLAZE__
+#ifdef XPAR_MICROBLAZE_USE_DCACHE
+ Xil_DCacheDisable();
+#endif
+#ifdef XPAR_MICROBLAZE_USE_ICACHE
+ Xil_ICacheDisable();
+#endif
+#endif
+}
+
+void
+init_uart()
+{
+#ifdef STDOUT_IS_16550
+ XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, UART_BAUD);
+ XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS);
+#endif
+ /* Bootrom/BSP configures PS7/PSU UART to 115200 bps */
+}
+
+void
+init_platform()
+{
+ /*
+ * If you want to run this example outside of SDK,
+ * uncomment one of the following two lines and also #include "ps7_init.h"
+ * or #include "ps7_init.h" at the top, depending on the target.
+ * Make sure that the ps7/psu_init.c and ps7/psu_init.h files are included
+ * along with this example source files for compilation.
+ */
+ /* ps7_init(); */
+ /* psu_init();*/
+ enable_caches();
+ init_uart();
+}
+
+void
+cleanup_platform()
+{
+ disable_caches();
+}
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform.h b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform.h
new file mode 100644
index 0000000000..e273e37180
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+*
+* Copyright (C) 2008 - 2014 Xilinx, Inc. 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 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.
+*
+* Use of the Software is limited solely to applications:
+* (a) running on a Xilinx device, or
+* (b) that interact with a Xilinx device through a bus or interconnect.
+*
+* 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
+* XILINX 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.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+
+#ifndef __PLATFORM_H_
+#define __PLATFORM_H_
+
+#include "platform_config.h"
+
+void init_platform();
+void cleanup_platform();
+
+#endif
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform_config.h b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform_config.h
new file mode 100644
index 0000000000..3e9b7f1847
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/src/platform_config.h
@@ -0,0 +1,6 @@
+#ifndef __PLATFORM_CONFIG_H_
+#define __PLATFORM_CONFIG_H_
+
+#define STDOUT_IS_PS7_UART
+#define UART_DEVICE_ID 0
+#endif
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/zc702 Configuration QEMU.launch b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/zc702 Configuration QEMU.launch
new file mode 100644
index 0000000000..3b8bdebbbd
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo/zc702 Configuration QEMU.launch
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.cproject b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.cproject
new file mode 100644
index 0000000000..418770440c
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.cproject
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.gitignore b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.gitignore
new file mode 100644
index 0000000000..ac01e665d2
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.gitignore
@@ -0,0 +1,2 @@
+/Debug/
+/Release/
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.project b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.project
new file mode 100644
index 0000000000..974df32b86
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/.project
@@ -0,0 +1,30 @@
+
+
+ RTOSDemo_system
+
+
+ RTOSDemo
+ zc702
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ com.xilinx.sdx.system.core.embedded
+ com.xilinx.sdx.system.systemprojectnature
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/RTOSDemo_system.sprj b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/RTOSDemo_system.sprj
new file mode 100644
index 0000000000..8800a51978
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702_Vitis_QEMU/RTOSDemo_system/RTOSDemo_system.sprj
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/Common/Minimal/blocktim.c b/FreeRTOS/Demo/Common/Minimal/blocktim.c
index a01f9b1b43..bd080f9717 100644
--- a/FreeRTOS/Demo/Common/Minimal/blocktim.c
+++ b/FreeRTOS/Demo/Common/Minimal/blocktim.c
@@ -1,597 +1,597 @@
-/*
- * FreeRTOS V202112.00
- * Copyright (C) 2020 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
- * 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.
- *
- * https://www.FreeRTOS.org
- * https://aws.amazon.com/freertos
- *
- */
-
-/*
- * This file contains some test scenarios that ensure tasks do not exit queue
- * send or receive functions prematurely. A description of the tests is
- * included within the code.
- */
-
-/* Kernel includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-
-/* Demo includes. */
-#include "blocktim.h"
-
-/* Task priorities and stack sizes. Allow these to be overridden. */
-#ifndef bktPRIMARY_PRIORITY
- #define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
-#endif
-
-#ifndef bktSECONDARY_PRIORITY
- #define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 )
-#endif
-
-#ifndef bktBLOCK_TIME_TASK_STACK_SIZE
- #define bktBLOCK_TIME_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
-#endif
-
-/* Task behaviour. */
-#define bktQUEUE_LENGTH ( 5 )
-#define bktSHORT_WAIT pdMS_TO_TICKS( ( TickType_t ) 20 )
-#define bktPRIMARY_BLOCK_TIME ( 10 )
-#define bktALLOWABLE_MARGIN ( 15 )
-#define bktTIME_TO_BLOCK ( 175 )
-#define bktDONT_BLOCK ( ( TickType_t ) 0 )
-#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 )
-
-/* In case the demo does not have software timers enabled, as this file uses
- * the configTIMER_TASK_PRIORITY setting. */
-#ifndef configTIMER_TASK_PRIORITY
- #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * The two test tasks. Their behaviour is commented within the functions.
- */
-static void vPrimaryBlockTimeTestTask( void * pvParameters );
-static void vSecondaryBlockTimeTestTask( void * pvParameters );
-
-/*
- * Very basic tests to verify the block times are as expected.
- */
-static void prvBasicDelayTests( void );
-
-/*-----------------------------------------------------------*/
-
-/* The queue on which the tasks block. */
-static QueueHandle_t xTestQueue;
-
-/* Handle to the secondary task is required by the primary task for calls
- * to vTaskSuspend/Resume(). */
-static TaskHandle_t xSecondary;
-
-/* Used to ensure that tasks are still executing without error. */
-static volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;
-static volatile BaseType_t xErrorOccurred = pdFALSE;
-
-/* Provides a simple mechanism for the primary task to know when the
- * secondary task has executed. */
-static volatile UBaseType_t xRunIndicator;
-
-/*-----------------------------------------------------------*/
-
-void vCreateBlockTimeTasks( void )
-{
- /* Create the queue on which the two tasks block. */
- xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) );
-
- if( xTestQueue != NULL )
- {
- /* vQueueAddToRegistry() adds the queue to the queue registry, if one
- * is in use. The queue registry is provided as a means for kernel aware
- * debuggers to locate queues and has no purpose if a kernel aware
- * debugger is not being used. The call to vQueueAddToRegistry() will be
- * removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
- * defined or is defined to be less than 1. */
- vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" );
-
- /* Create the two test tasks. */
- xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", bktBLOCK_TIME_TASK_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
- xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", bktBLOCK_TIME_TASK_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
- }
-}
-/*-----------------------------------------------------------*/
-
-static void vPrimaryBlockTimeTestTask( void * pvParameters )
-{
- BaseType_t xItem, xData;
- TickType_t xTimeWhenBlocking;
- TickType_t xTimeToBlock, xBlockedTime;
-
- ( void ) pvParameters;
-
- for( ; ; )
- {
- /*********************************************************************
- * Test 0
- *
- * Basic vTaskDelay() and vTaskDelayUntil() tests. */
- prvBasicDelayTests();
-
- /*********************************************************************
- * Test 1
- *
- * Simple block time wakeup test on queue receives. */
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
- {
- /* The queue is empty. Attempt to read from the queue using a block
- * time. When we wake, ensure the delta in time is as expected. */
- xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
-
- xTimeWhenBlocking = xTaskGetTickCount();
-
- /* We should unblock after xTimeToBlock having not received
- * anything on the queue. */
- if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* How long were we blocked for? */
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
-
- if( xBlockedTime < xTimeToBlock )
- {
- /* Should not have blocked for less than we requested. */
- xErrorOccurred = pdTRUE;
- }
-
- if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
- {
- /* Should not have blocked for longer than we requested,
- * although we would not necessarily run as soon as we were
- * unblocked so a margin is allowed. */
- xErrorOccurred = pdTRUE;
- }
- }
-
- /*********************************************************************
- * Test 2
- *
- * Simple block time wakeup test on queue sends.
- *
- * First fill the queue. It should be empty so all sends should pass. */
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
- {
- if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
- {
- xErrorOccurred = pdTRUE;
- }
-
- #if configUSE_PREEMPTION == 0
- taskYIELD();
- #endif
- }
-
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
- {
- /* The queue is full. Attempt to write to the queue using a block
- * time. When we wake, ensure the delta in time is as expected. */
- xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
-
- xTimeWhenBlocking = xTaskGetTickCount();
-
- /* We should unblock after xTimeToBlock having not received
- * anything on the queue. */
- if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* How long were we blocked for? */
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
-
- if( xBlockedTime < xTimeToBlock )
- {
- /* Should not have blocked for less than we requested. */
- xErrorOccurred = pdTRUE;
- }
-
- if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
- {
- /* Should not have blocked for longer than we requested,
- * although we would not necessarily run as soon as we were
- * unblocked so a margin is allowed. */
- xErrorOccurred = pdTRUE;
- }
- }
-
- /*********************************************************************
- * Test 3
- *
- * Wake the other task, it will block attempting to post to the queue.
- * When we read from the queue the other task will wake, but before it
- * can run we will post to the queue again. When the other task runs it
- * will find the queue still full, even though it was woken. It should
- * recognise that its block time has not expired and return to block for
- * the remains of its block time.
- *
- * Wake the other task so it blocks attempting to post to the already
- * full queue. */
- xRunIndicator = 0;
- vTaskResume( xSecondary );
-
- /* We need to wait a little to ensure the other task executes. */
- while( xRunIndicator != bktRUN_INDICATOR )
- {
- /* The other task has not yet executed. */
- vTaskDelay( bktSHORT_WAIT );
- }
-
- /* Make sure the other task is blocked on the queue. */
- vTaskDelay( bktSHORT_WAIT );
- xRunIndicator = 0;
-
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
- {
- /* Now when we make space on the queue the other task should wake
- * but not execute as this task has higher priority. */
- if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Now fill the queue again before the other task gets a chance to
- * execute. If the other task had executed we would find the queue
- * full ourselves, and the other task have set xRunIndicator. */
- if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
- {
- xErrorOccurred = pdTRUE;
- }
-
- if( xRunIndicator == bktRUN_INDICATOR )
- {
- /* The other task should not have executed. */
- xErrorOccurred = pdTRUE;
- }
-
- /* Raise the priority of the other task so it executes and blocks
- * on the queue again. */
- vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
-
- /* The other task should now have re-blocked without exiting the
- * queue function. */
- if( xRunIndicator == bktRUN_INDICATOR )
- {
- /* The other task should not have executed outside of the
- * queue function. */
- xErrorOccurred = pdTRUE;
- }
-
- /* Set the priority back down. */
- vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
- }
-
- /* Let the other task timeout. When it unblockes it will check that it
- * unblocked at the correct time, then suspend itself. */
- while( xRunIndicator != bktRUN_INDICATOR )
- {
- vTaskDelay( bktSHORT_WAIT );
- }
-
- vTaskDelay( bktSHORT_WAIT );
- xRunIndicator = 0;
-
- /*********************************************************************
- * Test 4
- *
- * As per test 3 - but with the send and receive the other way around.
- * The other task blocks attempting to read from the queue.
- *
- * Empty the queue. We should find that it is full. */
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
- {
- if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
- {
- xErrorOccurred = pdTRUE;
- }
- }
-
- /* Wake the other task so it blocks attempting to read from the
- * already empty queue. */
- vTaskResume( xSecondary );
-
- /* We need to wait a little to ensure the other task executes. */
- while( xRunIndicator != bktRUN_INDICATOR )
- {
- vTaskDelay( bktSHORT_WAIT );
- }
-
- vTaskDelay( bktSHORT_WAIT );
- xRunIndicator = 0;
-
- for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
- {
- /* Now when we place an item on the queue the other task should
- * wake but not execute as this task has higher priority. */
- if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Now empty the queue again before the other task gets a chance to
- * execute. If the other task had executed we would find the queue
- * empty ourselves, and the other task would be suspended. */
- if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
- {
- xErrorOccurred = pdTRUE;
- }
-
- if( xRunIndicator == bktRUN_INDICATOR )
- {
- /* The other task should not have executed. */
- xErrorOccurred = pdTRUE;
- }
-
- /* Raise the priority of the other task so it executes and blocks
- * on the queue again. */
- vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
-
- /* The other task should now have re-blocked without exiting the
- * queue function. */
- if( xRunIndicator == bktRUN_INDICATOR )
- {
- /* The other task should not have executed outside of the
- * queue function. */
- xErrorOccurred = pdTRUE;
- }
-
- vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
- }
-
- /* Let the other task timeout. When it unblockes it will check that it
- * unblocked at the correct time, then suspend itself. */
- while( xRunIndicator != bktRUN_INDICATOR )
- {
- vTaskDelay( bktSHORT_WAIT );
- }
-
- vTaskDelay( bktSHORT_WAIT );
-
- xPrimaryCycles++;
- }
-}
-/*-----------------------------------------------------------*/
-
-static void vSecondaryBlockTimeTestTask( void * pvParameters )
-{
- TickType_t xTimeWhenBlocking, xBlockedTime;
- BaseType_t xData;
-
- ( void ) pvParameters;
-
- for( ; ; )
- {
- /*********************************************************************
- * Test 0, 1 and 2
- *
- * This task does not participate in these tests. */
- vTaskSuspend( NULL );
-
- /*********************************************************************
- * Test 3
- *
- * The first thing we do is attempt to read from the queue. It should be
- * full so we block. Note the time before we block so we can check the
- * wake time is as per that expected. */
- xTimeWhenBlocking = xTaskGetTickCount();
-
- /* We should unblock after bktTIME_TO_BLOCK having not sent anything to
- * the queue. */
- xData = 0;
- xRunIndicator = bktRUN_INDICATOR;
-
- if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* How long were we inside the send function? */
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
-
- /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
- if( xBlockedTime < bktTIME_TO_BLOCK )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
- * either. A margin is permitted as we would not necessarily run as
- * soon as we unblocked. */
- if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Suspend ready for test 3. */
- xRunIndicator = bktRUN_INDICATOR;
- vTaskSuspend( NULL );
-
- /*********************************************************************
- * Test 4
- *
- * As per test three, but with the send and receive reversed. */
- xTimeWhenBlocking = xTaskGetTickCount();
-
- /* We should unblock after bktTIME_TO_BLOCK having not received
- * anything on the queue. */
- xRunIndicator = bktRUN_INDICATOR;
-
- if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
- {
- xErrorOccurred = pdTRUE;
- }
-
- xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
-
- /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
- if( xBlockedTime < bktTIME_TO_BLOCK )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
- * either. A margin is permitted as we would not necessarily run as soon
- * as we unblocked. */
- if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
- {
- xErrorOccurred = pdTRUE;
- }
-
- xRunIndicator = bktRUN_INDICATOR;
-
- xSecondaryCycles++;
- }
-}
-/*-----------------------------------------------------------*/
-
-static void prvBasicDelayTests( void )
-{
- TickType_t xPreTime, xPostTime, x, xLastUnblockTime, xExpectedUnblockTime;
- const TickType_t xPeriod = 75, xCycles = 5, xAllowableMargin = ( bktALLOWABLE_MARGIN >> 1 ), xHalfPeriod = xPeriod / ( TickType_t ) 2;
- BaseType_t xDidBlock;
-
- /* Temporarily increase priority so the timing is more accurate, but not so
- * high as to disrupt the timer tests. */
- vTaskPrioritySet( NULL, configTIMER_TASK_PRIORITY - 1 );
-
- /* Crude check to too see that vTaskDelay() blocks for the expected
- * period. */
- xPreTime = xTaskGetTickCount();
- vTaskDelay( bktTIME_TO_BLOCK );
- xPostTime = xTaskGetTickCount();
-
- /* The priority is higher, so the allowable margin is halved when compared
- * to the other tests in this file. */
- if( ( xPostTime - xPreTime ) > ( bktTIME_TO_BLOCK + xAllowableMargin ) )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Now crude tests to check the vTaskDelayUntil() functionality. */
- xPostTime = xTaskGetTickCount();
- xLastUnblockTime = xPostTime;
-
- for( x = 0; x < xCycles; x++ )
- {
- /* Calculate the next expected unblock time from the time taken before
- * this loop was entered. */
- xExpectedUnblockTime = xPostTime + ( x * xPeriod );
-
- vTaskDelayUntil( &xLastUnblockTime, xPeriod );
-
- if( ( xTaskGetTickCount() - xExpectedUnblockTime ) > ( bktTIME_TO_BLOCK + xAllowableMargin ) )
- {
- xErrorOccurred = pdTRUE;
- }
-
- xPrimaryCycles++;
- }
-
- /* Crude tests for return value of xTaskDelayUntil(). First a standard block
- * should return that the task does block. */
- xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
-
- if( xDidBlock != pdTRUE )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Now delay a few ticks so repeating the above block period will not block for
- * the full amount of time, but will still block. */
- vTaskDelay( xHalfPeriod );
- xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
-
- if( xDidBlock != pdTRUE )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* This time block for longer than xPeriod before calling xTaskDelayUntil() so
- * the call to xTaskDelayUntil() should not block. */
- vTaskDelay( xPeriod );
- xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
-
- if( xDidBlock != pdFALSE )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Catch up. */
- xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
-
- if( xDidBlock != pdTRUE )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Again block for slightly longer than a period so ensure the time is in the
- * past next time xTaskDelayUntil() gets called. */
- vTaskDelay( xPeriod + xAllowableMargin );
- xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
-
- if( xDidBlock != pdFALSE )
- {
- xErrorOccurred = pdTRUE;
- }
-
- /* Reset to the original task priority ready for the other tests. */
- vTaskPrioritySet( NULL, bktPRIMARY_PRIORITY );
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xAreBlockTimeTestTasksStillRunning( void )
-{
- static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
- BaseType_t xReturn = pdPASS;
-
- /* Have both tasks performed at least one cycle since this function was
- * last called? */
- if( xPrimaryCycles == xLastPrimaryCycleCount )
- {
- xReturn = pdFAIL;
- }
-
- if( xSecondaryCycles == xLastSecondaryCycleCount )
- {
- xReturn = pdFAIL;
- }
-
- if( xErrorOccurred == pdTRUE )
- {
- xReturn = pdFAIL;
- }
-
- xLastSecondaryCycleCount = xSecondaryCycles;
- xLastPrimaryCycleCount = xPrimaryCycles;
-
- return xReturn;
-}
+/*
+ * FreeRTOS V202112.00
+ * Copyright (C) 2020 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
+ * 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*
+ * This file contains some test scenarios that ensure tasks do not exit queue
+ * send or receive functions prematurely. A description of the tests is
+ * included within the code.
+ */
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Demo includes. */
+#include "blocktim.h"
+
+/* Task priorities and stack sizes. Allow these to be overridden. */
+#ifndef bktPRIMARY_PRIORITY
+ #define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
+#endif
+
+#ifndef bktSECONDARY_PRIORITY
+ #define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 )
+#endif
+
+#ifndef bktBLOCK_TIME_TASK_STACK_SIZE
+ #define bktBLOCK_TIME_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
+#endif
+
+/* Task behaviour. */
+#define bktQUEUE_LENGTH ( 5 )
+#define bktSHORT_WAIT pdMS_TO_TICKS( ( TickType_t ) 20 )
+#define bktPRIMARY_BLOCK_TIME ( 10 )
+#define bktALLOWABLE_MARGIN ( 15 )
+#define bktTIME_TO_BLOCK ( 175 )
+#define bktDONT_BLOCK ( ( TickType_t ) 0 )
+#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 )
+
+/* In case the demo does not have software timers enabled, as this file uses
+ * the configTIMER_TASK_PRIORITY setting. */
+#ifndef configTIMER_TASK_PRIORITY
+ #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The two test tasks. Their behaviour is commented within the functions.
+ */
+static void vPrimaryBlockTimeTestTask( void * pvParameters );
+static void vSecondaryBlockTimeTestTask( void * pvParameters );
+
+/*
+ * Very basic tests to verify the block times are as expected.
+ */
+static void prvBasicDelayTests( void );
+
+/*-----------------------------------------------------------*/
+
+/* The queue on which the tasks block. */
+static QueueHandle_t xTestQueue;
+
+/* Handle to the secondary task is required by the primary task for calls
+ * to vTaskSuspend/Resume(). */
+static TaskHandle_t xSecondary;
+
+/* Used to ensure that tasks are still executing without error. */
+static volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;
+static volatile BaseType_t xErrorOccurred = pdFALSE;
+
+/* Provides a simple mechanism for the primary task to know when the
+ * secondary task has executed. */
+static volatile UBaseType_t xRunIndicator;
+
+/*-----------------------------------------------------------*/
+
+void vCreateBlockTimeTasks( void )
+{
+ /* Create the queue on which the two tasks block. */
+ xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( BaseType_t ) );
+
+ if( xTestQueue != NULL )
+ {
+ /* vQueueAddToRegistry() adds the queue to the queue registry, if one
+ * is in use. The queue registry is provided as a means for kernel aware
+ * debuggers to locate queues and has no purpose if a kernel aware
+ * debugger is not being used. The call to vQueueAddToRegistry() will be
+ * removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
+ * defined or is defined to be less than 1. */
+ vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" );
+
+ /* Create the two test tasks. */
+ xTaskCreate( vPrimaryBlockTimeTestTask, "BTest1", bktBLOCK_TIME_TASK_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL );
+ xTaskCreate( vSecondaryBlockTimeTestTask, "BTest2", bktBLOCK_TIME_TASK_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vPrimaryBlockTimeTestTask( void * pvParameters )
+{
+ BaseType_t xItem, xData;
+ TickType_t xTimeWhenBlocking;
+ TickType_t xTimeToBlock, xBlockedTime;
+
+ ( void ) pvParameters;
+
+ for( ; ; )
+ {
+ /*********************************************************************
+ * Test 0
+ *
+ * Basic vTaskDelay() and vTaskDelayUntil() tests. */
+ prvBasicDelayTests();
+
+ /*********************************************************************
+ * Test 1
+ *
+ * Simple block time wakeup test on queue receives. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* The queue is empty. Attempt to read from the queue using a block
+ * time. When we wake, ensure the delta in time is as expected. */
+ xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
+
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after xTimeToBlock having not received
+ * anything on the queue. */
+ if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we blocked for? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ if( xBlockedTime < xTimeToBlock )
+ {
+ /* Should not have blocked for less than we requested. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
+ {
+ /* Should not have blocked for longer than we requested,
+ * although we would not necessarily run as soon as we were
+ * unblocked so a margin is allowed. */
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /*********************************************************************
+ * Test 2
+ *
+ * Simple block time wakeup test on queue sends.
+ *
+ * First fill the queue. It should be empty so all sends should pass. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ #if configUSE_PREEMPTION == 0
+ taskYIELD();
+ #endif
+ }
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* The queue is full. Attempt to write to the queue using a block
+ * time. When we wake, ensure the delta in time is as expected. */
+ xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
+
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after xTimeToBlock having not received
+ * anything on the queue. */
+ if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we blocked for? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ if( xBlockedTime < xTimeToBlock )
+ {
+ /* Should not have blocked for less than we requested. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
+ {
+ /* Should not have blocked for longer than we requested,
+ * although we would not necessarily run as soon as we were
+ * unblocked so a margin is allowed. */
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /*********************************************************************
+ * Test 3
+ *
+ * Wake the other task, it will block attempting to post to the queue.
+ * When we read from the queue the other task will wake, but before it
+ * can run we will post to the queue again. When the other task runs it
+ * will find the queue still full, even though it was woken. It should
+ * recognise that its block time has not expired and return to block for
+ * the remains of its block time.
+ *
+ * Wake the other task so it blocks attempting to post to the already
+ * full queue. */
+ xRunIndicator = 0;
+ vTaskResume( xSecondary );
+
+ /* We need to wait a little to ensure the other task executes. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ /* The other task has not yet executed. */
+ vTaskDelay( bktSHORT_WAIT );
+ }
+
+ /* Make sure the other task is blocked on the queue. */
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* Now when we make space on the queue the other task should wake
+ * but not execute as this task has higher priority. */
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now fill the queue again before the other task gets a chance to
+ * execute. If the other task had executed we would find the queue
+ * full ourselves, and the other task have set xRunIndicator. */
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Raise the priority of the other task so it executes and blocks
+ * on the queue again. */
+ vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
+
+ /* The other task should now have re-blocked without exiting the
+ * queue function. */
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed outside of the
+ * queue function. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Set the priority back down. */
+ vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
+ }
+
+ /* Let the other task timeout. When it unblockes it will check that it
+ * unblocked at the correct time, then suspend itself. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ /*********************************************************************
+ * Test 4
+ *
+ * As per test 3 - but with the send and receive the other way around.
+ * The other task blocks attempting to read from the queue.
+ *
+ * Empty the queue. We should find that it is full. */
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+ }
+
+ /* Wake the other task so it blocks attempting to read from the
+ * already empty queue. */
+ vTaskResume( xSecondary );
+
+ /* We need to wait a little to ensure the other task executes. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+
+ vTaskDelay( bktSHORT_WAIT );
+ xRunIndicator = 0;
+
+ for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
+ {
+ /* Now when we place an item on the queue the other task should
+ * wake but not execute as this task has higher priority. */
+ if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now empty the queue again before the other task gets a chance to
+ * execute. If the other task had executed we would find the queue
+ * empty ourselves, and the other task would be suspended. */
+ if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Raise the priority of the other task so it executes and blocks
+ * on the queue again. */
+ vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
+
+ /* The other task should now have re-blocked without exiting the
+ * queue function. */
+ if( xRunIndicator == bktRUN_INDICATOR )
+ {
+ /* The other task should not have executed outside of the
+ * queue function. */
+ xErrorOccurred = pdTRUE;
+ }
+
+ vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
+ }
+
+ /* Let the other task timeout. When it unblockes it will check that it
+ * unblocked at the correct time, then suspend itself. */
+ while( xRunIndicator != bktRUN_INDICATOR )
+ {
+ vTaskDelay( bktSHORT_WAIT );
+ }
+
+ vTaskDelay( bktSHORT_WAIT );
+
+ xPrimaryCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vSecondaryBlockTimeTestTask( void * pvParameters )
+{
+ TickType_t xTimeWhenBlocking, xBlockedTime;
+ BaseType_t xData;
+
+ ( void ) pvParameters;
+
+ for( ; ; )
+ {
+ /*********************************************************************
+ * Test 0, 1 and 2
+ *
+ * This task does not participate in these tests. */
+ vTaskSuspend( NULL );
+
+ /*********************************************************************
+ * Test 3
+ *
+ * The first thing we do is attempt to read from the queue. It should be
+ * full so we block. Note the time before we block so we can check the
+ * wake time is as per that expected. */
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after bktTIME_TO_BLOCK having not sent anything to
+ * the queue. */
+ xData = 0;
+ xRunIndicator = bktRUN_INDICATOR;
+
+ if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* How long were we inside the send function? */
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+ if( xBlockedTime < bktTIME_TO_BLOCK )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+ * either. A margin is permitted as we would not necessarily run as
+ * soon as we unblocked. */
+ if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Suspend ready for test 3. */
+ xRunIndicator = bktRUN_INDICATOR;
+ vTaskSuspend( NULL );
+
+ /*********************************************************************
+ * Test 4
+ *
+ * As per test three, but with the send and receive reversed. */
+ xTimeWhenBlocking = xTaskGetTickCount();
+
+ /* We should unblock after bktTIME_TO_BLOCK having not received
+ * anything on the queue. */
+ xRunIndicator = bktRUN_INDICATOR;
+
+ if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+ /* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+ if( xBlockedTime < bktTIME_TO_BLOCK )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+ * either. A margin is permitted as we would not necessarily run as soon
+ * as we unblocked. */
+ if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xRunIndicator = bktRUN_INDICATOR;
+
+ xSecondaryCycles++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvBasicDelayTests( void )
+{
+ TickType_t xPreTime, xPostTime, x, xLastUnblockTime, xExpectedUnblockTime;
+ const TickType_t xPeriod = 75, xCycles = 5, xAllowableMargin = ( bktALLOWABLE_MARGIN >> 1 ), xHalfPeriod = xPeriod / ( TickType_t ) 2;
+ BaseType_t xDidBlock;
+
+ /* Temporarily increase priority so the timing is more accurate, but not so
+ * high as to disrupt the timer tests. */
+ vTaskPrioritySet( NULL, configTIMER_TASK_PRIORITY - 1 );
+
+ /* Crude check to too see that vTaskDelay() blocks for the expected
+ * period. */
+ xPreTime = xTaskGetTickCount();
+ vTaskDelay( bktTIME_TO_BLOCK );
+ xPostTime = xTaskGetTickCount();
+
+ /* The priority is higher, so the allowable margin is halved when compared
+ * to the other tests in this file. */
+ if( ( xPostTime - xPreTime ) > ( bktTIME_TO_BLOCK + xAllowableMargin ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now crude tests to check the vTaskDelayUntil() functionality. */
+ xPostTime = xTaskGetTickCount();
+ xLastUnblockTime = xPostTime;
+
+ for( x = 0; x < xCycles; x++ )
+ {
+ /* Calculate the next expected unblock time from the time taken before
+ * this loop was entered. */
+ xExpectedUnblockTime = xPostTime + ( x * xPeriod );
+
+ vTaskDelayUntil( &xLastUnblockTime, xPeriod );
+
+ if( ( xTaskGetTickCount() - xExpectedUnblockTime ) > ( bktTIME_TO_BLOCK + xAllowableMargin ) )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ xPrimaryCycles++;
+ }
+
+ /* Crude tests for return value of xTaskDelayUntil(). First a standard block
+ * should return that the task does block. */
+ xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
+
+ if( xDidBlock != pdTRUE )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Now delay a few ticks so repeating the above block period will not block for
+ * the full amount of time, but will still block. */
+ vTaskDelay( xHalfPeriod );
+ xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
+
+ if( xDidBlock != pdTRUE )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* This time block for longer than xPeriod before calling xTaskDelayUntil() so
+ * the call to xTaskDelayUntil() should not block. */
+ vTaskDelay( xPeriod );
+ xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
+
+ if( xDidBlock != pdFALSE )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Catch up. */
+ xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
+
+ if( xDidBlock != pdTRUE )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Again block for slightly longer than a period so ensure the time is in the
+ * past next time xTaskDelayUntil() gets called. */
+ vTaskDelay( xPeriod + xAllowableMargin );
+ xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
+
+ if( xDidBlock != pdFALSE )
+ {
+ xErrorOccurred = pdTRUE;
+ }
+
+ /* Reset to the original task priority ready for the other tests. */
+ vTaskPrioritySet( NULL, bktPRIMARY_PRIORITY );
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xAreBlockTimeTestTasksStillRunning( void )
+{
+ static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
+ BaseType_t xReturn = pdPASS;
+
+ /* Have both tasks performed at least one cycle since this function was
+ * last called? */
+ if( xPrimaryCycles == xLastPrimaryCycleCount )
+ {
+ xReturn = pdFAIL;
+ }
+
+ if( xSecondaryCycles == xLastSecondaryCycleCount )
+ {
+ xReturn = pdFAIL;
+ }
+
+ if( xErrorOccurred == pdTRUE )
+ {
+ xReturn = pdFAIL;
+ }
+
+ xLastSecondaryCycleCount = xSecondaryCycles;
+ xLastPrimaryCycleCount = xPrimaryCycles;
+
+ return xReturn;
+}
diff --git a/lexicon.txt b/lexicon.txt
index de02056cc2..48a4f1230b 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -1,3 +1,4 @@
+aaaa
ab
abs
accesskeyid
@@ -81,6 +82,7 @@ basetype
bauddiv
baudrate
baudrateconverter
+bb
bcd
bcdcdc
bcddevicel
@@ -2459,6 +2461,7 @@ staticsemaphore
staticstreambuffer
statictask
statictimer
+statusmessage
stdarg
stdint
stdlib
@@ -2770,6 +2773,7 @@ ulong
ulpacketsreceived
ulpacketssent
ulport
+ulportinterruptnesting
ulprescale
ulpriority
ulprioritysetcounter