diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h
new file mode 100644
index 000000000..a8df38e6c
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h
@@ -0,0 +1,220 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+/* The MPU version of port.c includes and excludes functions depending on the
+settings within this file. Therefore, to ensure all the functions in port.c
+build, this configuration file has all options turned on. */
+
+#define configUSE_PREEMPTION 1
+#define configTICK_RATE_HZ ( 1000 )
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#define configUSE_QUEUE_SETS 1
+#define configUSE_IDLE_HOOK 1
+#define configUSE_TICK_HOOK 1
+#define configCPU_CLOCK_HZ 48000000
+#define configMAX_PRIORITIES ( 5 )
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16 * 1024 ) )
+#define configMAX_TASK_NAME_LEN ( 10 )
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configQUEUE_REGISTRY_SIZE 5
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_MALLOC_FAILED_HOOK 1
+#define configUSE_APPLICATION_TASK_TAG 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_TICKLESS_IDLE 0
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 2
+
+/* This demo shows the MPU being used without any dynamic memory allocation. */
+#define configSUPPORT_STATIC_ALLOCATION 1
+#define configSUPPORT_DYNAMIC_ALLOCATION 0
+
+/* Run time stats gathering definitions. */
+#define configGENERATE_RUN_TIME_STATS 1
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+#define portGET_RUN_TIME_COUNTER_VALUE() 0
+
+/* This demo makes use of one or more example stats formatting functions. These
+format the raw data provided by the uxTaskGetSystemState() function in to human
+readable ASCII form. See the notes in the implementation of vTaskList() within
+FreeRTOS/Source/tasks.c for limitations. */
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+/* Software timer definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY ( 2 )
+#define configTIMER_QUEUE_LENGTH 5
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_eTaskGetState 1
+#define INCLUDE_xTimerPendFunctionCall 0
+#define INCLUDE_xSemaphoreGetMutexHolder 1
+#define INCLUDE_xTaskGetHandle 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_xTaskGetIdleTaskHandle 1
+#define INCLUDE_xTaskAbortDelay 1
+#define INCLUDE_xTaskGetSchedulerState 1
+#define INCLUDE_xTaskGetIdleTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+
+/* Cortex-M specific definitions. */
+#ifdef __NVIC_PRIO_BITS
+ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+ #define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+ #define configPRIO_BITS 4 /* 15 priority levels */
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names. */
+#define xPortPendSVHandler PendSV_Handler
+#define vPortSVCHandler SVC_Handler
+#define xPortSysTickHandler SysTick_Handler
+
+/* Normal assert() semantics without relying on the provision of an assert.h
+header file. */
+#define configASSERT( x ) if( ( x ) == 0UL ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
+
+/* LED not used at present, so just increment a variable to keep a count of the
+number of times the LED would otherwise have been toggled. */
+#define configTOGGLE_LED() ulLED++
+
+/* Definitions for the messages that can be sent to the check task. */
+#define configREG_TEST_1_STILL_EXECUTING ( 0 )
+#define configREG_TEST_2_STILL_EXECUTING ( 1 )
+#define configTIMER_STILL_EXECUTING ( 2 )
+#define configPRINT_SYSTEM_STATUS ( 3 )
+
+/* Parameters that are passed into the third and fourth register check tasks
+solely for the purpose of ensuring parameters are passed into tasks correctly. */
+#define configREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x11112222 )
+#define configREG_TEST_TASK_3_PARAMETER ( ( void * ) 0x12345678 )
+#define configREG_TEST_TASK_4_PARAMETER ( ( void * ) 0x87654321 )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREERTOS_CONFIG_H */
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx
new file mode 100644
index 000000000..c9679d2b4
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx
@@ -0,0 +1,369 @@
+
+
+
+ 1.0
+
+ ### uVision Project, (C) Keil Software
+
+
+ *.c;*.S
+
+ *.obj
+ *.lib
+ *.txt; *.h; *.inc
+ *.plm
+ *.cpp
+ 0
+
+
+
+ 0
+ 0
+
+
+
+ RTOSDemo_GCC_MPU
+ 0x3
+ ARM-GNU
+
+ 12000000
+
+ 1
+ 1
+ 0
+ 1
+ 0
+
+
+ 1
+ 65535
+ 0
+ 0
+ 0
+
+
+ 120
+ 65
+ 8
+ .\Listings\
+
+
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+ 7
+
+ 1
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+ BIN\UL2CM3.DLL
+
+
+
+ 0
+ DLGDARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=1215,201,1680,501,0)
+
+
+ 0
+ ARMRTXEVENTFLAGS
+ -L70 -Z18 -C0 -M0 -T1
+
+
+ 0
+ DLGTARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=120,149,354,683,0)(1012=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMDBGFLAGS
+ -T0
+
+
+ 0
+ DLGUARM
+ (105=-1,-1,-1,-1,0)
+
+
+ 0
+ UL2CM3
+ -UV1115SAE -O2983 -S0 -C0 -P00 -N00("ARM CoreSight JTAG-DP") -D00(4BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO11 -FN1 -FC1000 -FD20000000 -FF0NEW_DEVICE -FL080000 -FS00 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM)
+
+
+
+
+
+ 0
+ 1
+ xTickCount
+
+
+ 1
+ 1
+ ulCycleCount
+
+
+
+
+ 1
+ 2
+ 0x100000
+ 4
+
+
+
+ 0
+
+
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 0
+
+
+ 0
+
+ 1
+ 0
+ 2
+ 10000000
+
+
+
+
+
+ System
+ 1
+ 0
+ 0
+ 0
+
+ 1
+ 1
+ 2
+ 0
+ 0
+ 0
+ .\startup_ARMCM4.S
+ startup_ARMCM4.S
+ 0
+ 0
+
+
+
+
+ application_and_config
+ 1
+ 0
+ 0
+ 0
+
+ 2
+ 2
+ 1
+ 0
+ 0
+ 0
+ ..\main.c
+ main.c
+ 0
+ 0
+
+
+ 2
+ 3
+ 5
+ 0
+ 0
+ 0
+ ..\FreeRTOSConfig.h
+ FreeRTOSConfig.h
+ 0
+ 0
+
+
+ 2
+ 4
+ 1
+ 0
+ 0
+ 0
+ .\RegTest.c
+ RegTest.c
+ 0
+ 0
+
+
+
+
+ FreeRTOS_Source
+ 1
+ 0
+ 0
+ 0
+
+ 3
+ 5
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\event_groups.c
+ event_groups.c
+ 0
+ 0
+
+
+ 3
+ 6
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\list.c
+ list.c
+ 0
+ 0
+
+
+ 3
+ 7
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\queue.c
+ queue.c
+ 0
+ 0
+
+
+ 3
+ 8
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\tasks.c
+ tasks.c
+ 0
+ 0
+
+
+ 3
+ 9
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\timers.c
+ timers.c
+ 0
+ 0
+
+
+ 3
+ 10
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\portable\Common\mpu_wrappers.c
+ mpu_wrappers.c
+ 0
+ 0
+
+
+ 3
+ 11
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\portable\GCC\ARM_CM4_MPU\port.c
+ port.c
+ 0
+ 0
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx
new file mode 100644
index 000000000..645d4826d
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx
@@ -0,0 +1,348 @@
+
+
+
+ 2.1
+
+ ### uVision Project, (C) Keil Software
+
+
+
+ RTOSDemo_GCC_MPU
+ 0x3
+ ARM-GNU
+ 5060061::V5.06 update 1 (build 61)::ARMCC
+
+
+ ARMCM4_FP
+ ARM
+ ARM.CMSIS.5.0.0-Beta4
+ http://www.keil.com/pack/
+ IROM(0x00000000,0x80000) IRAM(0x20000000,0x20000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ESEL ELITTLE
+
+
+ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0NEW_DEVICE -FS00 -FL080000 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM))
+ 0
+ $$Device:ARMCM4_FP$Device\ARM\ARMCM4\Include\ARMCM4_FP.h
+
+
+
+
+
+
+
+
+
+ $$Device:ARMCM4_FP$Device\ARM\SVD\ARMCM4.svd
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+
+ .\Objects\
+ RTOSDemo
+ 1
+ 0
+ 0
+ 1
+ 0
+ .\Listings\
+ 1
+ 0
+ 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 3
+
+
+ 1
+
+
+ SARMCM3.DLL
+ -MPU
+ DCM.DLL
+ -pCM4
+ SARMCM3.DLL
+ -MPU
+ TCM.DLL
+ -pCM4
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 16
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4096
+
+ 1
+ BIN\UL2CM3.DLL
+ "" ()
+
+
+
+
+ 0
+
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ "Cortex-M4"
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 0
+ 2
+ 0
+ 0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x20000
+
+
+ 1
+ 0x0
+ 0x80000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 1
+ 0x200000
+ 0x4000
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 2
+ 1
+
+ -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -ffunction-sections -fdata-sections -O0 -g
+
+
+ ..;..\..\..\Source\include;..\..\..\Source\portable\GCC\ARM_CM4_MPU;..\..\Common\include;..\peripheral_library;..\CMSIS;..\main_full;..\peripheral_library\interrupt
+
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+ 1
+ 0
+ 1
+ 0
+ 1
+
+
+
+
+
+ -Xlinker --gc-sections
+ .\sections.ld
+
+
+
+
+
+ System
+
+
+ startup_ARMCM4.S
+ 2
+ .\startup_ARMCM4.S
+
+
+
+
+ application_and_config
+
+
+ main.c
+ 1
+ ..\main.c
+
+
+ FreeRTOSConfig.h
+ 5
+ ..\FreeRTOSConfig.h
+
+
+ RegTest.c
+ 1
+ .\RegTest.c
+
+
+
+
+ FreeRTOS_Source
+
+
+ event_groups.c
+ 1
+ ..\..\..\Source\event_groups.c
+
+
+ list.c
+ 1
+ ..\..\..\Source\list.c
+
+
+ queue.c
+ 1
+ ..\..\..\Source\queue.c
+
+
+ tasks.c
+ 1
+ ..\..\..\Source\tasks.c
+
+
+ timers.c
+ 1
+ ..\..\..\Source\timers.c
+
+
+ mpu_wrappers.c
+ 1
+ ..\..\..\Source\portable\Common\mpu_wrappers.c
+
+
+ port.c
+ 1
+ ..\..\..\Source\portable\GCC\ARM_CM4_MPU\port.c
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c
new file mode 100644
index 000000000..5b45ce166
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c
@@ -0,0 +1,692 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "queue.h"
+
+/*
+ * "Reg test" tasks - These fill the 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.
+ */
+
+void vRegTest1Implementation( void *pvParameters );
+void vRegTest2Implementation( void *pvParameters );
+void vRegTest3Implementation( void ) __attribute__ ((naked));
+void vRegTest4Implementation( void ) __attribute__ ((naked));
+
+/*
+ * Used as an easy way of deleting a task from inline assembly.
+ */
+extern void vMainDeleteMe( void ) __attribute__((noinline));
+
+/*
+ * Used by the first two reg test tasks and a software timer callback function
+ * to send messages to the check task. The message just lets the check task
+ * know that the tasks and timer are still functioning correctly. If a reg test
+ * task detects an error it will delete itself, and in so doing prevent itself
+ * from sending any more 'I'm Alive' messages to the check task.
+ */
+extern void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber );
+
+/* The queue used to send a message to the check task. */
+extern QueueHandle_t xGlobalScopeCheckQueue;
+
+/*-----------------------------------------------------------*/
+
+void vRegTest1Implementation( void *pvParameters )
+{
+/* This task is created in privileged mode so can access the file scope
+queue variable. Take a stack copy of this before the task is set into user
+mode. Once this task is in user mode the file scope queue variable will no
+longer be accessible but the stack copy will. */
+QueueHandle_t xQueue = xGlobalScopeCheckQueue;
+
+ /* Now the queue handle has been obtained the task can switch to user
+ mode. This is just one method of passing a handle into a protected
+ task, the other reg test task uses the task parameter instead. */
+ portSWITCH_TO_USER_MODE();
+
+ /* First check that the parameter value is as expected. */
+ if( pvParameters != ( void * ) configREG_TEST_TASK_1_PARAMETER )
+ {
+ /* Error detected. Delete the task so it stops communicating with
+ the check task. */
+ vMainDeleteMe();
+ }
+
+ for( ;; )
+ {
+ /* This task tests the kernel context switch mechanism by reading and
+ writing directly to registers - which requires the test to be written
+ in assembly code. */
+ __asm volatile
+ (
+ " MOV R4, #104 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */
+ " MOV R5, #105 \n"
+ " MOV R6, #106 \n"
+ " MOV R8, #108 \n"
+ " MOV R9, #109 \n"
+ " MOV R10, #110 \n"
+ " MOV R11, #111 \n"
+ "reg1loop: \n"
+ " MOV R0, #100 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */
+ " MOV R1, #101 \n"
+ " MOV R2, #102 \n"
+ " MOV R3, #103 \n"
+ " MOV R12, #112 \n"
+ " SVC #1 \n" /* Yield just to increase test coverage. */
+ " CMP R0, #100 \n" /* Check all the registers still contain their expected values. */
+ " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */
+ " CMP R1, #101 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R2, #102 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R3, #103 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R4, #104 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R5, #105 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R6, #106 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R8, #108 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R9, #109 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R10, #110 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R11, #111 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R12, #112 \n"
+ " BNE vMainDeleteMe \n"
+ :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+
+ /* Send configREG_TEST_1_STILL_EXECUTING to the check task to indicate that this
+ task is still functioning. */
+ vMainSendImAlive( xQueue, configREG_TEST_1_STILL_EXECUTING );
+
+ /* Go back to check all the register values again. */
+ __asm volatile( " B reg1loop " );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vRegTest2Implementation( void *pvParameters )
+{
+/* The queue handle is passed in as the task parameter. This is one method of
+passing data into a protected task, the other reg test task uses a different
+method. */
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
+
+ for( ;; )
+ {
+ /* This task tests the kernel context switch mechanism by reading and
+ writing directly to registers - which requires the test to be written
+ in assembly code. */
+ __asm volatile
+ (
+ " MOV R4, #4 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */
+ " MOV R5, #5 \n"
+ " MOV R6, #6 \n"
+ " MOV R8, #8 \n" /* Frame pointer is omitted as it must not be changed. */
+ " MOV R9, #9 \n"
+ " MOV R10, 10 \n"
+ " MOV R11, #11 \n"
+ "reg2loop: \n"
+ " MOV R0, #13 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */
+ " MOV R1, #1 \n"
+ " MOV R2, #2 \n"
+ " MOV R3, #3 \n"
+ " MOV R12, #12 \n"
+ " CMP R0, #13 \n" /* Check all the registers still contain their expected values. */
+ " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task */
+ " CMP R1, #1 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R2, #2 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R3, #3 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R4, #4 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R5, #5 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R6, #6 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R8, #8 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R9, #9 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R10, #10 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R11, #11 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R12, #12 \n"
+ " BNE vMainDeleteMe \n"
+ :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+
+ /* Send configREG_TEST_2_STILL_EXECUTING to the check task to indicate that this
+ task is still functioning. */
+ vMainSendImAlive( xQueue, configREG_TEST_2_STILL_EXECUTING );
+
+ /* Go back to check all the register values again. */
+ __asm volatile( " B reg2loop " );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vRegTest3Implementation( void )
+{
+ __asm volatile
+ (
+ ".extern pulRegTest3LoopCounter \n"
+ "/* Fill the core registers with known values. */ \n"
+ "mov r0, #100 \n"
+ "mov r1, #101 \n"
+ "mov r2, #102 \n"
+ "mov r3, #103 \n"
+ "mov r4, #104 \n"
+ "mov r5, #105 \n"
+ "mov r6, #106 \n"
+ "mov r7, #107 \n"
+ "mov r8, #108 \n"
+ "mov r9, #109 \n"
+ "mov r10, #110 \n"
+ "mov r11, #111 \n"
+ "mov r12, #112 \n"
+
+ "/* Fill the VFP registers with known values. */ \n"
+ "vmov d0, r0, r1 \n"
+ "vmov d1, r2, r3 \n"
+ "vmov d2, r4, r5 \n"
+ "vmov d3, r6, r7 \n"
+ "vmov d4, r8, r9 \n"
+ "vmov d5, r10, r11 \n"
+ "vmov d6, r0, r1 \n"
+ "vmov d7, r2, r3 \n"
+ "vmov d8, r4, r5 \n"
+ "vmov d9, r6, r7 \n"
+ "vmov d10, r8, r9 \n"
+ "vmov d11, r10, r11 \n"
+ "vmov d12, r0, r1 \n"
+ "vmov d13, r2, r3 \n"
+ "vmov d14, r4, r5 \n"
+ "vmov d15, r6, r7 \n"
+
+ "reg1_loop: \n"
+ "/* Check all the VFP registers still contain the values set above. \n"
+ "First save registers that are clobbered by the test. */ \n"
+ "push { r0-r1 } \n"
+
+ "vmov r0, r1, d0 \n"
+ "cmp r0, #100 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #101 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d1 \n"
+ "cmp r0, #102 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #103 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d2 \n"
+ "cmp r0, #104 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #105 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d3 \n"
+ "cmp r0, #106 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #107 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d4 \n"
+ "cmp r0, #108 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #109 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d5 \n"
+ "cmp r0, #110 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #111 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d6 \n"
+ "cmp r0, #100 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #101 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d7 \n"
+ "cmp r0, #102 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #103 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d8 \n"
+ "cmp r0, #104 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #105 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d9 \n"
+ "cmp r0, #106 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #107 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d10 \n"
+ "cmp r0, #108 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #109 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d11 \n"
+ "cmp r0, #110 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #111 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d12 \n"
+ "cmp r0, #100 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #101 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d13 \n"
+ "cmp r0, #102 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #103 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d14 \n"
+ "cmp r0, #104 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #105 \n"
+ "bne reg1_error_loopf \n"
+ "vmov r0, r1, d15 \n"
+ "cmp r0, #106 \n"
+ "bne reg1_error_loopf \n"
+ "cmp r1, #107 \n"
+ "bne reg1_error_loopf \n"
+
+ "/* Restore the registers that were clobbered by the test. */ \n"
+ "pop {r0-r1} \n"
+
+ "/* VFP register test passed. Jump to the core register test. */ \n"
+ "b reg1_loopf_pass \n"
+
+ "reg1_error_loopf: \n"
+ "/* If this line is hit then a VFP register value was found to be incorrect. */ \n"
+ "b reg1_error_loopf \n"
+
+ "reg1_loopf_pass: \n"
+
+ "cmp r0, #100 \n"
+ "bne reg1_error_loop \n"
+ "cmp r1, #101 \n"
+ "bne reg1_error_loop \n"
+ "cmp r2, #102 \n"
+ "bne reg1_error_loop \n"
+ "cmp r3, #103 \n"
+ "bne reg1_error_loop \n"
+ "cmp r4, #104 \n"
+ "bne reg1_error_loop \n"
+ "cmp r5, #105 \n"
+ "bne reg1_error_loop \n"
+ "cmp r6, #106 \n"
+ "bne reg1_error_loop \n"
+ "cmp r7, #107 \n"
+ "bne reg1_error_loop \n"
+ "cmp r8, #108 \n"
+ "bne reg1_error_loop \n"
+ "cmp r9, #109 \n"
+ "bne reg1_error_loop \n"
+ "cmp r10, #110 \n"
+ "bne reg1_error_loop \n"
+ "cmp r11, #111 \n"
+ "bne reg1_error_loop \n"
+ "cmp r12, #112 \n"
+ "bne reg1_error_loop \n"
+
+ "/* Everything passed, increment the loop counter. */ \n"
+ "push { r0-r1 } \n"
+ "ldr r0, =pulRegTest3LoopCounter \n"
+ "ldr r0, [r0] \n"
+ "ldr r1, [r0] \n"
+ "adds r1, r1, #1 \n"
+ "str r1, [r0] \n"
+ "pop { r0-r1 } \n"
+
+ "/* Start again. */ \n"
+ "b reg1_loop \n"
+
+ "reg1_error_loop: \n"
+ "/* If this line is hit then there was an error in a core register value. \n"
+ "The loop ensures the loop counter stops incrementing. */ \n"
+ "b reg1_error_loop \n"
+ "nop "
+ ); /* __asm volatile. */
+}
+/*-----------------------------------------------------------*/
+
+void vRegTest4Implementation( void )
+{
+ __asm volatile
+ (
+ ".extern pulRegTest4LoopCounter \n"
+ "/* Set all the core registers to known values. */ \n"
+ "mov r0, #-1 \n"
+ "mov r1, #1 \n"
+ "mov r2, #2 \n"
+ "mov r3, #3 \n"
+ "mov r4, #4 \n"
+ "mov r5, #5 \n"
+ "mov r6, #6 \n"
+ "mov r7, #7 \n"
+ "mov r8, #8 \n"
+ "mov r9, #9 \n"
+ "mov r10, #10 \n"
+ "mov r11, #11 \n"
+ "mov r12, #12 \n"
+
+ "/* Set all the VFP to known values. */ \n"
+ "vmov d0, r0, r1 \n"
+ "vmov d1, r2, r3 \n"
+ "vmov d2, r4, r5 \n"
+ "vmov d3, r6, r7 \n"
+ "vmov d4, r8, r9 \n"
+ "vmov d5, r10, r11 \n"
+ "vmov d6, r0, r1 \n"
+ "vmov d7, r2, r3 \n"
+ "vmov d8, r4, r5 \n"
+ "vmov d9, r6, r7 \n"
+ "vmov d10, r8, r9 \n"
+ "vmov d11, r10, r11 \n"
+ "vmov d12, r0, r1 \n"
+ "vmov d13, r2, r3 \n"
+ "vmov d14, r4, r5 \n"
+ "vmov d15, r6, r7 \n"
+
+ "reg2_loop: \n"
+
+ "/* Check all the VFP registers still contain the values set above. \n"
+ "First save registers that are clobbered by the test. */ \n"
+ "push { r0-r1 } \n"
+
+ "vmov r0, r1, d0 \n"
+ "cmp r0, #-1 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #1 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d1 \n"
+ "cmp r0, #2 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #3 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d2 \n"
+ "cmp r0, #4 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #5 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d3 \n"
+ "cmp r0, #6 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #7 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d4 \n"
+ "cmp r0, #8 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #9 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d5 \n"
+ "cmp r0, #10 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #11 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d6 \n"
+ "cmp r0, #-1 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #1 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d7 \n"
+ "cmp r0, #2 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #3 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d8 \n"
+ "cmp r0, #4 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #5 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d9 \n"
+ "cmp r0, #6 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #7 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d10 \n"
+ "cmp r0, #8 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #9 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d11 \n"
+ "cmp r0, #10 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #11 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d12 \n"
+ "cmp r0, #-1 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #1 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d13 \n"
+ "cmp r0, #2 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #3 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d14 \n"
+ "cmp r0, #4 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #5 \n"
+ "bne reg2_error_loopf \n"
+ "vmov r0, r1, d15 \n"
+ "cmp r0, #6 \n"
+ "bne reg2_error_loopf \n"
+ "cmp r1, #7 \n"
+ "bne reg2_error_loopf \n"
+
+ "/* Restore the registers that were clobbered by the test. */ \n"
+ "pop {r0-r1} \n"
+
+ "/* VFP register test passed. Jump to the core register test. */ \n"
+ "b reg2_loopf_pass \n"
+
+ "reg2_error_loopf: \n"
+ "/* If this line is hit then a VFP register value was found to be \n"
+ "incorrect. */ \n"
+ "b reg2_error_loopf \n"
+
+ "reg2_loopf_pass: \n"
+
+ "cmp r0, #-1 \n"
+ "bne reg2_error_loop \n"
+ "cmp r1, #1 \n"
+ "bne reg2_error_loop \n"
+ "cmp r2, #2 \n"
+ "bne reg2_error_loop \n"
+ "cmp r3, #3 \n"
+ "bne reg2_error_loop \n"
+ "cmp r4, #4 \n"
+ "bne reg2_error_loop \n"
+ "cmp r5, #5 \n"
+ "bne reg2_error_loop \n"
+ "cmp r6, #6 \n"
+ "bne reg2_error_loop \n"
+ "cmp r7, #7 \n"
+ "bne reg2_error_loop \n"
+ "cmp r8, #8 \n"
+ "bne reg2_error_loop \n"
+ "cmp r9, #9 \n"
+ "bne reg2_error_loop \n"
+ "cmp r10, #10 \n"
+ "bne reg2_error_loop \n"
+ "cmp r11, #11 \n"
+ "bne reg2_error_loop \n"
+ "cmp r12, #12 \n"
+ "bne reg2_error_loop \n"
+
+ "/* Increment the loop counter so the check task knows this task is \n"
+ "still running. */ \n"
+ "push { r0-r1 } \n"
+ "ldr r0, =pulRegTest4LoopCounter \n"
+ "ldr r0, [r0] \n"
+ "ldr r1, [r0] \n"
+ "adds r1, r1, #1 \n"
+ "str r1, [r0] \n"
+ "pop { r0-r1 } \n"
+
+ "/* Yield to increase test coverage. */ \n"
+ "SVC #1 \n"
+
+ "/* Start again. */ \n"
+ "b reg2_loop \n"
+
+ "reg2_error_loop: \n"
+ "/* If this line is hit then there was an error in a core register value. \n"
+ "This loop ensures the loop counter variable stops incrementing. */ \n"
+ "b reg2_error_loop \n"
+ ); /* __asm volatile */
+}
+/*-----------------------------------------------------------*/
+
+/* Fault handlers are here for convenience as they use compiler specific syntax
+and this file is specific to the GCC compiler. */
+void hard_fault_handler( uint32_t * hardfault_args )
+{
+volatile uint32_t stacked_r0;
+volatile uint32_t stacked_r1;
+volatile uint32_t stacked_r2;
+volatile uint32_t stacked_r3;
+volatile uint32_t stacked_r12;
+volatile uint32_t stacked_lr;
+volatile uint32_t stacked_pc;
+volatile uint32_t stacked_psr;
+
+ stacked_r0 = ((uint32_t) hardfault_args[ 0 ]);
+ stacked_r1 = ((uint32_t) hardfault_args[ 1 ]);
+ stacked_r2 = ((uint32_t) hardfault_args[ 2 ]);
+ stacked_r3 = ((uint32_t) hardfault_args[ 3 ]);
+
+ stacked_r12 = ((uint32_t) hardfault_args[ 4 ]);
+ stacked_lr = ((uint32_t) hardfault_args[ 5 ]);
+ stacked_pc = ((uint32_t) hardfault_args[ 6 ]);
+ stacked_psr = ((uint32_t) hardfault_args[ 7 ]);
+
+ /* Inspect stacked_pc to locate the offending instruction. */
+ for( ;; );
+
+ ( void ) stacked_psr;
+ ( void ) stacked_pc;
+ ( void ) stacked_lr;
+ ( void ) stacked_r12;
+ ( void ) stacked_r0;
+ ( void ) stacked_r1;
+ ( void ) stacked_r2;
+ ( void ) stacked_r3;
+}
+/*-----------------------------------------------------------*/
+
+void HardFault_Handler( void ) __attribute__((naked));
+void HardFault_Handler( void )
+{
+ __asm volatile
+ (
+ " tst lr, #4 \n"
+ " ite eq \n"
+ " mrseq r0, msp \n"
+ " mrsne r0, psp \n"
+ " ldr r1, [r0, #24] \n"
+ " ldr r2, handler_address_const \n"
+ " bx r2 \n"
+ " handler_address_const: .word hard_fault_handler \n"
+ );
+}
+/*-----------------------------------------------------------*/
+
+void MemManage_Handler( void ) __attribute__((naked));
+void MemManage_Handler( void )
+{
+ __asm volatile
+ (
+ " tst lr, #4 \n"
+ " ite eq \n"
+ " mrseq r0, msp \n"
+ " mrsne r0, psp \n"
+ " ldr r1, [r0, #24] \n"
+ " ldr r2, handler2_address_const \n"
+ " bx r2 \n"
+ " handler2_address_const: .word hard_fault_handler \n"
+ );
+}/*-----------------------------------------------------------*/
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld
new file mode 100644
index 000000000..5ba471449
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld
@@ -0,0 +1,356 @@
+/* Default memory layout. */
+MEMORY
+{
+ ROM (rx) : ORIGIN = 0x00, LENGTH = 0x80000
+ RAM (rw) : ORIGIN = 0x20000000, LENGTH = 0x8000
+}
+
+/* Variables used by FreeRTOS-MPU. */
+_Privileged_Functions_Region_Size = 32K;
+_Privileged_Data_Region_Size = 2048;
+
+__FLASH_segment_start__ = ORIGIN( ROM );
+__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( ROM );
+
+__privileged_functions_start__ = ORIGIN( ROM );
+__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
+
+__SRAM_segment_start__ = ORIGIN( RAM );
+__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( RAM );
+
+__privileged_data_start__ = ORIGIN( RAM );
+__privileged_data_end__ = ORIGIN( RAM ) + _Privileged_Data_Region_Size;
+
+
+/*
+ * The '__stack' definition is required by crt0, do not remove it.
+ */
+__stack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = __stack;
+
+/*
+ * Default stack sizes.
+ * These are used by the startup in order to allocate stacks
+ * for the different modes.
+ */
+
+__Main_Stack_Size = 2048 ;
+
+PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
+
+__Main_Stack_Limit = __stack - __Main_Stack_Size ;
+
+/*"PROVIDE" allows to easily override these values from an object file or the command line. */
+PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;
+
+/*
+ * There will be a link error if there is not this amount of
+ * RAM free at the end.
+ */
+_Minimum_Stack_Size = 1024 ;
+
+/*
+ * Default heap definitions.
+ * The heap start immediately after the last statically allocated
+ * .sbss/.noinit section, and extends up to the main stack limit.
+ */
+PROVIDE ( _Heap_Begin = _end_noinit ) ;
+PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;
+
+/*
+ * The entry point is informative, for debuggers and simulators,
+ * since the Cortex-M vector points to it anyway.
+ */
+ENTRY(_start)
+
+/* Sections Definitions */
+
+SECTIONS
+{
+ /*
+ * For Cortex-M devices, the beginning of the startup code is stored in
+ * the .isr_vector section, which goes to ROM
+ */
+ privileged_functions :
+ {
+ . = ALIGN(4);
+ _isr_vector = .;
+ KEEP(*(.isr_vector))
+ *(privileged_functions)
+ . = ALIGN(4);
+
+ /* Non privileged code is after _Privileged_Functions_Region_Size. */
+ __privileged_functions_actual_end__ = .;
+ . = _Privileged_Functions_Region_Size;
+ } > ROM
+
+
+
+ .text :
+ {
+ . = ALIGN(4);
+
+
+ /*
+ * This section is here for convenience, to store the
+ * startup code at the beginning of the flash area, hoping that
+ * this will increase the readability of the listing.
+ */
+ KEEP(*(.after_vectors .after_vectors.*)) /* Startup code and ISR */
+
+ . = ALIGN(4);
+
+ /*
+ * These are the old initialisation sections, intended to contain
+ * naked code, with the prologue/epilogue added by crti.o/crtn.o
+ * when linking with startup files. The standalone startup code
+ * currently does not run these, better use the init arrays below.
+ */
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ . = ALIGN(4);
+
+ /*
+ * The preinit code, i.e. an array of pointers to initialisation
+ * functions to be performed before constructors.
+ */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+
+ /*
+ * Used to run the SystemInit() before anything else.
+ */
+ KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
+
+ /*
+ * Used for other platform inits.
+ */
+ KEEP(*(.preinit_array_platform .preinit_array_platform.*))
+
+ /*
+ * The application inits. If you need to enforce some order in
+ * execution, create new sections, as before.
+ */
+ KEEP(*(.preinit_array .preinit_array.*))
+
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+
+ /*
+ * The init code, i.e. an array of pointers to static constructors.
+ */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+ . = ALIGN(4);
+
+ /*
+ * The fini code, i.e. an array of pointers to static destructors.
+ */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(4);
+
+ . = ALIGN(4);
+
+ *(.text*) /* all remaining code */
+
+ *(vtable) /* C++ virtual tables */
+
+ } >ROM
+
+ .rodata :
+ {
+ *(.rodata*) /* read-only data (constants) */
+ } >ROM
+
+ .glue :
+ {
+ KEEP(*(.eh_frame*))
+
+ /*
+ * Stub sections generated by the linker, to glue together
+ * ARM and Thumb code. .glue_7 is used for ARM code calling
+ * Thumb code, and .glue_7t is used for Thumb code calling
+ * ARM code. Apparently always generated by the linker, for some
+ * architectures, so better leave them here.
+ */
+ *(.glue_7)
+ *(.glue_7t)
+ } >ROM
+
+ /* ARM magic sections */
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > ROM
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > ROM
+ __exidx_end = .;
+
+ . = ALIGN(4);
+ _etext = .;
+ __etext = .;
+
+ /*
+ * This address is used by the startup code to
+ * initialise the .data section.
+ */
+ _sidata = _etext;
+
+ /* MEMORY_ARRAY */
+ /*
+ .ROarraySection :
+ {
+ *(.ROarraySection .ROarraySection.*)
+ } >MEMORY_ARRAY
+ */
+
+
+ privileged_data :
+ {
+ *(privileged_data)
+ /* Non kernel data is kept out of the first _Privileged_Data_Region_Size
+ bytes of SRAM. */
+ __privileged_data_actual_end__ = .;
+ . = _Privileged_Data_Region_Size;
+ } > RAM
+
+ /*
+ * The initialised data section.
+ * The program executes knowing that the data is in the RAM
+ * but the loader puts the initial values in the ROM (inidata).
+ * It is one task of the startup to copy the initial values from
+ * ROM to RAM.
+ */
+ .data : AT ( _sidata )
+ {
+ . = ALIGN(4);
+
+ /* This is used by the startup code to initialise the .data section */
+ _sdata = . ; /* STM specific definition */
+ __data_start__ = . ;
+ *(.data_begin .data_begin.*)
+
+ *(.data .data.*)
+
+ *(.data_end .data_end.*)
+ . = ALIGN(4);
+
+ /* This is used by the startup code to initialise the .data section */
+ _edata = . ; /* STM specific definition */
+ __data_end__ = . ;
+
+ } >RAM
+
+
+ /*
+ * The uninitialised data section. NOLOAD is used to avoid
+ * the "section `.bss' type changed to PROGBITS" warning
+ */
+ .bss (NOLOAD) :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .; /* standard newlib definition */
+ _sbss = .; /* STM specific definition */
+ *(.bss_begin .bss_begin.*)
+
+ *(.bss .bss.*)
+ *(COMMON)
+
+ *(.bss_end .bss_end.*)
+ . = ALIGN(4);
+ __bss_end__ = .; /* standard newlib definition */
+ _ebss = . ; /* STM specific definition */
+ } >RAM
+
+ .noinit (NOLOAD) :
+ {
+ . = ALIGN(4);
+ _noinit = .;
+
+ *(.noinit .noinit.*)
+
+ . = ALIGN(4) ;
+ _end_noinit = .;
+ } > RAM
+
+ /* Mandatory to be word aligned, _sbrk assumes this */
+ PROVIDE ( end = _end_noinit ); /* was _ebss */
+ PROVIDE ( _end = _end_noinit );
+ PROVIDE ( __end = _end_noinit );
+ PROVIDE ( __end__ = _end_noinit );
+ PROVIDE ( ROM_DATA_START = __data_start__ );
+
+ /*
+ * Used for validation only, do not allocate anything here!
+ *
+ * This is just to check that there is enough RAM left for the Main
+ * stack. It should generate an error if it's full.
+ */
+ ._check_stack :
+ {
+ . = ALIGN(4);
+
+ . = . + _Minimum_Stack_Size ;
+
+ . = ALIGN(4);
+ } >RAM
+
+ /* After that there are only debugging sections. */
+
+ /* This can remove the debugging information from the standard libraries */
+ /*
+ DISCARD :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }
+ */
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /*
+ * DWARF debug sections.
+ * Symbols in the DWARF debugging sections are relative to the beginning
+ * of the section so we begin them at 0.
+ */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+}
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S
new file mode 100644
index 000000000..fb2af495a
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S
@@ -0,0 +1,217 @@
+/* File: startup_ARMCM4.S
+ * Purpose: startup file for Cortex-M4 devices. Should use with
+ * GCC for ARM Embedded Processors
+ * Version: V2.0
+ * Date: 16 August 2013
+ *
+/* Copyright (c) 2011 - 2013 ARM LIMITED
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ - Neither the name of ARM nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+ *
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ ---------------------------------------------------------------------------*/
+ .syntax unified
+ .arch armv7e-m
+
+ .extern __SRAM_segment_end__
+
+ .section .isr_vector
+ .align 4
+ .globl __isr_vector
+__isr_vector:
+ .long __SRAM_segment_end__ - 4 /* Top of Stack at top of RAM*/
+ .long Reset_Handler /* Reset Handler */
+ .long NMI_Handler /* NMI Handler */
+ .long HardFault_Handler /* Hard Fault Handler */
+ .long MemManage_Handler /* MPU Fault Handler */
+ .long BusFault_Handler /* Bus Fault Handler */
+ .long UsageFault_Handler /* Usage Fault Handler */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long 0 /* Reserved */
+ .long SVC_Handler /* SVCall Handler */
+ .long DebugMon_Handler /* Debug Monitor Handler */
+ .long 0 /* Reserved */
+ .long PendSV_Handler /* PendSV Handler */
+ .long SysTick_Handler /* SysTick Handler */
+
+ /* External interrupts */
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+ .long DummyHandler
+
+
+ .text
+ .thumb
+ .thumb_func
+ .align 2
+ .globl _start
+ .extern main
+ .globl Reset_Handler
+ .type Reset_Handler, %function
+_start:
+Reset_Handler:
+/* Firstly it copies data from read only memory to RAM. There are two schemes
+ * to copy. One can copy more than one sections. Another can only copy
+ * one section. The former scheme needs more instructions and read-only
+ * data to implement than the latter.
+ * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
+
+/* Single section scheme.
+ *
+ * The ranges of copy from/to are specified by following symbols
+ * __etext: LMA of start of the section to copy from. Usually end of text
+ * __data_start__: VMA of start of the section to copy to
+ * __data_end__: VMA of end of the section to copy to
+ *
+ * All addresses must be aligned to 4 bytes boundary.
+ */
+ ldr r1, =__etext
+ ldr r2, =__data_start__
+ ldr r3, =__data_end__
+
+.L_loop1:
+ cmp r2, r3
+ ittt lt
+ ldrlt r0, [r1], #4
+ strlt r0, [r2], #4
+ blt .L_loop1
+
+/* This part of work usually is done in C library startup code. Otherwise,
+ * define this macro to enable it in this startup.
+ *
+ * There are two schemes too. One can clear multiple BSS sections. Another
+ * can only clear one section. The former is more size expensive than the
+ * latter.
+ *
+ * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
+ * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
+ */
+
+ /* Single BSS section scheme.
+ *
+ * The BSS section is specified by following symbols
+ * __bss_start__: start of the BSS section.
+ * __bss_end__: end of the BSS section.
+ *
+ * Both addresses must be aligned to 4 bytes boundary.
+ */
+ ldr r1, =__bss_start__
+ ldr r2, =__bss_end__
+
+ movs r0, 0
+.L_loop3:
+ cmp r1, r2
+ itt lt
+ strlt r0, [r1], #4
+ blt .L_loop3
+
+#ifndef __NO_SYSTEM_INIT
+/* bl SystemInit */
+#endif
+
+ bl main
+
+ .pool
+ .size Reset_Handler, . - Reset_Handler
+
+ .align 1
+ .thumb_func
+ .weak Default_Handler
+ .type Default_Handler, %function
+Default_Handler:
+ b .
+ .size Default_Handler, . - Default_Handler
+
+/* Macro to define default handlers. Default handler
+ * will be weak symbol and just dead loops. They can be
+ * overwritten by other handlers */
+ .macro def_irq_handler handler_name
+ .weak \handler_name
+ .set \handler_name, Default_Handler
+ .endm
+
+ def_irq_handler NMI_Handler
+ def_irq_handler HardFault_Handler
+ def_irq_handler MemManage_Handler
+ def_irq_handler BusFault_Handler
+ def_irq_handler UsageFault_Handler
+ def_irq_handler SVC_Handler
+ def_irq_handler DebugMon_Handler
+ def_irq_handler PendSV_Handler
+ def_irq_handler SysTick_Handler
+ def_irq_handler DEF_IRQHandler
+ def_irq_handler DummyHandler
+
+
+ .end
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct
new file mode 100644
index 000000000..ee30fbd50
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct
@@ -0,0 +1,23 @@
+; *************************************************************
+; *** Scatter-Loading Description File generated by uVision ***
+; *************************************************************
+
+
+LR_IROM1 0x00000000 { ; load region size_region
+ ER_IROM1 0x00000000 { ; load address = execution address
+ *.o (RESET, +First)
+ *(InRoot$$Sections)
+ *( privileged_functions )
+ }
+ ER_IROM2 0x8000 FIXED {
+ .ANY (+RO)
+ }
+ RW_IRAM1 0x20000000 { ; RW data
+ *( privileged_data )
+ }
+ RW_IRAM2 0x20000800 { ; RW data
+ .ANY (+RW +ZI)
+ }
+}
+
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx
new file mode 100644
index 000000000..58cf95293
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx
@@ -0,0 +1,358 @@
+
+
+
+ 1.0
+
+ ### uVision Project, (C) Keil Software
+
+
+ *.c
+ *.s*; *.src; *.a*
+ *.obj
+ *.lib
+ *.txt; *.h; *.inc
+ *.plm
+ *.cpp
+ 0
+
+
+
+ 0
+ 0
+
+
+
+ RTOSDemo
+ 0x4
+ ARM-ADS
+
+ 48000000
+
+ 1
+ 1
+ 0
+ 1
+ 0
+
+
+ 1
+ 65535
+ 0
+ 0
+ 0
+
+
+ 79
+ 66
+ 8
+ .\Listings\
+
+
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+ 7
+
+ 1
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+ BIN\UL2CM3.DLL
+
+
+
+ 0
+ DLGDARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)
+
+
+ 0
+ DLGUARM
+ (105=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMRTXEVENTFLAGS
+ -L70 -Z18 -C0 -M0 -T1
+
+
+ 0
+ DLGTARM
+ (1010=1231,224,1641,767,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=1199,245,1664,545,0)
+
+
+ 0
+ ARMDBGFLAGS
+ -T0
+
+
+ 0
+ UL2CM3
+ -UV1115SAE -O3047 -S0 -C0 -P00 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO19 -TC48000000 -TP21 -TDS8028 -TDT0 -TDC1F -TIE1 -TIP8 -FO11 -FD118000 -FC8000 -FN1 -FF0NEW_DEVICE.FLM -FS0E0000 -FL038000 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM)
+
+
+
+
+
+ 0
+ 1
+ ulCycleCount
+
+
+
+
+ 1
+ 2
+ 0xe000e284
+ 4
+
+
+
+ 0
+
+
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+ System
+ 1
+ 0
+ 0
+ 0
+
+ 1
+ 1
+ 2
+ 0
+ 0
+ 0
+ .\startup_MPS_CM4.S
+ startup_MPS_CM4.S
+ 0
+ 0
+
+
+
+
+ main_and_config
+ 1
+ 0
+ 0
+ 0
+
+ 2
+ 2
+ 1
+ 0
+ 0
+ 0
+ ..\main.c
+ main.c
+ 0
+ 0
+
+
+ 2
+ 3
+ 5
+ 0
+ 0
+ 0
+ ..\FreeRTOSConfig.h
+ FreeRTOSConfig.h
+ 0
+ 0
+
+
+ 2
+ 4
+ 1
+ 0
+ 0
+ 0
+ .\RegTest.c
+ RegTest.c
+ 0
+ 0
+
+
+
+
+ FreeRTOS_Source
+ 1
+ 0
+ 0
+ 0
+
+ 3
+ 5
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\event_groups.c
+ event_groups.c
+ 0
+ 0
+
+
+ 3
+ 6
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\list.c
+ list.c
+ 0
+ 0
+
+
+ 3
+ 7
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\queue.c
+ queue.c
+ 0
+ 0
+
+
+ 3
+ 8
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\tasks.c
+ tasks.c
+ 0
+ 0
+
+
+ 3
+ 9
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\timers.c
+ timers.c
+ 0
+ 0
+
+
+ 3
+ 10
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\portable\RVDS\ARM_CM4_MPU\port.c
+ port.c
+ 0
+ 0
+
+
+ 3
+ 11
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\Source\portable\Common\mpu_wrappers.c
+ mpu_wrappers.c
+ 0
+ 0
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx
new file mode 100644
index 000000000..3a254da24
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx
@@ -0,0 +1,451 @@
+
+
+
+ 2.1
+
+ ### uVision Project, (C) Keil Software
+
+
+
+ RTOSDemo
+ 0x4
+ ARM-ADS
+ 5060183::V5.06 update 2 (build 183)::ARMCC
+
+
+ ARMCM4_FP
+ ARM
+ ARM.CMSIS.5.0.0-Beta4
+ http://www.keil.com/pack/
+ IROM(0x00000000,0x80000) IRAM(0x20000000,0x20000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ESEL ELITTLE
+
+
+ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0NEW_DEVICE -FS00 -FL080000 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM))
+ 0
+ $$Device:ARMCM4_FP$Device\ARM\ARMCM4\Include\ARMCM4_FP.h
+
+
+
+
+
+
+
+
+
+ $$Device:ARMCM4_FP$Device\ARM\SVD\ARMCM4.svd
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+
+ .\Objects\
+ RTOSDemo
+ 1
+ 0
+ 1
+ 1
+ 1
+ .\Listings\
+ 1
+ 0
+ 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 3
+
+
+ 1
+
+
+ SARMCM3.DLL
+ -MPU
+ DCM.DLL
+ -pCM4
+ SARMCM3.DLL
+ -MPU
+ TCM.DLL
+ -pCM4
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 16
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4096
+
+ 1
+ BIN\UL2CM3.DLL
+ "" ()
+
+
+
+
+ 0
+
+
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ "Cortex-M4"
+
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 0
+ 2
+ 0
+ 0
+ 8
+ 1
+ 1
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x20000
+
+
+ 1
+ 0x0
+ 0x80000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x80000
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x8000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+
+
+
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 2
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+ ..;..\..\..\Source\include;..\..\..\Source\portable\RVDS\ARM_CM4_MPU;..\..\Common\include;..\CMSIS;..\main_full
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0x00000000
+ 0x20000000
+
+ RTOSDemo.sct
+
+
+
+
+
+
+
+
+
+
+ System
+
+
+ startup_MPS_CM4.S
+ 2
+ .\startup_MPS_CM4.S
+
+
+
+
+ main_and_config
+
+
+ main.c
+ 1
+ ..\main.c
+
+
+ FreeRTOSConfig.h
+ 5
+ ..\FreeRTOSConfig.h
+
+
+ RegTest.c
+ 1
+ .\RegTest.c
+
+
+
+
+ FreeRTOS_Source
+
+
+ event_groups.c
+ 1
+ ..\..\..\Source\event_groups.c
+
+
+ list.c
+ 1
+ ..\..\..\Source\list.c
+
+
+ queue.c
+ 1
+ ..\..\..\Source\queue.c
+
+
+ tasks.c
+ 1
+ ..\..\..\Source\tasks.c
+
+
+ timers.c
+ 1
+ ..\..\..\Source\timers.c
+
+
+ port.c
+ 1
+ ..\..\..\Source\portable\RVDS\ARM_CM4_MPU\port.c
+
+
+ mpu_wrappers.c
+ 1
+ ..\..\..\Source\portable\Common\mpu_wrappers.c
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c
new file mode 100644
index 000000000..90e1625c5
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c
@@ -0,0 +1,703 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "task.h"
+
+/*
+ * "Reg test" tasks - These fill the 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.
+ */
+
+void vRegTest1Implementation( void *pvParameters );
+void vRegTest2Implementation( void *pvParameters );
+void vRegTest3Implementation( void );
+void vRegTest4Implementation( void );
+
+/*
+ * Used as an easy way of deleting a task from inline assembly.
+ */
+extern void vMainDeleteMe( void ) __attribute__((noinline));
+
+/*
+ * Used by the first two reg test tasks and a software timer callback function
+ * to send messages to the check task. The message just lets the check task
+ * know that the tasks and timer are still functioning correctly. If a reg test
+ * task detects an error it will delete itself, and in so doing prevent itself
+ * from sending any more 'I'm Alive' messages to the check task.
+ */
+extern void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber );
+
+/* The queue used to send a message to the check task. */
+extern QueueHandle_t xGlobalScopeCheckQueue;
+
+/*-----------------------------------------------------------*/
+
+void vRegTest1Implementation( void *pvParameters )
+{
+/* This task is created in privileged mode so can access the file scope
+queue variable. Take a stack copy of this before the task is set into user
+mode. Once this task is in user mode the file scope queue variable will no
+longer be accessible but the stack copy will. */
+QueueHandle_t xQueue = xGlobalScopeCheckQueue;
+const TickType_t xDelayTime = pdMS_TO_TICKS( 100UL );
+
+ /* Now the queue handle has been obtained the task can switch to user
+ mode. This is just one method of passing a handle into a protected
+ task, the other reg test task uses the task parameter instead. */
+ portSWITCH_TO_USER_MODE();
+
+ /* First check that the parameter value is as expected. */
+ if( pvParameters != ( void * ) configREG_TEST_TASK_1_PARAMETER )
+ {
+ /* Error detected. Delete the task so it stops communicating with
+ the check task. */
+ vMainDeleteMe();
+ }
+
+ for( ;; )
+ {
+ #if defined ( __GNUC__ )
+ {
+ /* This task tests the kernel context switch mechanism by reading and
+ writing directly to registers - which requires the test to be written
+ in assembly code. */
+ __asm volatile
+ (
+ " MOV R4, #104 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */
+ " MOV R5, #105 \n"
+ " MOV R6, #106 \n"
+ " MOV R8, #108 \n"
+ " MOV R9, #109 \n"
+ " MOV R10, #110 \n"
+ " MOV R11, #111 \n"
+ "reg1loop: \n"
+ " MOV R0, #100 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */
+ " MOV R1, #101 \n"
+ " MOV R2, #102 \n"
+ " MOV R3, #103 \n"
+ " MOV R12, #112 \n"
+ " SVC #1 \n" /* Yield just to increase test coverage. */
+ " CMP R0, #100 \n" /* Check all the registers still contain their expected values. */
+ " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */
+ " CMP R1, #101 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R2, #102 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R3, #103 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R4, #104 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R5, #105 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R6, #106 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R8, #108 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R9, #109 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R10, #110 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R11, #111 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R12, #112 \n"
+ " BNE vMainDeleteMe \n"
+ :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+ }
+ #endif /* __GNUC__ */
+
+ /* Send configREG_TEST_1_STILL_EXECUTING to the check task to indicate that this
+ task is still functioning. */
+ vMainSendImAlive( xQueue, configREG_TEST_1_STILL_EXECUTING );
+ vTaskDelay( xDelayTime );
+
+ #if defined ( __GNUC__ )
+ {
+ /* Go back to check all the register values again. */
+ __asm volatile( " B reg1loop " );
+ }
+ #endif /* __GNUC__ */
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vRegTest2Implementation( void *pvParameters )
+{
+/* The queue handle is passed in as the task parameter. This is one method of
+passing data into a protected task, the other reg test task uses a different
+method. */
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;
+const TickType_t xDelayTime = pdMS_TO_TICKS( 100UL );
+
+ for( ;; )
+ {
+ #if defined ( __GNUC__ )
+ {
+ /* This task tests the kernel context switch mechanism by reading and
+ writing directly to registers - which requires the test to be written
+ in assembly code. */
+ __asm volatile
+ (
+ " MOV R4, #4 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */
+ " MOV R5, #5 \n"
+ " MOV R6, #6 \n"
+ " MOV R8, #8 \n" /* Frame pointer is omitted as it must not be changed. */
+ " MOV R9, #9 \n"
+ " MOV R10, 10 \n"
+ " MOV R11, #11 \n"
+ "reg2loop: \n"
+ " MOV R0, #13 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */
+ " MOV R1, #1 \n"
+ " MOV R2, #2 \n"
+ " MOV R3, #3 \n"
+ " MOV R12, #12 \n"
+ " CMP R0, #13 \n" /* Check all the registers still contain their expected values. */
+ " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task */
+ " CMP R1, #1 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R2, #2 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R3, #3 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R4, #4 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R5, #5 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R6, #6 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R8, #8 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R9, #9 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R10, #10 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R11, #11 \n"
+ " BNE vMainDeleteMe \n"
+ " CMP R12, #12 \n"
+ " BNE vMainDeleteMe \n"
+ :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"
+ );
+ }
+ #endif /* __GNUC__ */
+
+ /* Send configREG_TEST_2_STILL_EXECUTING to the check task to indicate
+ that this task is still functioning. */
+ vMainSendImAlive( xQueue, configREG_TEST_2_STILL_EXECUTING );
+ vTaskDelay( xDelayTime );
+
+ #if defined ( __GNUC__ )
+ {
+ /* Go back to check all the register values again. */
+ __asm volatile( " B reg2loop " );
+ }
+ #endif /* __GNUC__ */
+ }
+}
+/*-----------------------------------------------------------*/
+
+__asm void vRegTest3Implementation( void )
+{
+ extern pulRegTest3LoopCounter
+
+ PRESERVE8
+
+ /* Fill the core registers with known values. */
+ mov r0, #100
+ mov r1, #101
+ mov r2, #102
+ mov r3, #103
+ mov r4, #104
+ mov r5, #105
+ mov r6, #106
+ mov r7, #107
+ mov r8, #108
+ mov r9, #109
+ mov r10, #110
+ mov r11, #111
+ mov r12, #112
+
+ /* Fill the VFP registers with known values. */
+ 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
+
+reg1_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, #100
+ bne reg1_error_loopf
+ cmp r1, #101
+ bne reg1_error_loopf
+ vmov r0, r1, d1
+ cmp r0, #102
+ bne reg1_error_loopf
+ cmp r1, #103
+ bne reg1_error_loopf
+ vmov r0, r1, d2
+ cmp r0, #104
+ bne reg1_error_loopf
+ cmp r1, #105
+ bne reg1_error_loopf
+ vmov r0, r1, d3
+ cmp r0, #106
+ bne reg1_error_loopf
+ cmp r1, #107
+ bne reg1_error_loopf
+ vmov r0, r1, d4
+ cmp r0, #108
+ bne reg1_error_loopf
+ cmp r1, #109
+ bne reg1_error_loopf
+ vmov r0, r1, d5
+ cmp r0, #110
+ bne reg1_error_loopf
+ cmp r1, #111
+ bne reg1_error_loopf
+ vmov r0, r1, d6
+ cmp r0, #100
+ bne reg1_error_loopf
+ cmp r1, #101
+ bne reg1_error_loopf
+ vmov r0, r1, d7
+ cmp r0, #102
+ bne reg1_error_loopf
+ cmp r1, #103
+ bne reg1_error_loopf
+ vmov r0, r1, d8
+ cmp r0, #104
+ bne reg1_error_loopf
+ cmp r1, #105
+ bne reg1_error_loopf
+ vmov r0, r1, d9
+ cmp r0, #106
+ bne reg1_error_loopf
+ cmp r1, #107
+ bne reg1_error_loopf
+ vmov r0, r1, d10
+ cmp r0, #108
+ bne reg1_error_loopf
+ cmp r1, #109
+ bne reg1_error_loopf
+ vmov r0, r1, d11
+ cmp r0, #110
+ bne reg1_error_loopf
+ cmp r1, #111
+ bne reg1_error_loopf
+ vmov r0, r1, d12
+ cmp r0, #100
+ bne reg1_error_loopf
+ cmp r1, #101
+ bne reg1_error_loopf
+ vmov r0, r1, d13
+ cmp r0, #102
+ bne reg1_error_loopf
+ cmp r1, #103
+ bne reg1_error_loopf
+ vmov r0, r1, d14
+ cmp r0, #104
+ bne reg1_error_loopf
+ cmp r1, #105
+ bne reg1_error_loopf
+ vmov r0, r1, d15
+ cmp r0, #106
+ bne reg1_error_loopf
+ cmp r1, #107
+ 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
+
+ cmp r0, #100
+ bne reg1_error_loop
+ cmp r1, #101
+ bne reg1_error_loop
+ cmp r2, #102
+ bne reg1_error_loop
+ cmp r3, #103
+ bne reg1_error_loop
+ cmp r4, #104
+ bne reg1_error_loop
+ cmp r5, #105
+ bne reg1_error_loop
+ cmp r6, #106
+ bne reg1_error_loop
+ cmp r7, #107
+ bne reg1_error_loop
+ cmp r8, #108
+ bne reg1_error_loop
+ cmp r9, #109
+ bne reg1_error_loop
+ cmp r10, #110
+ bne reg1_error_loop
+ cmp r11, #111
+ bne reg1_error_loop
+ cmp r12, #112
+ bne reg1_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ push { r0-r1 }
+ ldr r0, =pulRegTest3LoopCounter
+ ldr r0, [r0]
+ 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
+ nop
+}
+/*-----------------------------------------------------------*/
+
+__asm void vRegTest4Implementation( void )
+{
+ extern pulRegTest4LoopCounter;
+
+ PRESERVE8
+
+ /* Set all the core registers to known values. */
+ mov r0, #-1
+ mov r1, #1
+ mov r2, #2
+ mov r3, #3
+ mov r4, #4
+ mov r5, #5
+ mov r6, #6
+ mov r7, #7
+ mov r8, #8
+ mov r9, #9
+ mov r10, #10
+ mov r11, #11
+ mov r12, #12
+
+ /* Set all the VFP to known values. */
+ 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
+
+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, #-1
+ bne reg2_error_loopf
+ cmp r1, #1
+ bne reg2_error_loopf
+ vmov r0, r1, d1
+ cmp r0, #2
+ bne reg2_error_loopf
+ cmp r1, #3
+ bne reg2_error_loopf
+ vmov r0, r1, d2
+ cmp r0, #4
+ bne reg2_error_loopf
+ cmp r1, #5
+ bne reg2_error_loopf
+ vmov r0, r1, d3
+ cmp r0, #6
+ bne reg2_error_loopf
+ cmp r1, #7
+ bne reg2_error_loopf
+ vmov r0, r1, d4
+ cmp r0, #8
+ bne reg2_error_loopf
+ cmp r1, #9
+ bne reg2_error_loopf
+ vmov r0, r1, d5
+ cmp r0, #10
+ bne reg2_error_loopf
+ cmp r1, #11
+ bne reg2_error_loopf
+ vmov r0, r1, d6
+ cmp r0, #-1
+ bne reg2_error_loopf
+ cmp r1, #1
+ bne reg2_error_loopf
+ vmov r0, r1, d7
+ cmp r0, #2
+ bne reg2_error_loopf
+ cmp r1, #3
+ bne reg2_error_loopf
+ vmov r0, r1, d8
+ cmp r0, #4
+ bne reg2_error_loopf
+ cmp r1, #5
+ bne reg2_error_loopf
+ vmov r0, r1, d9
+ cmp r0, #6
+ bne reg2_error_loopf
+ cmp r1, #7
+ bne reg2_error_loopf
+ vmov r0, r1, d10
+ cmp r0, #8
+ bne reg2_error_loopf
+ cmp r1, #9
+ bne reg2_error_loopf
+ vmov r0, r1, d11
+ cmp r0, #10
+ bne reg2_error_loopf
+ cmp r1, #11
+ bne reg2_error_loopf
+ vmov r0, r1, d12
+ cmp r0, #-1
+ bne reg2_error_loopf
+ cmp r1, #1
+ bne reg2_error_loopf
+ vmov r0, r1, d13
+ cmp r0, #2
+ bne reg2_error_loopf
+ cmp r1, #3
+ bne reg2_error_loopf
+ vmov r0, r1, d14
+ cmp r0, #4
+ bne reg2_error_loopf
+ cmp r1, #5
+ bne reg2_error_loopf
+ vmov r0, r1, d15
+ cmp r0, #6
+ bne reg2_error_loopf
+ cmp r1, #7
+ 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, #-1
+ bne reg2_error_loop
+ cmp r1, #1
+ bne reg2_error_loop
+ cmp r2, #2
+ bne reg2_error_loop
+ cmp r3, #3
+ bne reg2_error_loop
+ cmp r4, #4
+ bne reg2_error_loop
+ cmp r5, #5
+ bne reg2_error_loop
+ cmp r6, #6
+ bne reg2_error_loop
+ cmp r7, #7
+ bne reg2_error_loop
+ cmp r8, #8
+ bne reg2_error_loop
+ cmp r9, #9
+ bne reg2_error_loop
+ cmp r10, #10
+ bne reg2_error_loop
+ cmp r11, #11
+ bne reg2_error_loop
+ cmp r12, #12
+ bne reg2_error_loop
+
+ /* Increment the loop counter so the check task knows this task is
+ still running. */
+ push { r0-r1 }
+ ldr r0, =pulRegTest4LoopCounter
+ ldr r0, [r0]
+ ldr r1, [r0]
+ adds r1, r1, #1
+ str r1, [r0]
+ pop { r0-r1 }
+
+ /* Yield to increase test coverage. */
+ SVC #1
+
+ /* Start again. */
+ b reg2_loop
+
+reg2_error_loop
+ /* If this line is hit then there was an error in a core register value.
+ This loop ensures the loop counter variable stops incrementing. */
+ b reg2_error_loop
+ nop
+}
+/*-----------------------------------------------------------*/
+
+/* Fault handlers are here for convenience as they use compiler specific syntax
+and this file is specific to the Keil compiler. */
+void hard_fault_handler( uint32_t * hardfault_args )
+{
+volatile uint32_t stacked_r0;
+volatile uint32_t stacked_r1;
+volatile uint32_t stacked_r2;
+volatile uint32_t stacked_r3;
+volatile uint32_t stacked_r12;
+volatile uint32_t stacked_lr;
+volatile uint32_t stacked_pc;
+volatile uint32_t stacked_psr;
+
+ stacked_r0 = ((uint32_t) hardfault_args[ 0 ]);
+ stacked_r1 = ((uint32_t) hardfault_args[ 1 ]);
+ stacked_r2 = ((uint32_t) hardfault_args[ 2 ]);
+ stacked_r3 = ((uint32_t) hardfault_args[ 3 ]);
+
+ stacked_r12 = ((uint32_t) hardfault_args[ 4 ]);
+ stacked_lr = ((uint32_t) hardfault_args[ 5 ]);
+ stacked_pc = ((uint32_t) hardfault_args[ 6 ]);
+ stacked_psr = ((uint32_t) hardfault_args[ 7 ]);
+
+ /* Inspect stacked_pc to locate the offending instruction. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void HardFault_Handler( void );
+__asm void HardFault_Handler( void )
+{
+ extern hard_fault_handler
+
+ tst lr, #4
+ ite eq
+ mrseq r0, msp
+ mrsne r0, psp
+ ldr r1, [r0, #24]
+ ldr r2, hard_fault_handler
+ bx r2
+}
+/*-----------------------------------------------------------*/
+
+void MemManage_Handler( void );
+__asm void MemManage_Handler( void )
+{
+ extern hard_fault_handler
+
+ tst lr, #4
+ ite eq
+ mrseq r0, msp
+ mrsne r0, psp
+ ldr r1, [r0, #24]
+ ldr r2, hard_fault_handler
+ bx r2
+}
+/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S
new file mode 100644
index 000000000..8534aa2b1
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S
@@ -0,0 +1,172 @@
+;/*****************************************************************************
+; * @file: startup_MPS_CM4.s
+; * @purpose: CMSIS Cortex-M4 Core Device Startup File
+; * for the ARM 'Microcontroller Prototyping System'
+; * @version: V1.00
+; * @date: 1. Jun. 2010
+; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
+; *
+; * Copyright (C) 2008-2010 ARM Limited. All rights reserved.
+; * ARM Limited (ARM) is supplying this software for use with Cortex-M4
+; * processor based microcontrollers. This file can be freely distributed
+; * within development tools that are supporting such ARM based processors.
+; *
+; * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+; *
+; ****************************************************************************/
+
+
+; Stack Configuration
+; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;
+Stack_Size EQU 0x00000800
+
+ AREA STACK, NOINIT, READWRITE, ALIGN=3
+Stack_Mem SPACE Stack_Size
+__initial_sp
+
+
+; Heap Configuration
+; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;
+
+Heap_Size EQU 0x00000000
+
+ AREA HEAP, NOINIT, READWRITE, ALIGN=3
+__heap_base
+Heap_Mem SPACE Heap_Size
+__heap_limit
+
+
+ PRESERVE8
+ THUMB
+
+
+; Vector Table Mapped to Address 0 at Reset
+
+ AREA RESET, DATA, READONLY
+ EXPORT __Vectors
+
+__Vectors DCD __initial_sp ; Top of Stack
+ DCD Reset_Handler ; Reset Handler
+ DCD NMI_Handler ; NMI Handler
+ DCD HardFault_Handler ; Hard Fault Handler
+ DCD MemManage_Handler ; MPU Fault Handler
+ DCD BusFault_Handler ; Bus Fault Handler
+ DCD UsageFault_Handler ; Usage Fault Handler
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD SVC_Handler ; SVCall Handler
+ DCD DebugMon_Handler ; Debug Monitor Handler
+ DCD 0 ; Reserved
+ DCD PendSV_Handler ; PendSV Handler
+ DCD SysTick_Handler ; SysTick Handler
+
+
+ AREA |.text|, CODE, READONLY
+; AREA RESET, CODE, READONLY
+
+; Reset Handler
+
+Reset_Handler PROC
+ EXPORT Reset_Handler [WEAK]
+ IMPORT __main
+
+ ; Remap vector table
+ LDR R0, =__Vectors
+ LDR R1, =0xE000ED08
+ STR R0, [r1]
+ NOP
+
+ IF {CPU} = "Cortex-M4.fp"
+ LDR R0, =0xE000ED88 ; Enable CP10,CP11
+ LDR R1,[R0]
+ ORR R1,R1,#(0xF << 20)
+ STR R1,[R0]
+ ENDIF
+
+ LDR R0, =__main
+ BX R0
+ ENDP
+
+
+; Dummy Exception Handlers (infinite loops which can be modified)
+
+NMI_Handler PROC
+ EXPORT NMI_Handler [WEAK]
+ B .
+ ENDP
+HardFault_Handler\
+ PROC
+ EXPORT HardFault_Handler [WEAK]
+ B .
+ ENDP
+MemManage_Handler\
+ PROC
+ EXPORT MemManage_Handler [WEAK]
+ B .
+ ENDP
+BusFault_Handler\
+ PROC
+ EXPORT BusFault_Handler [WEAK]
+ B .
+ ENDP
+UsageFault_Handler\
+ PROC
+ EXPORT UsageFault_Handler [WEAK]
+ B .
+ ENDP
+SVC_Handler PROC
+ EXPORT SVC_Handler [WEAK]
+ B .
+ ENDP
+DebugMon_Handler\
+ PROC
+ EXPORT DebugMon_Handler [WEAK]
+ B .
+ ENDP
+PendSV_Handler PROC
+ EXPORT PendSV_Handler [WEAK]
+ B .
+ ENDP
+SysTick_Handler PROC
+ EXPORT SysTick_Handler [WEAK]
+ B .
+ ENDP
+
+
+ ALIGN
+
+
+; User Initial Stack & Heap
+
+ IF :DEF:__MICROLIB
+
+ EXPORT __initial_sp
+ EXPORT __heap_base
+ EXPORT __heap_limit
+
+ ELSE
+
+ IMPORT __use_two_region_memory
+ EXPORT __user_initial_stackheap
+__user_initial_stackheap
+
+ LDR R0, = Heap_Mem
+ LDR R1, =(Stack_Mem + Stack_Size)
+ LDR R2, = (Heap_Mem + Heap_Size)
+ LDR R3, = Stack_Mem
+ BX LR
+
+ ALIGN
+
+ ENDIF
+
+
+ END
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c
new file mode 100644
index 000000000..cbaaabafa
--- /dev/null
+++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c
@@ -0,0 +1,1196 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+/*
+ * This file demonstrates the use of FreeRTOS-MPU in a completely statically
+ * allocated application (with configSUPPORT_DYNAMIC_ALLOCATION set to 0). It
+ * creates tasks in both User mode and Privileged mode, and using both the
+ * xTaskCreateStatic() and xTaskCreateRestrictedStatic() API functions. The
+ * purpose of each created task is documented in the comments above the task
+ * function prototype (in this file), with the task behaviour demonstrated and
+ * documented within the task function itself.
+ *
+ * In addition a queue is used to demonstrate passing data between
+ * protected/restricted tasks as well as passing data between an interrupt and
+ * a protected/restricted task. A software timer is also used.
+ */
+
+/* Standard includes. */
+#include "string.h"
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+#include "timers.h"
+#include "event_groups.h"
+
+/*-----------------------------------------------------------*/
+
+/* Misc constants. */
+#define mainDONT_BLOCK ( 0 )
+
+/* GCC specifics. */
+#define mainALIGN_TO( x ) __attribute__((aligned(x)))
+
+/* Hardware register addresses. */
+#define mainVTOR ( * ( volatile uint32_t * ) 0xE000ED08 )
+
+/* The period of the timer must be less than the rate at which
+configPRINT_SYSTEM_STATUS messages are sent to the check task - otherwise the
+check task will think the timer has stopped. */
+#define mainTIMER_PERIOD pdMS_TO_TICKS( 200 )
+
+/* The name of the task that is deleted by the Idle task is used in a couple of
+places, so is #defined. */
+#define mainTASK_TO_DELETE_NAME "DeleteMe"
+
+/*-----------------------------------------------------------*/
+/* Prototypes for functions that implement tasks. -----------*/
+/*-----------------------------------------------------------*/
+
+/*
+ * NOTE: The filling and checking of the registers in the following two tasks
+ * is only actually performed when the GCC compiler is used. Use of the
+ * queue to communicate with the check task is done with all compilers.
+ *
+ * Prototype for the first two register test tasks, which execute in User mode.
+ * Amongst other things, these fill the CPU registers (other than the FPU
+ * registers) with known values before checking that the registers still contain
+ * the expected values. Each of the two tasks use different values so an error
+ * in the context switch mechanism can be caught. Both tasks execute at the
+ * idle priority so will get preempted regularly. Each task repeatedly sends a
+ * message on a queue to a 'check' task so the check task knows the register
+ * check task is still executing and has not detected any errors. If an error
+ * is detected within the task the task is simply deleted so it no longer sends
+ * messages.
+ *
+ * For demonstration and test purposes, both tasks obtain access to the queue
+ * handle in different ways; vRegTest1Implementation() is created in Privileged
+ * mode and copies the queue handle to its local stack before setting itself to
+ * User mode, and vRegTest2Implementation() receives the task handle using its
+ * parameter.
+ */
+extern void vRegTest1Implementation( void *pvParameters );
+extern void vRegTest2Implementation( void *pvParameters );
+
+/*
+ * The second two register test tasks are similar to the first two, but do test
+ * the floating point registers, execute in Privileged mode, and signal their
+ * execution status to the 'check' task by incrementing a loop counter on each
+ * iteration instead of sending a message on a queue. The loop counters use a
+ * memory region to which the User mode 'check' task has read access.
+ *
+ * The functions ending 'Implementation' are called by the register check tasks.
+ *
+ * The tasks are created with xTaskCreateStatic(), so the stack and variables
+ * used to hold the task's data structures also have to be provided.
+ */
+static StackType_t xRegTest3Stack[ configMINIMAL_STACK_SIZE ], xRegTest4Stack[ configMINIMAL_STACK_SIZE ];
+static StaticTask_t xRegTest3Buffer, xRegTest4Buffer;
+static void prvRegTest3Task( void *pvParameters );
+extern void vRegTest3Implementation( void );
+static void prvRegTest4Task( void *pvParameters );
+extern void vRegTest4Implementation( void );
+
+/*
+ * Prototype for the check task. The check task demonstrates various features
+ * of the MPU before entering a loop where it waits for messages to arrive on a
+ * queue.
+ *
+ * Two types of messages can be processes:
+ *
+ * 1) "I'm Alive" messages sent from the first two register test tasks and a
+ * software timer callback, as described above.
+ *
+ * 2) "Print Status commands" sent periodically by the tick hook function (and
+ * therefore from within an interrupt) which commands the check task to write
+ * either pass or fail to the terminal, depending on the status of the reg
+ * test tasks (no write is performed in the simulator!).
+ */
+static void prvCheckTask( void *pvParameters );
+
+/*
+ * Prototype for a task created in User mode using vTaskCreateStatic() API
+ * function. The task demonstrates the characteristics of such a task,
+ * before simply deleting itself. As the task is created without using any
+ * dynamic memory allocate the stack and variable in which the task's data
+ * structure will be stored must also be provided - however the task is
+ * unprivileged so the stack cannot be in a privileged section.
+ */
+static StackType_t xUserModeTaskStack[ configMINIMAL_STACK_SIZE ];
+static PRIVILEGED_DATA StaticTask_t xUserModeTaskBuffer;
+static void prvOldStyleUserModeTask( void *pvParameters );
+
+/*
+ * Prototype for a task created in Privileged mode using the
+ * xTaskCreateStatic() API function. The task demonstrates the characteristics
+ * of such a task, before simply deleting itself. As no dynamic memory
+ * allocation is used the stack and variable used to hold the task's data
+ * structure must also be provided. The task is privileged, so the stack can
+ * be in a privileged section.
+ */
+static PRIVILEGED_DATA StackType_t xPrivilegedModeTaskStack[ configMINIMAL_STACK_SIZE ];
+static PRIVILEGED_DATA StaticTask_t xPrivilegedModeTaskBuffer;
+static void prvOldStylePrivilegedModeTask( void *pvParameters );
+
+/*
+ * A task that exercises the API of various RTOS objects before being deleted by
+ * the Idle task. This is done for MPU API code coverage test purposes.
+ */
+static void prvTaskToDelete( void *pvParameters );
+
+/*
+ * Functions called by prvTaskToDelete() to exercise the MPU API.
+ */
+static void prvExerciseEventGroupAPI( void );
+static void prvExerciseSemaphoreAPI( void );
+static void prvExerciseTaskNotificationAPI( void );
+
+/*
+ * Just configures any clocks and IO necessary.
+ */
+static void prvSetupHardware( void );
+
+/*
+ * Simply deletes the calling task. The function is provided only because it
+ * is simpler to call from asm code than the normal vTaskDelete() API function.
+ * It has the noinline attribute because it is called from asm code.
+ */
+void vMainDeleteMe( void ) __attribute__((noinline));
+
+/*
+ * Used by the first two reg test tasks and a software timer callback function
+ * to send messages to the check task. The message just lets the check task
+ * know that the tasks and timer are still functioning correctly. If a reg test
+ * task detects an error it will delete itself, and in so doing prevent itself
+ * from sending any more 'I'm Alive' messages to the check task.
+ */
+void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber );
+
+/*
+ * The check task is created with access to three memory regions (plus its
+ * stack). Each memory region is configured with different parameters and
+ * prvTestMemoryRegions() demonstrates what can and cannot be accessed for each
+ * region. prvTestMemoryRegions() also demonstrates a task that was created
+ * as a privileged task settings its own privilege level down to that of a user
+ * task.
+ */
+static void prvTestMemoryRegions( void );
+
+/*
+ * Callback function used with the timer that uses the queue to send messages
+ * to the check task.
+ */
+static void prvTimerCallback( TimerHandle_t xExpiredTimer );
+
+/*-----------------------------------------------------------*/
+
+/* The handle of the queue used to communicate between tasks and between tasks
+and interrupts. Note that this is a global scope variable that falls outside of
+any MPU region. As such other techniques have to be used to allow the tasks
+to gain access to the queue. See the comments in the tasks themselves for
+further information. */
+QueueHandle_t xGlobalScopeCheckQueue = NULL;
+
+/* xGlobalScopeCheckQueue is created using xQueueCreateStatic(), so the storage
+area and variable used to hold the queue data structure must also be provided.
+These are placed in a prviliged segment. */
+static PRIVILEGED_DATA StaticQueue_t xGlobalScopeQueueBuffer;
+uint8_t PRIVILEGED_DATA ucGlobalScopeQueueStorageArea[ 1 * sizeof( uint32_t ) ];
+
+
+/* Holds the handle of a task that is deleted in the idle task hook - this is
+done for code coverage test purposes only. */
+static TaskHandle_t xTaskToDelete = NULL;
+
+/* The timer that periodically sends data to the check task on the queue. This
+is created with xTimerCreateStatic(), so the variable in which the timer's data
+structure will be stored must also be provided. The structure is placed in the
+kernel's privileged data region. */
+static TimerHandle_t xTimer = NULL;
+static PRIVILEGED_DATA StaticTimer_t xTimerBuffer;
+
+#if defined ( __GNUC__ )
+ extern uint32_t __FLASH_segment_start__[];
+ extern uint32_t __FLASH_segment_end__[];
+ extern uint32_t __SRAM_segment_start__[];
+ extern uint32_t __SRAM_segment_end__[];
+ extern uint32_t __privileged_functions_start__[];
+ extern uint32_t __privileged_functions_end__[];
+ extern uint32_t __privileged_data_start__[];
+ extern uint32_t __privileged_data_end__[];
+ extern uint32_t __privileged_functions_actual_end__[];
+ extern uint32_t __privileged_data_actual_end__[];
+#else
+ const uint32_t * __FLASH_segment_start__ = ( uint32_t * ) 0x00UL;
+ const uint32_t * __FLASH_segment_end__ = ( uint32_t * ) 0x00080000UL;
+ const uint32_t * __SRAM_segment_start__ = ( uint32_t * ) 0x20000000UL;
+ const uint32_t * __SRAM_segment_end__ = ( uint32_t * ) 0x20008000UL;
+ const uint32_t * __privileged_functions_start__ = ( uint32_t * ) 0x00UL;
+ const uint32_t * __privileged_functions_end__ = ( uint32_t * ) 0x8000UL;
+ const uint32_t * __privileged_data_start__ = ( uint32_t * ) 0x20000000UL;
+ const uint32_t * __privileged_data_end__ = ( uint32_t * ) 0x20000800UL;
+#endif
+/*-----------------------------------------------------------*/
+/* Data used by the 'check' task. ---------------------------*/
+/*-----------------------------------------------------------*/
+
+/* Define the constants used to allocate the check task stack. Note that the
+stack size is defined in words, not bytes. */
+#define mainCHECK_TASK_STACK_SIZE_WORDS 128
+#define mainCHECK_TASK_STACK_ALIGNMENT ( mainCHECK_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )
+
+/* Declare the stack that will be used by the check task. The kernel will
+automatically create an MPU region for the stack. The stack alignment must
+match its size, so if 128 words are reserved for the stack then it must be
+aligned to ( 128 * 4 ) bytes. */
+static portSTACK_TYPE xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainCHECK_TASK_STACK_ALIGNMENT );
+
+/* Declare the variable in which the check task's data structures will be
+stored. PRIVILEGED_DATA is used to place this in the kernel's RAM segment. */
+static PRIVILEGED_DATA StaticTask_t xCheckTaskBuffer;
+
+/* Declare three arrays - an MPU region will be created for each array
+using the TaskParameters_t structure below. THIS IS JUST TO DEMONSTRATE THE
+MPU FUNCTIONALITY, the data is not used by the check tasks primary function
+of monitoring the reg test tasks and printing out status information.
+
+Note that the arrays allocate slightly more RAM than is actually assigned to
+the MPU region. This is to permit writes off the end of the array to be
+detected even when the arrays are placed in adjacent memory locations (with no
+gaps between them). The align size must be a power of two. */
+#define mainREAD_WRITE_ARRAY_SIZE 130
+#define mainREAD_WRITE_ALIGN_SIZE 128
+char cReadWriteArray[ mainREAD_WRITE_ARRAY_SIZE ] mainALIGN_TO( mainREAD_WRITE_ALIGN_SIZE );
+
+#define mainREAD_ONLY_ARRAY_SIZE 260
+#define mainREAD_ONLY_ALIGN_SIZE 256
+char cReadOnlyArray[ mainREAD_ONLY_ARRAY_SIZE ] mainALIGN_TO( mainREAD_ONLY_ALIGN_SIZE );
+
+#define mainPRIVILEGED_ONLY_ACCESS_ARRAY_SIZE 130
+#define mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE 128
+char cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] mainALIGN_TO( mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE );
+
+/* The following two variables are used to communicate the status of the second
+two register check tasks (tasks 3 and 4) 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. The variables
+overlay the array that the check task has access to so they can be read by the
+check task without causing a memory fault. The check task has the highest
+priority so will have finished with the array before the register test tasks
+start to access it. */
+volatile uint32_t *pulRegTest3LoopCounter = ( uint32_t * ) &( cReadWriteArray[ 0 ] ), *pulRegTest4LoopCounter = ( uint32_t * ) &( cReadWriteArray[ 4 ] );
+
+/* Fill in a TaskParameters_t structure to define the check task - this is the
+structure passed to the xTaskCreateRestricted() function. */
+static const TaskParameters_t xCheckTaskParameters =
+{
+ prvCheckTask, /* pvTaskCode - the function that implements the task. */
+ "Check", /* pcName */
+ mainCHECK_TASK_STACK_SIZE_WORDS, /* usStackDepth - defined in words, not bytes. */
+ ( void * ) 0x12121212, /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */
+ ( tskIDLE_PRIORITY + 1 ) | portPRIVILEGE_BIT,/* uxPriority - this is the highest priority task in the system. The task is created in privileged mode to demonstrate accessing the privileged only data. */
+ xCheckTaskStack, /* puxStackBuffer - the array to use as the task stack, as declared above. */
+
+ /* xRegions - In this case the xRegions array is used to create MPU regions
+ for all three of the arrays declared directly above. Each MPU region is
+ created with different parameters. Again, THIS IS JUST TO DEMONSTRATE THE
+ MPU FUNCTIONALITY, the data is not used by the check tasks primary function
+ of monitoring the reg test tasks and printing out status information.*/
+ {
+ /* Base address Length Parameters */
+ { cReadWriteArray, mainREAD_WRITE_ALIGN_SIZE, portMPU_REGION_READ_WRITE },
+ { cReadOnlyArray, mainREAD_ONLY_ALIGN_SIZE, portMPU_REGION_READ_ONLY },
+ { cPrivilegedOnlyAccessArray, mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE, portMPU_REGION_PRIVILEGED_READ_WRITE }
+ },
+
+ &xCheckTaskBuffer /* Additional structure member present when the task is being created without any dynamic memory allocation. */
+};
+
+
+/*-----------------------------------------------------------*/
+/* Data used by the 'reg test' tasks. -----------------------*/
+/*-----------------------------------------------------------*/
+
+/* Define the constants used to allocate the reg test task stacks. Note that
+that stack size is defined in words, not bytes. */
+#define mainREG_TEST_STACK_SIZE_WORDS 128
+#define mainREG_TEST_STACK_ALIGNMENT ( mainREG_TEST_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )
+
+/* Declare the stacks that will be used by the reg test tasks. The kernel will
+automatically create an MPU region for the stack. The stack alignment must
+match its size, so if 128 words are reserved for the stack then it must be
+aligned to ( 128 * 4 ) bytes. */
+static portSTACK_TYPE xRegTest1Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT );
+static portSTACK_TYPE xRegTest2Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT );
+
+/* The reg test tasks are created using the xTaskCreateRestrictedStatic() API
+function, so variables that hold the task's data structures must also be
+provided. The are placed in the kernel's privileged memory section. */
+static PRIVILEGED_DATA StaticTask_t xRegTest1TaskBuffer, xRegTest2TaskBuffer;
+
+/* Fill in a TaskParameters_t structure per reg test task to define the tasks. */
+static const TaskParameters_t xRegTest1Parameters =
+{
+ vRegTest1Implementation, /* pvTaskCode - the function that implements the task. */
+ "RegTest1", /* pcName */
+ mainREG_TEST_STACK_SIZE_WORDS, /* usStackDepth */
+ ( void * ) configREG_TEST_TASK_1_PARAMETER, /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */
+ tskIDLE_PRIORITY | portPRIVILEGE_BIT, /* uxPriority - note that this task is created with privileges to demonstrate one method of passing a queue handle into the task. */
+ xRegTest1Stack, /* puxStackBuffer - the array to use as the task stack, as declared above. */
+ { /* xRegions - this task does not use any non-stack data hence all members are zero. */
+ /* Base address Length Parameters */
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00 }
+ },
+
+ &xRegTest1TaskBuffer /* Additional parameter required when the task is created with xTaskCreateRestrictedStatic(). */
+};
+/*-----------------------------------------------------------*/
+
+static TaskParameters_t xRegTest2Parameters =
+{
+ vRegTest2Implementation, /* pvTaskCode - the function that implements the task. */
+ "RegTest2", /* pcName */
+ mainREG_TEST_STACK_SIZE_WORDS, /* usStackDepth */
+ ( void * ) NULL, /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */
+ tskIDLE_PRIORITY, /* uxPriority */
+ xRegTest2Stack, /* puxStackBuffer - the array to use as the task stack, as declared above. */
+ { /* xRegions - this task does not use any non-stack data hence all members are zero. */
+ /* Base address Length Parameters */
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00 }
+ },
+
+ &xRegTest2TaskBuffer /* Additional parameter required when the task is created with xTaskCreateRestrictedStatic(). */
+};
+
+/*-----------------------------------------------------------*/
+/* Configures the task that is deleted. ---------------------*/
+/*-----------------------------------------------------------*/
+
+/* Define the constants used to allocate the stack of the task that is
+deleted. Note that the stack size is defined in words, not bytes. */
+#define mainDELETE_TASK_STACK_SIZE_WORDS 128
+#define mainTASK_TO_DELETE_STACK_ALIGNMENT ( mainDELETE_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )
+
+/* Declare the stack that will be used by the task that gets deleted. The
+kernel will automatically create an MPU region for the stack. The stack
+alignment must match its size, so if 128 words are reserved for the stack
+then it must be aligned to ( 128 * 4 ) bytes. */
+static portSTACK_TYPE xDeleteTaskStack[ mainDELETE_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainTASK_TO_DELETE_STACK_ALIGNMENT );
+
+/* The task that gets deleted is created using xTaskCreateRestrictedStatic(),
+so the variable that stores the task's data structure must also be provided.
+This is placed in the kernel's privileged data segment. */
+static PRIVILEGED_DATA StaticTask_t xStaticDeleteTaskBuffer;
+
+static TaskParameters_t xTaskToDeleteParameters =
+{
+ prvTaskToDelete, /* pvTaskCode - the function that implements the task. */
+ mainTASK_TO_DELETE_NAME, /* pcName */
+ mainDELETE_TASK_STACK_SIZE_WORDS, /* usStackDepth */
+ ( void * ) NULL, /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */
+ tskIDLE_PRIORITY + 1, /* uxPriority */
+ xDeleteTaskStack, /* puxStackBuffer - the array to use as the task stack, as declared above. */
+ { /* xRegions - this task does not use any non-stack data hence all members are zero. */
+ /* Base address Length Parameters */
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00 }
+ },
+
+ &xStaticDeleteTaskBuffer /* Additional parameter required when xTaskCreateRestrictedStatic() is used. */
+};
+
+/*-----------------------------------------------------------*/
+
+volatile uint32_t ul1 = 0x123, ul2 = 0;
+
+int main( void )
+{
+ configASSERT( ul1 == 0x123 );
+ configASSERT( ul2 == 0 );
+ prvSetupHardware();
+
+ /* Create the queue used to pass "I'm alive" messages to the check task. */
+ xGlobalScopeCheckQueue = xQueueCreateStatic( 1, sizeof( uint32_t ), ucGlobalScopeQueueStorageArea, &xGlobalScopeQueueBuffer );
+
+ /* One check task uses the task parameter to receive the queue handle.
+ This allows the file scope variable to be accessed from within the task.
+ The pvParameters member of xRegTest2Parameters can only be set after the
+ queue has been created so is set here. */
+ xRegTest2Parameters.pvParameters = xGlobalScopeCheckQueue;
+
+ /* Create three test tasks. Handles to the created tasks are not required,
+ hence the second parameter is NULL. */
+ xTaskCreateRestrictedStatic( &xRegTest1Parameters, NULL );
+ xTaskCreateRestrictedStatic( &xRegTest2Parameters, NULL );
+ xTaskCreateRestrictedStatic( &xCheckTaskParameters, NULL );
+
+ /* Create a task that does nothing but ensure some of the MPU API functions
+ can be called correctly, then get deleted. This is done for code coverage
+ test purposes only. The task's handle is saved in xTaskToDelete so it can
+ get deleted in the idle task hook. */
+ xTaskCreateRestrictedStatic( &xTaskToDeleteParameters, &xTaskToDelete );
+
+ /* Create the tasks that are created using the original xTaskCreate() API
+ function. */
+ xTaskCreateStatic( prvOldStyleUserModeTask, /* The function that implements the task. */
+ "Task1", /* Text name for the task. */
+ 100, /* Stack depth in words. */
+ NULL, /* Task parameters. */
+ 3, /* Priority and mode (user in this case). */
+ xUserModeTaskStack, /* Used as the task's stack. */
+ &xUserModeTaskBuffer /* Used to hold the task's data structure. */
+ );
+
+ xTaskCreateStatic( prvOldStylePrivilegedModeTask, /* The function that implements the task. */
+ "Task2", /* Text name for the task. */
+ 100, /* Stack depth in words. */
+ NULL, /* Task parameters. */
+ ( 3 | portPRIVILEGE_BIT ), /* Priority and mode. */
+ xPrivilegedModeTaskStack, /* Used as the task's stack. */
+ &xPrivilegedModeTaskBuffer /* Used to hold the task's data structure. */
+ );
+
+ /* Create the third and fourth register check tasks, as described at the top
+ of this file. */
+ xTaskCreateStatic( prvRegTest3Task, "Reg3", configMINIMAL_STACK_SIZE, configREG_TEST_TASK_3_PARAMETER, tskIDLE_PRIORITY, xRegTest3Stack, &xRegTest3Buffer );
+ xTaskCreateStatic( prvRegTest4Task, "Reg4", configMINIMAL_STACK_SIZE, configREG_TEST_TASK_4_PARAMETER, tskIDLE_PRIORITY, xRegTest4Stack, &xRegTest4Buffer );
+
+ /* Create and start the software timer. */
+ xTimer = xTimerCreateStatic( "Timer", /* Test name for the timer. */
+ mainTIMER_PERIOD, /* Period of the timer. */
+ pdTRUE, /* The timer will auto-reload itself. */
+ ( void * ) 0, /* The timer's ID is used to count the number of times it expires - initialise this to 0. */
+ prvTimerCallback, /* The function called when the timer expires. */
+ &xTimerBuffer ); /* The variable in which the created timer's data structure will be stored. */
+ configASSERT( xTimer );
+ xTimerStart( xTimer, mainDONT_BLOCK );
+
+ /* Start the scheduler. */
+ vTaskStartScheduler();
+
+ /* Will only get here if there was insufficient memory to create the idle
+ task. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTask( void *pvParameters )
+{
+/* This task is created in privileged mode so can access the file scope
+queue variable. Take a stack copy of this before the task is set into user
+mode. Once that task is in user mode the file scope queue variable will no
+longer be accessible but the stack copy will. */
+QueueHandle_t xQueue = xGlobalScopeCheckQueue;
+int32_t lMessage;
+uint32_t ulStillAliveCounts[ 3 ] = { 0 };
+const char *pcStatusMessage = "PASS\r\n";
+uint32_t ulLastRegTest3CountValue = 0, ulLastRegTest4Value = 0;
+
+/* The register test tasks that also test the floating point registers increment
+a counter on each iteration of their loop. The counters are inside the array
+that this task has access to. */
+volatile uint32_t *pulOverlaidCounter3 = ( uint32_t * ) &( cReadWriteArray[ 0 ] ), *pulOverlaidCounter4 = ( uint32_t * ) &( cReadWriteArray[ 4 ] );
+
+/* ulCycleCount is incremented on each cycle of the check task. It can be
+viewed updating in the Keil watch window as the simulator does not print to
+the ITM port. */
+volatile uint32_t ulCycleCount = 0;
+
+ /* Just to remove compiler warning. */
+ ( void ) pvParameters;
+
+ /* Demonstrate how the various memory regions can and can't be accessed.
+ The task privilege level is set down to user mode within this function. */
+ prvTestMemoryRegions();
+
+ /* Clear overlaid reg test counters before entering the loop below. */
+ *pulOverlaidCounter3 = 0UL;
+ *pulOverlaidCounter4 = 0UL;
+
+ /* This loop performs the main function of the task, which is blocking
+ on a message queue then processing each message as it arrives. */
+ for( ;; )
+ {
+ /* Wait for the next message to arrive. */
+ xQueueReceive( xQueue, &lMessage, portMAX_DELAY );
+
+ switch( lMessage )
+ {
+ case configREG_TEST_1_STILL_EXECUTING :
+ case configREG_TEST_2_STILL_EXECUTING :
+ case configTIMER_STILL_EXECUTING :
+ /* Message from the first or second register check task, or
+ the timer callback function. Increment the count of the
+ number of times the message source has sent the message as
+ the message source must still be executed. */
+ ( ulStillAliveCounts[ lMessage ] )++;
+ break;
+
+ case configPRINT_SYSTEM_STATUS :
+ /* Message from tick hook, time to print out the system
+ status. If messages have stopped arriving from either of
+ the first two reg test task or the timer callback then the
+ status must be set to fail. */
+ if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 ) || ( ulStillAliveCounts[ 2 ] == 0 ) )
+ {
+ /* One or both of the test tasks are no longer sending
+ 'still alive' messages. */
+ pcStatusMessage = "FAIL\r\n";
+ }
+ else
+ {
+ /* Reset the count of 'still alive' messages. */
+ memset( ( void * ) ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );
+ }
+
+ /* Check that the register test 3 task is still incrementing
+ its counter, and therefore still running. */
+ if( ulLastRegTest3CountValue == *pulOverlaidCounter3 )
+ {
+ pcStatusMessage = "FAIL\r\n";
+ }
+ ulLastRegTest3CountValue = *pulOverlaidCounter3;
+
+ /* Check that the register test 4 task is still incrementing
+ its counter, and therefore still running. */
+ if( ulLastRegTest4Value == *pulOverlaidCounter4 )
+ {
+ pcStatusMessage = "FAIL\r\n";
+ }
+ ulLastRegTest4Value = *pulOverlaidCounter4;
+
+ /**** Print pcStatusMessage here. ****/
+ ( void ) pcStatusMessage;
+
+ /* The cycle count can be viewed updating in the Keil watch
+ window if ITM printf is not being used. */
+ ulCycleCount++;
+ break;
+
+ default :
+ /* Something unexpected happened. Delete this task so the
+ error is apparent (no output will be displayed). */
+ vMainDeleteMe();
+ break;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvTestMemoryRegions( void )
+{
+int32_t x;
+char cTemp;
+
+ /* The check task (from which this function is called) is created in the
+ Privileged mode. The privileged array can be both read from and written
+ to while this task is privileged. */
+ cPrivilegedOnlyAccessArray[ 0 ] = 'a';
+ if( cPrivilegedOnlyAccessArray[ 0 ] != 'a' )
+ {
+ /* Something unexpected happened. Delete this task so the error is
+ apparent (no output will be displayed). */
+ vMainDeleteMe();
+ }
+
+ /* Writing off the end of the RAM allocated to this task will *NOT* cause a
+ protection fault because the task is still executing in a privileged mode.
+ Uncomment the following to test. */
+ /*cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] = 'a';*/
+
+ /* Now set the task into user mode. */
+ portSWITCH_TO_USER_MODE();
+
+ /* Accessing the privileged only array will now cause a fault. Uncomment
+ the following line to test. */
+ /*cPrivilegedOnlyAccessArray[ 0 ] = 'a';*/
+
+ /* The read/write array can still be successfully read and written. */
+ for( x = 0; x < mainREAD_WRITE_ALIGN_SIZE; x++ )
+ {
+ cReadWriteArray[ x ] = 'a';
+ if( cReadWriteArray[ x ] != 'a' )
+ {
+ /* Something unexpected happened. Delete this task so the error is
+ apparent (no output will be displayed). */
+ vMainDeleteMe();
+ }
+ }
+
+ /* But attempting to read or write off the end of the RAM allocated to this
+ task will cause a fault. Uncomment either of the following two lines to
+ test. */
+ /* cReadWriteArray[ 0 ] = cReadWriteArray[ -1 ]; */
+ /* cReadWriteArray[ mainREAD_WRITE_ALIGN_SIZE ] = 0x00; */
+
+ /* The read only array can be successfully read... */
+ for( x = 0; x < mainREAD_ONLY_ALIGN_SIZE; x++ )
+ {
+ cTemp = cReadOnlyArray[ x ];
+ }
+
+ /* ...but cannot be written. Uncomment the following line to test. */
+ /* cReadOnlyArray[ 0 ] = 'a'; */
+
+ /* Writing to the first and last locations in the stack array should not
+ cause a protection fault. Note that doing this will cause the kernel to
+ detect a stack overflow if configCHECK_FOR_STACK_OVERFLOW is greater than
+ 1, hence the test is commented out by default. */
+ /* xCheckTaskStack[ 0 ] = 0;
+ xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS - 1 ] = 0; */
+
+ /* Writing off either end of the stack array should cause a protection
+ fault, uncomment either of the following two lines to test. */
+ /* xCheckTaskStack[ -1 ] = 0; */
+ /* xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] = 0; */
+
+ ( void ) cTemp;
+}
+/*-----------------------------------------------------------*/
+
+static void prvExerciseEventGroupAPI( void )
+{
+EventGroupHandle_t xEventGroup;
+StaticEventGroup_t xEventGroupBuffer;
+EventBits_t xBits;
+const EventBits_t xBitsToWaitFor = ( EventBits_t ) 0xff, xBitToClear = ( EventBits_t ) 0x01;
+
+ /* Exercise some event group functions. */
+ xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
+ configASSERT( xEventGroup );
+
+ /* No bits should be set. */
+ xBits = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdFALSE, mainDONT_BLOCK );
+ configASSERT( xBits == ( EventBits_t ) 0 );
+
+ /* Set bits and read back to ensure the bits were set. */
+ xEventGroupSetBits( xEventGroup, xBitsToWaitFor );
+ xBits = xEventGroupGetBits( xEventGroup );
+ configASSERT( xBits == xBitsToWaitFor );
+
+ /* Clear a bit and read back again using a different API function. */
+ xEventGroupClearBits( xEventGroup, xBitToClear );
+ xBits = xEventGroupSync( xEventGroup, 0x00, xBitsToWaitFor, mainDONT_BLOCK );
+ configASSERT( xBits == ( xBitsToWaitFor & ~xBitToClear ) );
+
+ /* Finished with the event group. */
+ vEventGroupDelete( xEventGroup );
+}
+/*-----------------------------------------------------------*/
+
+static void prvExerciseSemaphoreAPI( void )
+{
+SemaphoreHandle_t xSemaphore;
+StaticSemaphore_t xSemaphoreBuffer;
+const UBaseType_t uxMaxCount = 5, uxInitialCount = 0;
+
+ /* Most of the semaphore API is common to the queue API and is already being
+ used. This function uses a few semaphore functions that are unique to the
+ RTOS objects, rather than generic and used by queues also.
+
+ First create and use a counting semaphore. */
+ xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, &xSemaphoreBuffer );
+ configASSERT( xSemaphore );
+
+ /* Give the semaphore a couple of times and ensure the count is returned
+ correctly. */
+ xSemaphoreGive( xSemaphore );
+ xSemaphoreGive( xSemaphore );
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 2 );
+ vSemaphoreDelete( xSemaphore );
+
+ /* Create a recursive mutex, and ensure the mutex holder and count are
+ returned returned correctly. */
+ xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 );
+ configASSERT( xSemaphore );
+ xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK );
+ xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK );
+ configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() );
+ configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetHandle( mainTASK_TO_DELETE_NAME ) );
+ xSemaphoreGiveRecursive( xSemaphore );
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
+ xSemaphoreGiveRecursive( xSemaphore );
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 );
+ configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL );
+ vSemaphoreDelete( xSemaphore );
+
+ /* Create a normal mutex, and sure the mutex holder and count are returned
+ returned correctly. */
+ xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );
+ configASSERT( xSemaphore );
+ xSemaphoreTake( xSemaphore, mainDONT_BLOCK );
+ xSemaphoreTake( xSemaphore, mainDONT_BLOCK );
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); /* Not recursive so can only be 1. */
+ configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() );
+ xSemaphoreGive( xSemaphore );
+ configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 );
+ configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL );
+ vSemaphoreDelete( xSemaphore );
+}
+/*-----------------------------------------------------------*/
+
+static void prvExerciseTaskNotificationAPI( void )
+{
+uint32_t ulNotificationValue;
+BaseType_t xReturned;
+
+ /* The task should not yet have a notification pending. */
+ xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK );
+ configASSERT( xReturned == pdFAIL );
+ configASSERT( ulNotificationValue == 0UL );
+
+ /* Exercise the 'give' and 'take' versions of the notification API. */
+ xTaskNotifyGive( xTaskGetCurrentTaskHandle() );
+ xTaskNotifyGive( xTaskGetCurrentTaskHandle() );
+ ulNotificationValue = ulTaskNotifyTake( pdTRUE, mainDONT_BLOCK );
+ configASSERT( ulNotificationValue == 2 );
+
+ /* Exercise the 'notify' and 'clear' API. */
+ ulNotificationValue = 20;
+ xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite );
+ ulNotificationValue = 0;
+ xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK );
+ configASSERT( xReturned == pdPASS );
+ configASSERT( ulNotificationValue == 20 );
+ xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite );
+ xReturned = xTaskNotifyStateClear( NULL );
+ configASSERT( xReturned == pdTRUE ); /* First time a notification was pending. */
+ xReturned = xTaskNotifyStateClear( NULL );
+ configASSERT( xReturned == pdFALSE ); /* Second time the notification was already clear. */
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskToDelete( void *pvParameters )
+{
+ /* Remove compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ /* Check the enter and exit critical macros are working correctly. If the
+ SVC priority is below configMAX_SYSCALL_INTERRUPT_PRIORITY then this will
+ fault. */
+ taskENTER_CRITICAL();
+ taskEXIT_CRITICAL();
+
+ /* Exercise the API of various RTOS objects. */
+ prvExerciseEventGroupAPI();
+ prvExerciseSemaphoreAPI();
+ prvExerciseTaskNotificationAPI();
+
+ /* For code coverage test purposes it is deleted by the Idle task. */
+ configASSERT( uxTaskGetStackHighWaterMark( NULL ) > 0 );
+ vTaskSuspend( NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationIdleHook( void )
+{
+volatile const uint32_t *pul;
+volatile uint32_t ulReadData;
+
+ /* The idle task, and therefore this function, run in Supervisor mode and
+ can therefore access all memory. Try reading from corners of flash and
+ RAM to ensure a memory fault does not occur.
+
+ Start with the edges of the privileged data area. */
+ pul = __privileged_data_start__;
+ ulReadData = *pul;
+ pul = __privileged_data_end__ - 1;
+ ulReadData = *pul;
+
+ /* Next the standard SRAM area. */
+ pul = __SRAM_segment_end__ - 1;
+ ulReadData = *pul;
+
+ /* And the standard Flash area - the start of which is marked for
+ privileged access only. */
+ pul = __FLASH_segment_start__;
+ ulReadData = *pul;
+ pul = __FLASH_segment_end__ - 1;
+ ulReadData = *pul;
+
+ /* Reading off the end of Flash or SRAM space should cause a fault.
+ Uncomment one of the following two pairs of lines to test. */
+
+ /* pul = __FLASH_segment_end__ + 4;
+ ulReadData = *pul; */
+
+ /* pul = __SRAM_segment_end__ + 1;
+ ulReadData = *pul; */
+
+ /* One task is created purely so it can be deleted - done for code coverage
+ test purposes. */
+ if( xTaskToDelete != NULL )
+ {
+ vTaskDelete( xTaskToDelete );
+ xTaskToDelete = NULL;
+ }
+
+ ( void ) ulReadData;
+}
+/*-----------------------------------------------------------*/
+
+static void prvOldStyleUserModeTask( void *pvParameters )
+{
+/*const volatile uint32_t *pulStandardPeripheralRegister = ( volatile uint32_t * ) 0x40000000;*/
+volatile const uint32_t *pul;
+volatile uint32_t ulReadData;
+
+/* The following lines are commented out to prevent the unused variable
+compiler warnings when the tests that use the variable are also commented out. */
+/* extern uint32_t __privileged_functions_start__[]; */
+/* const volatile uint32_t *pulSystemPeripheralRegister = ( volatile uint32_t * ) 0xe000e014; */
+
+ ( void ) pvParameters;
+
+ /* This task is created in User mode using the original xTaskCreate() API
+ function. It should have access to all Flash and RAM except that marked
+ as Privileged access only. Reading from the start and end of the non-
+ privileged RAM should not cause a problem (the privileged RAM is the first
+ block at the bottom of the RAM memory). */
+ pul = __privileged_data_end__ + 1;
+ ulReadData = *pul;
+ pul = __SRAM_segment_end__ - 1;
+ ulReadData = *pul;
+
+ /* Likewise reading from the start and end of the non-privileged Flash
+ should not be a problem (the privileged Flash is the first block at the
+ bottom of the Flash memory). */
+ pul = __privileged_functions_end__ + 1;
+ ulReadData = *pul;
+ pul = __FLASH_segment_end__ - 1;
+ ulReadData = *pul;
+
+ /* Standard peripherals are accessible. */
+ /*ulReadData = *pulStandardPeripheralRegister;*/
+
+ /* System peripherals are not accessible. Uncomment the following line
+ to test. Also uncomment the declaration of pulSystemPeripheralRegister
+ at the top of this function.
+ ulReadData = *pulSystemPeripheralRegister; */
+
+ /* Reading from anywhere inside the privileged Flash or RAM should cause a
+ fault. This can be tested by uncommenting any of the following pairs of
+ lines. Also uncomment the declaration of __privileged_functions_start__
+ at the top of this function. */
+
+ /*pul = __privileged_functions_start__;
+ ulReadData = *pul;*/
+
+ /*pul = __privileged_functions_end__ - 1;
+ ulReadData = *pul;*/
+
+ /*pul = __privileged_data_start__;
+ ulReadData = *pul;*/
+
+ /*pul = __privileged_data_end__ - 1;
+ ulReadData = *pul;*/
+
+ /* Must not just run off the end of a task function, so delete this task.
+ Note that because this task was created using xTaskCreate() the stack was
+ allocated dynamically and I have not included any code to free it again. */
+ vTaskDelete( NULL );
+
+ ( void ) ulReadData;
+}
+/*-----------------------------------------------------------*/
+
+static void prvOldStylePrivilegedModeTask( void *pvParameters )
+{
+volatile const uint32_t *pul;
+volatile uint32_t ulReadData;
+const volatile uint32_t *pulSystemPeripheralRegister = ( volatile uint32_t * ) 0xe000e014; /* Systick */
+/*const volatile uint32_t *pulStandardPeripheralRegister = ( volatile uint32_t * ) 0x40000000;*/
+
+ ( void ) pvParameters;
+
+ /* This task is created in Privileged mode using the original xTaskCreate()
+ API function. It should have access to all Flash and RAM including that
+ marked as Privileged access only. So reading from the start and end of the
+ non-privileged RAM should not cause a problem (the privileged RAM is the
+ first block at the bottom of the RAM memory). */
+ pul = __privileged_data_end__ + 1;
+ ulReadData = *pul;
+ pul = __SRAM_segment_end__ - 1;
+ ulReadData = *pul;
+
+ /* Likewise reading from the start and end of the non-privileged Flash
+ should not be a problem (the privileged Flash is the first block at the
+ bottom of the Flash memory). */
+ pul = __privileged_functions_end__ + 1;
+ ulReadData = *pul;
+ pul = __FLASH_segment_end__ - 1;
+ ulReadData = *pul;
+
+ /* Reading from anywhere inside the privileged Flash or RAM should also
+ not be a problem. */
+ pul = __privileged_functions_start__;
+ ulReadData = *pul;
+ pul = __privileged_functions_end__ - 1;
+ ulReadData = *pul;
+ pul = __privileged_data_start__;
+ ulReadData = *pul;
+ pul = __privileged_data_end__ - 1;
+ ulReadData = *pul;
+
+ /* Finally, accessing both System and normal peripherals should both be
+ possible. */
+ ulReadData = *pulSystemPeripheralRegister;
+ /*ulReadData = *pulStandardPeripheralRegister;*/
+
+ /* Must not just run off the end of a task function, so delete this task.
+ Note that because this task was created using xTaskCreate() the stack was
+ allocated dynamically and I have not included any code to free it again. */
+ vTaskDelete( NULL );
+
+ ( void ) ulReadData;
+}
+/*-----------------------------------------------------------*/
+
+void vMainDeleteMe( void )
+{
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber )
+{
+ if( xHandle != NULL )
+ {
+ xQueueSend( xHandle, &ulTaskNumber, mainDONT_BLOCK );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvSetupHardware( void )
+{
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationTickHook( void )
+{
+static uint32_t ulCallCount = 0;
+const uint32_t ulCallsBetweenSends = pdMS_TO_TICKS( 1000 );
+const uint32_t ulMessage = configPRINT_SYSTEM_STATUS;
+portBASE_TYPE xDummy;
+
+ /* If configUSE_TICK_HOOK is set to 1 then this function will get called
+ from each RTOS tick. It is called from the tick interrupt and therefore
+ will be executing in the privileged state. */
+
+ ulCallCount++;
+
+ /* Is it time to print out the pass/fail message again? */
+ if( ulCallCount >= ulCallsBetweenSends )
+ {
+ ulCallCount = 0;
+
+ /* Send a message to the check task to command it to check that all
+ the tasks are still running then print out the status.
+
+ This is running in an ISR so has to use the "FromISR" version of
+ xQueueSend(). Because it is in an ISR it is running with privileges
+ so can access xGlobalScopeCheckQueue directly. */
+ xQueueSendFromISR( xGlobalScopeCheckQueue, &ulMessage, &xDummy );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
+{
+ /* If configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2 then this
+ function will automatically get called if a task overflows its stack. */
+ ( void ) pxTask;
+ ( void ) pcTaskName;
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationMallocFailedHook( void )
+{
+ /* If configUSE_MALLOC_FAILED_HOOK is set to 1 then this function will
+ be called automatically if a call to pvPortMalloc() fails. pvPortMalloc()
+ is called automatically when a task, queue or semaphore is created. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvTimerCallback( TaskHandle_t xExpiredTimer )
+{
+uint32_t ulCount;
+
+ /* The count of the number of times this timer has expired is saved in the
+ timer's ID. Obtain the current count. */
+ ulCount = ( uint32_t ) pvTimerGetTimerID( xTimer );
+
+ /* Increment the count, and save it back into the timer's ID. */
+ ulCount++;
+ vTimerSetTimerID( xTimer, ( void * ) ulCount );
+
+ /* Let the check task know the timer is still running. */
+ vMainSendImAlive( xGlobalScopeCheckQueue, configTIMER_STILL_EXECUTING );
+}
+/*-----------------------------------------------------------*/
+
+/* 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;
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTest3Task( 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 == configREG_TEST_TASK_3_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest3Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check task will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTest4Task( 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 == configREG_TEST_TASK_4_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest4Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check task will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+
diff --git a/FreeRTOS/Source/include/mpu_prototypes.h b/FreeRTOS/Source/include/mpu_prototypes.h
index b4a1d0980..205995757 100644
--- a/FreeRTOS/Source/include/mpu_prototypes.h
+++ b/FreeRTOS/Source/include/mpu_prototypes.h
@@ -83,6 +83,7 @@
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer );
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete );
void MPU_vTaskDelay( const TickType_t xTicksToDelay );
diff --git a/FreeRTOS/Source/include/mpu_wrappers.h b/FreeRTOS/Source/include/mpu_wrappers.h
index 7d3334282..622b0e2e0 100644
--- a/FreeRTOS/Source/include/mpu_wrappers.h
+++ b/FreeRTOS/Source/include/mpu_wrappers.h
@@ -177,8 +177,11 @@ only for ports that are using the MPU. */
#define xEventGroupSync MPU_xEventGroupSync
#define vEventGroupDelete MPU_vEventGroupDelete
- /* Remove the privileged function macro. */
+ /* Remove the privileged function macro, but keep the PRIVILEGED_DATA
+ macro so applications can place data in privileged access sections
+ (useful when using statically allocated objects). */
#define PRIVILEGED_FUNCTION
+ #define PRIVILEGED_DATA __attribute__((section("privileged_data")))
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h
index dd7cd0322..172e0b6d5 100644
--- a/FreeRTOS/Source/include/task.h
+++ b/FreeRTOS/Source/include/task.h
@@ -160,6 +160,9 @@ typedef struct xTASK_PARAMETERS
UBaseType_t uxPriority;
StackType_t *puxStackBuffer;
MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ];
+ #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ StaticTask_t * const pxTaskBuffer;
+ #endif
} TaskParameters_t;
/* Used with the uxTaskGetSystemState() function to return the state of each task
@@ -487,6 +490,8 @@ is used in assert() statements. */
*
BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
*
+ * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1.
+ *
* xTaskCreateRestricted() should only be used in systems that include an MPU
* implementation.
*
@@ -494,6 +499,9 @@ is used in assert() statements. */
* The function parameters define the memory regions and associated access
* permissions allocated to the task.
*
+ * See xTaskCreateRestrictedStatic() for a version that does not use any
+ * dynamic memory allocation.
+ *
* @param pxTaskDefinition Pointer to a structure that contains a member
* for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
* documentation) plus an optional stack buffer and the memory region
@@ -553,6 +561,94 @@ TaskHandle_t xHandle;
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif
+/**
+ * task. h
+ *
+ BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ *
+ * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1.
+ *
+ * xTaskCreateRestrictedStatic() should only be used in systems that include an
+ * MPU implementation.
+ *
+ * Internally, within the FreeRTOS implementation, tasks use two blocks of
+ * memory. The first block is used to hold the task's data structures. The
+ * second block is used by the task as its stack. If a task is created using
+ * xTaskCreateRestricted() then the stack is provided by the application writer,
+ * and the memory used to hold the task's data structure is automatically
+ * dynamically allocated inside the xTaskCreateRestricted() function. If a task
+ * is created using xTaskCreateRestrictedStatic() then the application writer
+ * must provide the memory used to hold the task's data structures too.
+ * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be
+ * created without using any dynamic memory allocation.
+ *
+ * @param pxTaskDefinition Pointer to a structure that contains a member
+ * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
+ * documentation) plus an optional stack buffer and the memory region
+ * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure
+ * contains an additional member, which is used to point to a variable of type
+ * StaticTask_t - which is then used to hold the task's data structure.
+ *
+ * @param pxCreatedTask Used to pass back a handle by which the created task
+ * can be referenced.
+ *
+ * @return pdPASS if the task was successfully created and added to a ready
+ * list, otherwise an error code defined in the file projdefs.h
+ *
+ * Example usage:
+
+// Create an TaskParameters_t structure that defines the task to be created.
+// The StaticTask_t variable is only included in the structure when
+// configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro can
+// be used to force the variable into the RTOS kernel's privileged data area.
+static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
+static const TaskParameters_t xCheckTaskParameters =
+{
+ vATask, // pvTaskCode - the function that implements the task.
+ "ATask", // pcName - just a text name for the task to assist debugging.
+ 100, // usStackDepth - the stack size DEFINED IN WORDS.
+ NULL, // pvParameters - passed into the task function as the function parameters.
+ ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+ cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+ // xRegions - Allocate up to three separate memory regions for access by
+ // the task, with appropriate access permissions. Different processors have
+ // different memory alignment requirements - refer to the FreeRTOS documentation
+ // for full information.
+ {
+ // Base address Length Parameters
+ { cReadWriteArray, 32, portMPU_REGION_READ_WRITE },
+ { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY },
+ { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE }
+ }
+
+ &xTaskBuffer; // Holds the task's data structure.
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+ // Create a task from the const structure defined above. The task handle
+ // is requested (the second parameter is not NULL) but in this case just for
+ // demonstration purposes as its not actually used.
+ xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+ // Start the scheduler.
+ vTaskStartScheduler();
+
+ // Will only get here if there was insufficient memory to create the idle
+ // and/or timer task.
+ for( ;; );
+}
+
+ * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic
+ * \ingroup Tasks
+ */
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+ BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
+#endif
+
/**
* task. h
*
diff --git a/FreeRTOS/Source/portable/Common/mpu_wrappers.c b/FreeRTOS/Source/portable/Common/mpu_wrappers.c
index 8a5115b78..0fae3c65c 100644
--- a/FreeRTOS/Source/portable/Common/mpu_wrappers.c
+++ b/FreeRTOS/Source/portable/Common/mpu_wrappers.c
@@ -96,15 +96,30 @@ extern BaseType_t xPortRaisePrivilege( void );
/*-----------------------------------------------------------*/
-BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
-{
-BaseType_t xReturn;
-BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+ {
+ BaseType_t xReturn;
+ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
- xReturn = xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
- vPortResetPrivilege( xRunningPrivileged );
- return xReturn;
-}
+ xReturn = xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
+ vPortResetPrivilege( xRunningPrivileged );
+ return xReturn;
+ }
+#endif /* conifgSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+ BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+ {
+ BaseType_t xReturn;
+ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+
+ xReturn = xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask );
+ vPortResetPrivilege( xRunningPrivileged );
+ return xReturn;
+ }
+#endif /* conifgSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
@@ -337,7 +352,7 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#endif
/*-----------------------------------------------------------*/
-#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void MPU_vTaskList( char *pcWriteBuffer )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@@ -348,7 +363,7 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
#endif
/*-----------------------------------------------------------*/
-#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@@ -726,7 +741,7 @@ void * xReturn;
#endif
/*-----------------------------------------------------------*/
-#if ( configUSE_QUEUE_SETS == 1 )
+#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength )
{
QueueSetHandle_t xReturn;
@@ -827,7 +842,6 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-
void *MPU_pvPortMalloc( size_t xSize )
{
void *pvReturn;
@@ -839,12 +853,10 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
return pvReturn;
}
-
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-
void MPU_vPortFree( void *pv )
{
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@@ -853,31 +865,34 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
vPortResetPrivilege( xRunningPrivileged );
}
-
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
-void MPU_vPortInitialiseBlocks( void )
-{
-BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ void MPU_vPortInitialiseBlocks( void )
+ {
+ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
- vPortInitialiseBlocks();
+ vPortInitialiseBlocks();
- vPortResetPrivilege( xRunningPrivileged );
-}
+ vPortResetPrivilege( xRunningPrivileged );
+ }
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
-size_t MPU_xPortGetFreeHeapSize( void )
-{
-size_t xReturn;
-BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+ size_t MPU_xPortGetFreeHeapSize( void )
+ {
+ size_t xReturn;
+ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
- xReturn = xPortGetFreeHeapSize();
+ xReturn = xPortGetFreeHeapSize();
- vPortResetPrivilege( xRunningPrivileged );
+ vPortResetPrivilege( xRunningPrivileged );
- return xReturn;
-}
+ return xReturn;
+ }
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
/*-----------------------------------------------------------*/
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_TIMERS == 1 ) )
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c
index 8a296ba53..1cdb016db 100644
--- a/FreeRTOS/Source/tasks.c
+++ b/FreeRTOS/Source/tasks.c
@@ -134,7 +134,7 @@ that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
a statically allocated stack and a dynamically allocated TCB.
!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
changed then the definition of StaticTask_t must also be updated. */
-#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
@@ -667,7 +667,53 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
#endif /* SUPPORT_STATIC_ALLOCATION */
/*-----------------------------------------------------------*/
-#if( portUSING_MPU_WRAPPERS == 1 )
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+ BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+ {
+ TCB_t *pxNewTCB;
+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+ configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
+ configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
+
+ if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
+ {
+ /* Allocate space for the TCB. Where the memory comes from depends
+ on the implementation of the port malloc function and whether or
+ not static allocation is being used. */
+ pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
+
+ /* Store the stack location in the TCB. */
+ pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+ #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+ {
+ /* Tasks can be created statically or dynamically, so note this
+ task was created statically in case the task is later deleted. */
+ pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+ }
+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+ prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
+ pxTaskDefinition->pcName,
+ ( uint32_t ) pxTaskDefinition->usStackDepth,
+ pxTaskDefinition->pvParameters,
+ pxTaskDefinition->uxPriority,
+ pxCreatedTask, pxNewTCB,
+ pxTaskDefinition->xRegions );
+
+ prvAddNewTaskToReadyList( pxNewTCB );
+ xReturn = pdPASS;
+ }
+
+ return xReturn;
+ }
+
+#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+/*-----------------------------------------------------------*/
+
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
{
@@ -3987,7 +4033,7 @@ TCB_t *pxTCB;
#endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
/*-----------------------------------------------------------*/
-#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void vTaskList( char * pcWriteBuffer )
{
@@ -4079,10 +4125,10 @@ TCB_t *pxTCB;
}
}
-#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
/*----------------------------------------------------------*/
-#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
void vTaskGetRunTimeStats( char *pcWriteBuffer )
{
@@ -4206,7 +4252,7 @@ TCB_t *pxTCB;
}
}
-#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
/*-----------------------------------------------------------*/
TickType_t uxTaskResetEventItemValue( void )