]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c
Add support for statically allocated memory protected tasks - previously only dynamic...
[freertos] / FreeRTOS / Demo / CORTEX_MPU_Static_Simulator_Keil_GCC / main.c
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 (file)
index 0000000..cbaaaba
--- /dev/null
@@ -0,0 +1,1196 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+\r
+/*\r
+ * This file demonstrates the use of FreeRTOS-MPU in a completely statically\r
+ * allocated application (with configSUPPORT_DYNAMIC_ALLOCATION set to 0).  It\r
+ * creates tasks in both User mode and Privileged mode, and using both the\r
+ * xTaskCreateStatic() and xTaskCreateRestrictedStatic() API functions.  The\r
+ * purpose of each created task is documented in the comments above the task\r
+ * function prototype (in this file), with the task behaviour demonstrated and\r
+ * documented within the task function itself.\r
+ *\r
+ * In addition a queue is used to demonstrate passing data between\r
+ * protected/restricted tasks as well as passing data between an interrupt and\r
+ * a protected/restricted task.  A software timer is also used.\r
+ */\r
+\r
+/* Standard includes. */\r
+#include "string.h"\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+#include "timers.h"\r
+#include "event_groups.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Misc constants. */\r
+#define mainDONT_BLOCK                                 ( 0 )\r
+\r
+/* GCC specifics. */\r
+#define mainALIGN_TO( x )                              __attribute__((aligned(x)))\r
+\r
+/* Hardware register addresses. */\r
+#define mainVTOR                                               ( * ( volatile uint32_t * ) 0xE000ED08 )\r
+\r
+/* The period of the timer must be less than the rate at which\r
+configPRINT_SYSTEM_STATUS messages are sent to the check task - otherwise the\r
+check task will think the timer has stopped. */\r
+#define mainTIMER_PERIOD                               pdMS_TO_TICKS( 200 )\r
+\r
+/* The name of the task that is deleted by the Idle task is used in a couple of\r
+places, so is #defined. */\r
+#define mainTASK_TO_DELETE_NAME                        "DeleteMe"\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for functions that implement tasks. -----------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * NOTE:  The filling and checking of the registers in the following two tasks\r
+ *        is only actually performed when the GCC compiler is used.  Use of the\r
+ *        queue to communicate with the check task is done with all compilers.\r
+ *\r
+ * Prototype for the first two register test tasks, which execute in User mode.\r
+ * Amongst other things, these fill the CPU registers (other than the FPU\r
+ * registers) with known values before checking that the registers still contain\r
+ * the expected values.  Each of the two tasks use different values so an error\r
+ * in the context switch mechanism can be caught.  Both tasks execute at the\r
+ * idle priority so will get preempted regularly.  Each task repeatedly sends a\r
+ * message on a queue to a 'check' task so the check task knows the register\r
+ * check task is still executing and has not detected any errors.  If an error\r
+ * is detected within the task the task is simply deleted so it no longer sends\r
+ * messages.\r
+ *\r
+ * For demonstration and test purposes, both tasks obtain access to the queue\r
+ * handle in different ways; vRegTest1Implementation() is created in Privileged\r
+ * mode and copies the queue handle to its local stack before setting itself to\r
+ * User mode, and vRegTest2Implementation() receives the task handle using its\r
+ * parameter.\r
+ */\r
+extern void vRegTest1Implementation( void *pvParameters );\r
+extern void vRegTest2Implementation( void *pvParameters );\r
+\r
+/*\r
+ * The second two register test tasks are similar to the first two, but do test\r
+ * the floating point registers, execute in Privileged mode, and signal their\r
+ * execution status to the 'check' task by incrementing a loop counter on each\r
+ * iteration instead of sending a message on a queue.  The loop counters use a\r
+ * memory region to which the User mode 'check' task has read access.\r
+ *\r
+ * The functions ending 'Implementation' are called by the register check tasks.\r
+ *\r
+ * The tasks are created with xTaskCreateStatic(), so the stack and variables\r
+ * used to hold the task's data structures also have to be provided.\r
+ */\r
+static StackType_t xRegTest3Stack[ configMINIMAL_STACK_SIZE ], xRegTest4Stack[ configMINIMAL_STACK_SIZE ];\r
+static StaticTask_t xRegTest3Buffer, xRegTest4Buffer;\r
+static void prvRegTest3Task( void *pvParameters );\r
+extern void vRegTest3Implementation( void );\r
+static void prvRegTest4Task( void *pvParameters );\r
+extern void vRegTest4Implementation( void );\r
+\r
+/*\r
+ * Prototype for the check task.  The check task demonstrates various features\r
+ * of the MPU before entering a loop where it waits for messages to arrive on a\r
+ * queue.\r
+ *\r
+ * Two types of messages can be processes:\r
+ *\r
+ * 1) "I'm Alive" messages sent from the first two register test tasks and a\r
+ *    software timer callback, as described above.\r
+ *\r
+ * 2) "Print Status commands" sent periodically by the tick hook function (and\r
+ *    therefore from within an interrupt) which commands the check task to write\r
+ *    either pass or fail to the terminal, depending on the status of the reg\r
+ *    test tasks (no write is performed in the simulator!).\r
+ */\r
+static void prvCheckTask( void *pvParameters );\r
+\r
+/*\r
+ * Prototype for a task created in User mode using vTaskCreateStatic() API\r
+ * function.  The task demonstrates the characteristics of such a task,\r
+ * before simply deleting itself.  As the task is created without using any\r
+ * dynamic memory allocate the stack and variable in which the task's data\r
+ * structure will be stored must also be provided - however the task is\r
+ * unprivileged so the stack cannot be in a privileged section.\r
+ */\r
+static StackType_t xUserModeTaskStack[ configMINIMAL_STACK_SIZE ];\r
+static PRIVILEGED_DATA StaticTask_t xUserModeTaskBuffer;\r
+static void prvOldStyleUserModeTask( void *pvParameters );\r
+\r
+/*\r
+ * Prototype for a task created in Privileged mode using the\r
+ * xTaskCreateStatic() API function.  The task demonstrates the characteristics\r
+ * of such a task, before simply deleting itself.  As no dynamic memory\r
+ * allocation is used the stack and variable used to hold the task's data\r
+ * structure must also be provided.  The task is privileged, so the stack can\r
+ * be in a privileged section.\r
+ */\r
+static PRIVILEGED_DATA StackType_t xPrivilegedModeTaskStack[ configMINIMAL_STACK_SIZE ];\r
+static PRIVILEGED_DATA StaticTask_t xPrivilegedModeTaskBuffer;\r
+static void prvOldStylePrivilegedModeTask( void *pvParameters );\r
+\r
+/*\r
+ * A task that exercises the API of various RTOS objects before being deleted by\r
+ * the Idle task.  This is done for MPU API code coverage test purposes.\r
+ */\r
+static void prvTaskToDelete( void *pvParameters );\r
+\r
+/*\r
+ * Functions called by prvTaskToDelete() to exercise the MPU API.\r
+ */\r
+static void prvExerciseEventGroupAPI( void );\r
+static void prvExerciseSemaphoreAPI( void );\r
+static void prvExerciseTaskNotificationAPI( void );\r
+\r
+/*\r
+ * Just configures any clocks and IO necessary.\r
+ */\r
+static void prvSetupHardware( void );\r
+\r
+/*\r
+ * Simply deletes the calling task.  The function is provided only because it\r
+ * is simpler to call from asm code than the normal vTaskDelete() API function.\r
+ * It has the noinline attribute because it is called from asm code.\r
+ */\r
+void vMainDeleteMe( void ) __attribute__((noinline));\r
+\r
+/*\r
+ * Used by the first two reg test tasks and a software timer callback function\r
+ * to send messages to the check task.  The message just lets the check task\r
+ * know that the tasks and timer are still functioning correctly.  If a reg test\r
+ * task detects an error it will delete itself, and in so doing prevent itself\r
+ * from sending any more 'I'm Alive' messages to the check task.\r
+ */\r
+void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber );\r
+\r
+/*\r
+ * The check task is created with access to three memory regions (plus its\r
+ * stack).  Each memory region is configured with different parameters and\r
+ * prvTestMemoryRegions() demonstrates what can and cannot be accessed for each\r
+ * region.  prvTestMemoryRegions() also demonstrates a task that was created\r
+ * as a privileged task settings its own privilege level down to that of a user\r
+ * task.\r
+ */\r
+static void prvTestMemoryRegions( void );\r
+\r
+/*\r
+ * Callback function used with the timer that uses the queue to send messages\r
+ * to the check task.\r
+ */\r
+static void prvTimerCallback( TimerHandle_t xExpiredTimer );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The handle of the queue used to communicate between tasks and between tasks\r
+and interrupts.  Note that this is a global scope variable that falls outside of\r
+any MPU region.  As such other techniques have to be used to allow the tasks\r
+to gain access to the queue.  See the comments in the tasks themselves for\r
+further information. */\r
+QueueHandle_t xGlobalScopeCheckQueue = NULL;\r
+\r
+/* xGlobalScopeCheckQueue is created using xQueueCreateStatic(), so the storage\r
+area and variable used to hold the queue data structure must also be provided.\r
+These are placed in a prviliged segment. */\r
+static PRIVILEGED_DATA StaticQueue_t xGlobalScopeQueueBuffer;\r
+uint8_t PRIVILEGED_DATA ucGlobalScopeQueueStorageArea[ 1 * sizeof( uint32_t ) ];\r
+\r
+\r
+/* Holds the handle of a task that is deleted in the idle task hook - this is\r
+done for code coverage test purposes only. */\r
+static TaskHandle_t xTaskToDelete = NULL;\r
+\r
+/* The timer that periodically sends data to the check task on the queue.  This\r
+is created with xTimerCreateStatic(), so the variable in which the timer's data\r
+structure will be stored must also be provided.  The structure is placed in the\r
+kernel's privileged data region. */\r
+static TimerHandle_t xTimer = NULL;\r
+static PRIVILEGED_DATA StaticTimer_t xTimerBuffer;\r
+\r
+#if defined ( __GNUC__ )\r
+       extern uint32_t __FLASH_segment_start__[];\r
+       extern uint32_t __FLASH_segment_end__[];\r
+       extern uint32_t __SRAM_segment_start__[];\r
+       extern uint32_t __SRAM_segment_end__[];\r
+       extern uint32_t __privileged_functions_start__[];\r
+       extern uint32_t __privileged_functions_end__[];\r
+       extern uint32_t __privileged_data_start__[];\r
+       extern uint32_t __privileged_data_end__[];\r
+       extern uint32_t __privileged_functions_actual_end__[];\r
+       extern uint32_t __privileged_data_actual_end__[];\r
+#else\r
+       const uint32_t * __FLASH_segment_start__ = ( uint32_t * ) 0x00UL;\r
+       const uint32_t * __FLASH_segment_end__ = ( uint32_t * ) 0x00080000UL;\r
+       const uint32_t * __SRAM_segment_start__ = ( uint32_t * ) 0x20000000UL;\r
+       const uint32_t * __SRAM_segment_end__ = ( uint32_t * ) 0x20008000UL;\r
+       const uint32_t * __privileged_functions_start__ = ( uint32_t * ) 0x00UL;\r
+       const uint32_t * __privileged_functions_end__ = ( uint32_t * ) 0x8000UL;\r
+       const uint32_t * __privileged_data_start__ = ( uint32_t * ) 0x20000000UL;\r
+       const uint32_t * __privileged_data_end__ = ( uint32_t * ) 0x20000800UL;\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+/* Data used by the 'check' task. ---------------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Define the constants used to allocate the check task stack.  Note that the\r
+stack size is defined in words, not bytes. */\r
+#define mainCHECK_TASK_STACK_SIZE_WORDS        128\r
+#define mainCHECK_TASK_STACK_ALIGNMENT ( mainCHECK_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )\r
+\r
+/* Declare the stack that will be used by the check task.  The kernel will\r
+automatically create an MPU region for the stack.  The stack alignment must\r
+match its size, so if 128 words are reserved for the stack then it must be\r
+aligned to ( 128 * 4 ) bytes. */\r
+static portSTACK_TYPE xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainCHECK_TASK_STACK_ALIGNMENT );\r
+\r
+/* Declare the variable in which the check task's data structures will be\r
+stored.  PRIVILEGED_DATA is used to place this in the kernel's RAM segment. */\r
+static PRIVILEGED_DATA StaticTask_t xCheckTaskBuffer;\r
+\r
+/* Declare three arrays - an MPU region will be created for each array\r
+using the TaskParameters_t structure below.  THIS IS JUST TO DEMONSTRATE THE\r
+MPU FUNCTIONALITY, the data is not used by the check tasks primary function\r
+of monitoring the reg test tasks and printing out status information.\r
+\r
+Note that the arrays allocate slightly more RAM than is actually assigned to\r
+the MPU region.  This is to permit writes off the end of the array to be\r
+detected even when the arrays are placed in adjacent memory locations (with no\r
+gaps between them).  The align size must be a power of two. */\r
+#define mainREAD_WRITE_ARRAY_SIZE 130\r
+#define mainREAD_WRITE_ALIGN_SIZE 128\r
+char cReadWriteArray[ mainREAD_WRITE_ARRAY_SIZE ] mainALIGN_TO( mainREAD_WRITE_ALIGN_SIZE );\r
+\r
+#define mainREAD_ONLY_ARRAY_SIZE 260\r
+#define mainREAD_ONLY_ALIGN_SIZE 256\r
+char cReadOnlyArray[ mainREAD_ONLY_ARRAY_SIZE ] mainALIGN_TO( mainREAD_ONLY_ALIGN_SIZE );\r
+\r
+#define mainPRIVILEGED_ONLY_ACCESS_ARRAY_SIZE 130\r
+#define mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE 128\r
+char cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] mainALIGN_TO( mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE );\r
+\r
+/* The following two variables are used to communicate the status of the second\r
+two register check tasks (tasks 3 and 4) to the check task.  If the variables\r
+keep incrementing, then the register check tasks have not discovered any errors.\r
+If a variable stops incrementing, then an error has been found.  The variables\r
+overlay the array that the check task has access to so they can be read by the\r
+check task without causing a memory fault.  The check task has the highest\r
+priority so will have finished with the array before the register test tasks\r
+start to access it. */\r
+volatile uint32_t *pulRegTest3LoopCounter = ( uint32_t * ) &( cReadWriteArray[ 0 ] ), *pulRegTest4LoopCounter = ( uint32_t * ) &( cReadWriteArray[ 4 ] );\r
+\r
+/* Fill in a TaskParameters_t structure to define the check task - this is the\r
+structure passed to the xTaskCreateRestricted() function. */\r
+static const TaskParameters_t xCheckTaskParameters =\r
+{\r
+       prvCheckTask,                                                           /* pvTaskCode - the function that implements the task. */\r
+       "Check",                                                                        /* pcName */\r
+       mainCHECK_TASK_STACK_SIZE_WORDS,                        /* usStackDepth - defined in words, not bytes. */\r
+       ( void * ) 0x12121212,                                          /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */\r
+       ( 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. */\r
+       xCheckTaskStack,                                                        /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+\r
+       /* xRegions - In this case the xRegions array is used to create MPU regions\r
+       for all three of the arrays declared directly above.  Each MPU region is\r
+       created with different parameters.  Again, THIS IS JUST TO DEMONSTRATE THE\r
+       MPU FUNCTIONALITY, the data is not used by the check tasks primary function\r
+       of monitoring the reg test tasks and printing out status information.*/\r
+       {\r
+               /* Base address                                 Length                                                                  Parameters */\r
+               { cReadWriteArray,                              mainREAD_WRITE_ALIGN_SIZE,                              portMPU_REGION_READ_WRITE },\r
+               { cReadOnlyArray,                               mainREAD_ONLY_ALIGN_SIZE,                               portMPU_REGION_READ_ONLY },\r
+               { cPrivilegedOnlyAccessArray,   mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE,  portMPU_REGION_PRIVILEGED_READ_WRITE }\r
+       },\r
+\r
+       &xCheckTaskBuffer                                                       /* Additional structure member present when the task is being created without any dynamic memory allocation. */\r
+};\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Data used by the 'reg test' tasks. -----------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Define the constants used to allocate the reg test task stacks.  Note that\r
+that stack size is defined in words, not bytes. */\r
+#define mainREG_TEST_STACK_SIZE_WORDS  128\r
+#define mainREG_TEST_STACK_ALIGNMENT   ( mainREG_TEST_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )\r
+\r
+/* Declare the stacks that will be used by the reg test tasks.  The kernel will\r
+automatically create an MPU region for the stack.  The stack alignment must\r
+match its size, so if 128 words are reserved for the stack then it must be\r
+aligned to ( 128 * 4 ) bytes. */\r
+static portSTACK_TYPE xRegTest1Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT );\r
+static portSTACK_TYPE xRegTest2Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT );\r
+\r
+/* The reg test tasks are created using the xTaskCreateRestrictedStatic() API\r
+function, so variables that hold the task's data structures must also be\r
+provided.  The are placed in the kernel's privileged memory section. */\r
+static PRIVILEGED_DATA StaticTask_t xRegTest1TaskBuffer, xRegTest2TaskBuffer;\r
+\r
+/* Fill in a TaskParameters_t structure per reg test task to define the tasks. */\r
+static const TaskParameters_t xRegTest1Parameters =\r
+{\r
+       vRegTest1Implementation,                                                        /* pvTaskCode - the function that implements the task. */\r
+       "RegTest1",                                                                     /* pcName                       */\r
+       mainREG_TEST_STACK_SIZE_WORDS,                          /* usStackDepth         */\r
+       ( void * ) configREG_TEST_TASK_1_PARAMETER,     /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */\r
+       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. */\r
+       xRegTest1Stack,                                                         /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+       {                                                                                       /* xRegions - this task does not use any non-stack data hence all members are zero. */\r
+               /* Base address         Length          Parameters */\r
+               { 0x00,                         0x00,                   0x00 },\r
+               { 0x00,                         0x00,                   0x00 },\r
+               { 0x00,                         0x00,                   0x00 }\r
+       },\r
+\r
+       &xRegTest1TaskBuffer                                            /* Additional parameter required when the task is created with xTaskCreateRestrictedStatic(). */\r
+};\r
+/*-----------------------------------------------------------*/\r
+\r
+static TaskParameters_t xRegTest2Parameters =\r
+{\r
+       vRegTest2Implementation,                                /* pvTaskCode - the function that implements the task. */\r
+       "RegTest2",                                             /* pcName                       */\r
+       mainREG_TEST_STACK_SIZE_WORDS,  /* usStackDepth         */\r
+       ( void * ) NULL,                                /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */\r
+       tskIDLE_PRIORITY,                               /* uxPriority           */\r
+       xRegTest2Stack,                                 /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+       {                                                               /* xRegions - this task does not use any non-stack data hence all members are zero. */\r
+               /* Base address         Length          Parameters */\r
+               { 0x00,                         0x00,                   0x00 },\r
+               { 0x00,                         0x00,                   0x00 },\r
+               { 0x00,                         0x00,                   0x00 }\r
+       },\r
+\r
+       &xRegTest2TaskBuffer                    /* Additional parameter required when the task is created with xTaskCreateRestrictedStatic(). */\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Configures the task that is deleted. ---------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Define the constants used to allocate the stack of the task that is\r
+deleted.  Note that the stack size is defined in words, not bytes. */\r
+#define mainDELETE_TASK_STACK_SIZE_WORDS       128\r
+#define mainTASK_TO_DELETE_STACK_ALIGNMENT     ( mainDELETE_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )\r
+\r
+/* Declare the stack that will be used by the task that gets deleted.  The\r
+kernel will automatically create an MPU region for the stack.  The stack\r
+alignment must match its size, so if 128 words are reserved for the stack\r
+then it must be aligned to ( 128 * 4 ) bytes. */\r
+static portSTACK_TYPE xDeleteTaskStack[ mainDELETE_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainTASK_TO_DELETE_STACK_ALIGNMENT );\r
+\r
+/* The task that gets deleted is created using xTaskCreateRestrictedStatic(),\r
+so the variable that stores the task's data structure must also be provided.\r
+This is placed in the kernel's privileged data segment. */\r
+static PRIVILEGED_DATA StaticTask_t xStaticDeleteTaskBuffer;\r
+\r
+static TaskParameters_t xTaskToDeleteParameters =\r
+{\r
+       prvTaskToDelete,                                        /* pvTaskCode - the function that implements the task. */\r
+       mainTASK_TO_DELETE_NAME,                        /* pcName */\r
+       mainDELETE_TASK_STACK_SIZE_WORDS,       /* usStackDepth */\r
+       ( void * ) NULL,                                        /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */\r
+       tskIDLE_PRIORITY + 1,                           /* uxPriority */\r
+       xDeleteTaskStack,                                       /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+       {                                                                       /* xRegions - this task does not use any non-stack data hence all members are zero. */\r
+               /* Base address         Length          Parameters */\r
+               { 0x00,                         0x00,                   0x00 },\r
+               { 0x00,                         0x00,                   0x00 },\r
+               { 0x00,                         0x00,                   0x00 }\r
+       },\r
+\r
+       &xStaticDeleteTaskBuffer                        /* Additional parameter required when xTaskCreateRestrictedStatic() is used. */\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+volatile uint32_t ul1 = 0x123, ul2 = 0;\r
+\r
+int main( void )\r
+{\r
+       configASSERT( ul1 == 0x123 );\r
+       configASSERT( ul2 == 0 );\r
+       prvSetupHardware();\r
+\r
+       /* Create the queue used to pass "I'm alive" messages to the check task. */\r
+       xGlobalScopeCheckQueue = xQueueCreateStatic( 1, sizeof( uint32_t ), ucGlobalScopeQueueStorageArea, &xGlobalScopeQueueBuffer );\r
+\r
+       /* One check task uses the task parameter to receive the queue handle.\r
+       This allows the file scope variable to be accessed from within the task.\r
+       The pvParameters member of xRegTest2Parameters can only be set after the\r
+       queue has been created so is set here. */\r
+       xRegTest2Parameters.pvParameters = xGlobalScopeCheckQueue;\r
+\r
+       /* Create three test tasks.  Handles to the created tasks are not required,\r
+       hence the second parameter is NULL. */\r
+       xTaskCreateRestrictedStatic( &xRegTest1Parameters, NULL );\r
+    xTaskCreateRestrictedStatic( &xRegTest2Parameters, NULL );\r
+       xTaskCreateRestrictedStatic( &xCheckTaskParameters, NULL );\r
+\r
+       /* Create a task that does nothing but ensure some of the MPU API functions\r
+       can be called correctly, then get deleted.  This is done for code coverage\r
+       test purposes only.  The task's handle is saved in xTaskToDelete so it can\r
+       get deleted in the idle task hook. */\r
+       xTaskCreateRestrictedStatic( &xTaskToDeleteParameters, &xTaskToDelete );\r
+\r
+       /* Create the tasks that are created using the original xTaskCreate() API\r
+       function. */\r
+       xTaskCreateStatic(      prvOldStyleUserModeTask,        /* The function that implements the task. */\r
+                                               "Task1",                                        /* Text name for the task. */\r
+                                               100,                                            /* Stack depth in words. */\r
+                                               NULL,                                           /* Task parameters. */\r
+                                               3,                                                      /* Priority and mode (user in this case). */\r
+                                               xUserModeTaskStack,                     /* Used as the task's stack. */\r
+                                               &xUserModeTaskBuffer            /* Used to hold the task's data structure. */\r
+                                       );\r
+\r
+       xTaskCreateStatic(      prvOldStylePrivilegedModeTask,  /* The function that implements the task. */\r
+                                               "Task2",                                                /* Text name for the task. */\r
+                                               100,                                                    /* Stack depth in words. */\r
+                                               NULL,                                                   /* Task parameters. */\r
+                                               ( 3 | portPRIVILEGE_BIT ),              /* Priority and mode. */\r
+                                               xPrivilegedModeTaskStack,               /* Used as the task's stack. */\r
+                                               &xPrivilegedModeTaskBuffer              /* Used to hold the task's data structure. */\r
+                                       );\r
+\r
+       /* Create the third and fourth register check tasks, as described at the top\r
+       of this file. */\r
+       xTaskCreateStatic( prvRegTest3Task, "Reg3", configMINIMAL_STACK_SIZE, configREG_TEST_TASK_3_PARAMETER, tskIDLE_PRIORITY, xRegTest3Stack, &xRegTest3Buffer );\r
+       xTaskCreateStatic( prvRegTest4Task, "Reg4", configMINIMAL_STACK_SIZE, configREG_TEST_TASK_4_PARAMETER, tskIDLE_PRIORITY, xRegTest4Stack, &xRegTest4Buffer );\r
+\r
+       /* Create and start the software timer. */\r
+       xTimer = xTimerCreateStatic( "Timer",                   /* Test name for the timer. */\r
+                                                                mainTIMER_PERIOD,      /* Period of the timer. */\r
+                                                                pdTRUE,                        /* The timer will auto-reload itself. */\r
+                                                                ( void * ) 0,          /* The timer's ID is used to count the number of times it expires - initialise this to 0. */\r
+                                                                prvTimerCallback,      /* The function called when the timer expires. */\r
+                                                                &xTimerBuffer );       /* The variable in which the created timer's data structure will be stored. */\r
+       configASSERT( xTimer );\r
+       xTimerStart( xTimer, mainDONT_BLOCK );\r
+\r
+       /* Start the scheduler. */\r
+       vTaskStartScheduler();\r
+\r
+       /* Will only get here if there was insufficient memory to create the idle\r
+       task. */\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckTask( void *pvParameters )\r
+{\r
+/* This task is created in privileged mode so can access the file scope\r
+queue variable.  Take a stack copy of this before the task is set into user\r
+mode.  Once that task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+QueueHandle_t xQueue = xGlobalScopeCheckQueue;\r
+int32_t lMessage;\r
+uint32_t ulStillAliveCounts[ 3 ] = { 0 };\r
+const char *pcStatusMessage = "PASS\r\n";\r
+uint32_t ulLastRegTest3CountValue = 0, ulLastRegTest4Value = 0;\r
+\r
+/* The register test tasks that also test the floating point registers increment\r
+a counter on each iteration of their loop.  The counters are inside the array\r
+that this task has access to. */\r
+volatile uint32_t *pulOverlaidCounter3 = ( uint32_t * ) &( cReadWriteArray[ 0 ] ), *pulOverlaidCounter4 = ( uint32_t * ) &( cReadWriteArray[ 4 ] );\r
+\r
+/* ulCycleCount is incremented on each cycle of the check task.  It can be\r
+viewed updating in the Keil watch window as the simulator does not print to\r
+the ITM port. */\r
+volatile uint32_t ulCycleCount = 0;\r
+\r
+       /* Just to remove compiler warning. */\r
+       ( void ) pvParameters;\r
+\r
+       /* Demonstrate how the various memory regions can and can't be accessed.\r
+       The task privilege level is set down to user mode within this function. */\r
+       prvTestMemoryRegions();\r
+\r
+       /* Clear overlaid reg test counters before entering the loop below. */\r
+       *pulOverlaidCounter3 = 0UL;\r
+       *pulOverlaidCounter4 = 0UL;\r
+\r
+       /* This loop performs the main function of the task, which is blocking\r
+       on a message queue then processing each message as it arrives. */\r
+       for( ;; )\r
+       {\r
+               /* Wait for the next message to arrive. */\r
+               xQueueReceive( xQueue, &lMessage, portMAX_DELAY );\r
+\r
+               switch( lMessage )\r
+               {\r
+                       case configREG_TEST_1_STILL_EXECUTING   :\r
+                       case configREG_TEST_2_STILL_EXECUTING   :\r
+                       case configTIMER_STILL_EXECUTING                :\r
+                                       /* Message from the first or second register check task, or\r
+                                       the timer callback function.  Increment the count of the\r
+                                       number of times the message source has sent the message as\r
+                                       the message source must still be executed. */\r
+                                       ( ulStillAliveCounts[ lMessage ] )++;\r
+                                       break;\r
+\r
+                       case configPRINT_SYSTEM_STATUS          :\r
+                                       /* Message from tick hook, time to print out the system\r
+                                       status.  If messages have stopped arriving from either of\r
+                                       the first two reg test task or the timer callback then the\r
+                                       status must be set to fail. */\r
+                                       if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 ) || ( ulStillAliveCounts[ 2 ] == 0 ) )\r
+                                       {\r
+                                               /* One or both of the test tasks are no longer sending\r
+                                               'still alive' messages. */\r
+                                               pcStatusMessage = "FAIL\r\n";\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Reset the count of 'still alive' messages. */\r
+                                               memset( ( void * ) ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );\r
+                                       }\r
+\r
+                                       /* Check that the register test 3 task is still incrementing\r
+                                       its counter, and therefore still running. */\r
+                                       if( ulLastRegTest3CountValue == *pulOverlaidCounter3 )\r
+                                       {\r
+                                               pcStatusMessage = "FAIL\r\n";\r
+                                       }\r
+                                       ulLastRegTest3CountValue = *pulOverlaidCounter3;\r
+\r
+                                       /* Check that the register test 4 task is still incrementing\r
+                                       its counter, and therefore still running. */\r
+                                       if( ulLastRegTest4Value == *pulOverlaidCounter4 )\r
+                                       {\r
+                                               pcStatusMessage = "FAIL\r\n";\r
+                                       }\r
+                                       ulLastRegTest4Value = *pulOverlaidCounter4;\r
+\r
+                                       /**** Print pcStatusMessage here. ****/\r
+                                       ( void ) pcStatusMessage;\r
+\r
+                                       /* The cycle count can be viewed updating in the Keil watch\r
+                                       window if ITM printf is not being used. */\r
+                                       ulCycleCount++;\r
+                                       break;\r
+\r
+               default :\r
+                                       /* Something unexpected happened.  Delete this task so the\r
+                                       error is apparent (no output will be displayed). */\r
+                                       vMainDeleteMe();\r
+                                       break;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTestMemoryRegions( void )\r
+{\r
+int32_t x;\r
+char cTemp;\r
+\r
+       /* The check task (from which this function is called) is created in the\r
+       Privileged mode.  The privileged array can be both read from and written\r
+       to while this task is privileged. */\r
+       cPrivilegedOnlyAccessArray[ 0 ] = 'a';\r
+       if( cPrivilegedOnlyAccessArray[ 0 ] != 'a' )\r
+       {\r
+               /* Something unexpected happened.  Delete this task so the error is\r
+               apparent (no output will be displayed). */\r
+               vMainDeleteMe();\r
+       }\r
+\r
+       /* Writing off the end of the RAM allocated to this task will *NOT* cause a\r
+       protection fault because the task is still executing in a privileged mode.\r
+       Uncomment the following to test. */\r
+       /*cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] = 'a';*/\r
+\r
+       /* Now set the task into user mode. */\r
+       portSWITCH_TO_USER_MODE();\r
+\r
+       /* Accessing the privileged only array will now cause a fault.  Uncomment\r
+       the following line to test. */\r
+       /*cPrivilegedOnlyAccessArray[ 0 ] = 'a';*/\r
+\r
+       /* The read/write array can still be successfully read and written. */\r
+       for( x = 0; x < mainREAD_WRITE_ALIGN_SIZE; x++ )\r
+       {\r
+               cReadWriteArray[ x ] = 'a';\r
+               if( cReadWriteArray[ x ] != 'a' )\r
+               {\r
+                       /* Something unexpected happened.  Delete this task so the error is\r
+                       apparent (no output will be displayed). */\r
+                       vMainDeleteMe();\r
+               }\r
+       }\r
+\r
+       /* But attempting to read or write off the end of the RAM allocated to this\r
+       task will cause a fault.  Uncomment either of the following two lines to\r
+       test. */\r
+       /* cReadWriteArray[ 0 ] = cReadWriteArray[ -1 ]; */\r
+       /* cReadWriteArray[ mainREAD_WRITE_ALIGN_SIZE ] = 0x00; */\r
+\r
+       /* The read only array can be successfully read... */\r
+       for( x = 0; x < mainREAD_ONLY_ALIGN_SIZE; x++ )\r
+       {\r
+               cTemp = cReadOnlyArray[ x ];\r
+       }\r
+\r
+       /* ...but cannot be written.  Uncomment the following line to test. */\r
+       /* cReadOnlyArray[ 0 ] = 'a'; */\r
+\r
+       /* Writing to the first and last locations in the stack array should not\r
+       cause a protection fault.  Note that doing this will cause the kernel to\r
+       detect a stack overflow if configCHECK_FOR_STACK_OVERFLOW is greater than\r
+       1, hence the test is commented out by default. */\r
+       /* xCheckTaskStack[ 0 ] = 0;\r
+       xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS - 1 ] = 0; */\r
+\r
+       /* Writing off either end of the stack array should cause a protection\r
+       fault, uncomment either of the following two lines to test. */\r
+       /* xCheckTaskStack[ -1 ] = 0; */\r
+       /* xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] = 0; */\r
+\r
+       ( void ) cTemp;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExerciseEventGroupAPI( void )\r
+{\r
+EventGroupHandle_t xEventGroup;\r
+StaticEventGroup_t xEventGroupBuffer;\r
+EventBits_t xBits;\r
+const EventBits_t xBitsToWaitFor = ( EventBits_t ) 0xff, xBitToClear = ( EventBits_t ) 0x01;\r
+\r
+       /* Exercise some event group functions. */\r
+       xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );\r
+       configASSERT( xEventGroup );\r
+\r
+       /* No bits should be set. */\r
+       xBits = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdFALSE, mainDONT_BLOCK );\r
+       configASSERT( xBits == ( EventBits_t ) 0 );\r
+\r
+       /* Set bits and read back to ensure the bits were set. */\r
+       xEventGroupSetBits( xEventGroup, xBitsToWaitFor );\r
+       xBits = xEventGroupGetBits( xEventGroup );\r
+       configASSERT( xBits == xBitsToWaitFor );\r
+\r
+       /* Clear a bit and read back again using a different API function. */\r
+       xEventGroupClearBits( xEventGroup, xBitToClear );\r
+       xBits = xEventGroupSync( xEventGroup, 0x00, xBitsToWaitFor, mainDONT_BLOCK );\r
+       configASSERT( xBits == ( xBitsToWaitFor & ~xBitToClear ) );\r
+\r
+       /* Finished with the event group. */\r
+       vEventGroupDelete( xEventGroup );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExerciseSemaphoreAPI( void )\r
+{\r
+SemaphoreHandle_t xSemaphore;\r
+StaticSemaphore_t xSemaphoreBuffer;\r
+const UBaseType_t uxMaxCount = 5, uxInitialCount = 0;\r
+\r
+       /* Most of the semaphore API is common to the queue API and is already being\r
+       used.  This function uses a few semaphore functions that are unique to the\r
+       RTOS objects, rather than generic and used by queues also.\r
+\r
+       First create and use a counting semaphore. */\r
+       xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, &xSemaphoreBuffer );\r
+       configASSERT( xSemaphore );\r
+\r
+       /* Give the semaphore a couple of times and ensure the count is returned\r
+       correctly. */\r
+       xSemaphoreGive( xSemaphore );\r
+       xSemaphoreGive( xSemaphore );\r
+       configASSERT( uxSemaphoreGetCount( xSemaphore ) == 2 );\r
+       vSemaphoreDelete( xSemaphore );\r
+\r
+       /* Create a recursive mutex, and ensure the mutex holder and count are\r
+       returned returned correctly. */\r
+       xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );\r
+       configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 );\r
+       configASSERT( xSemaphore );\r
+       xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK );\r
+       xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK );\r
+       configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() );\r
+       configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetHandle( mainTASK_TO_DELETE_NAME ) );\r
+       xSemaphoreGiveRecursive( xSemaphore );\r
+       configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );\r
+       xSemaphoreGiveRecursive( xSemaphore );\r
+       configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 );\r
+       configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL );\r
+       vSemaphoreDelete( xSemaphore );\r
+\r
+       /* Create a normal mutex, and sure the mutex holder and count are returned\r
+       returned correctly. */\r
+       xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );\r
+       configASSERT( xSemaphore );\r
+       xSemaphoreTake( xSemaphore, mainDONT_BLOCK );\r
+       xSemaphoreTake( xSemaphore, mainDONT_BLOCK );\r
+       configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); /* Not recursive so can only be 1. */\r
+       configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() );\r
+       xSemaphoreGive( xSemaphore );\r
+       configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 );\r
+       configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL );\r
+       vSemaphoreDelete( xSemaphore );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExerciseTaskNotificationAPI( void )\r
+{\r
+uint32_t ulNotificationValue;\r
+BaseType_t xReturned;\r
+\r
+       /* The task should not yet have a notification pending. */\r
+       xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK );\r
+       configASSERT( xReturned == pdFAIL );\r
+       configASSERT( ulNotificationValue == 0UL );\r
+\r
+       /* Exercise the 'give' and 'take' versions of the notification API. */\r
+       xTaskNotifyGive( xTaskGetCurrentTaskHandle() );\r
+       xTaskNotifyGive( xTaskGetCurrentTaskHandle() );\r
+       ulNotificationValue = ulTaskNotifyTake( pdTRUE, mainDONT_BLOCK );\r
+       configASSERT( ulNotificationValue == 2 );\r
+\r
+       /* Exercise the 'notify' and 'clear' API. */\r
+       ulNotificationValue = 20;\r
+       xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite );\r
+       ulNotificationValue = 0;\r
+       xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK );\r
+       configASSERT( xReturned == pdPASS );\r
+       configASSERT( ulNotificationValue == 20 );\r
+       xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite );\r
+       xReturned = xTaskNotifyStateClear( NULL );\r
+       configASSERT( xReturned == pdTRUE ); /* First time a notification was pending. */\r
+       xReturned = xTaskNotifyStateClear( NULL );\r
+       configASSERT( xReturned == pdFALSE ); /* Second time the notification was already clear. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTaskToDelete( void *pvParameters )\r
+{\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* Check the enter and exit critical macros are working correctly.  If the\r
+       SVC priority is below configMAX_SYSCALL_INTERRUPT_PRIORITY then this will\r
+       fault. */\r
+       taskENTER_CRITICAL();\r
+       taskEXIT_CRITICAL();\r
+\r
+       /* Exercise the API of various RTOS objects. */\r
+       prvExerciseEventGroupAPI();\r
+       prvExerciseSemaphoreAPI();\r
+       prvExerciseTaskNotificationAPI();\r
+\r
+       /* For code coverage test purposes it is deleted by the Idle task. */\r
+       configASSERT( uxTaskGetStackHighWaterMark( NULL ) > 0 );\r
+       vTaskSuspend( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationIdleHook( void )\r
+{\r
+volatile const uint32_t *pul;\r
+volatile uint32_t ulReadData;\r
+\r
+       /* The idle task, and therefore this function, run in Supervisor mode and\r
+       can therefore access all memory.  Try reading from corners of flash and\r
+       RAM to ensure a memory fault does not occur.\r
+\r
+       Start with the edges of the privileged data area. */\r
+       pul = __privileged_data_start__;\r
+       ulReadData = *pul;\r
+       pul = __privileged_data_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Next the standard SRAM area. */\r
+       pul = __SRAM_segment_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* And the standard Flash area - the start of which is marked for\r
+       privileged access only. */\r
+       pul = __FLASH_segment_start__;\r
+       ulReadData = *pul;\r
+       pul = __FLASH_segment_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Reading off the end of Flash or SRAM space should cause a fault.\r
+       Uncomment one of the following two pairs of lines to test. */\r
+\r
+       /* pul = __FLASH_segment_end__ + 4;\r
+       ulReadData = *pul; */\r
+\r
+       /* pul = __SRAM_segment_end__ + 1;\r
+       ulReadData = *pul; */\r
+\r
+       /* One task is created purely so it can be deleted - done for code coverage\r
+       test purposes. */\r
+       if( xTaskToDelete != NULL )\r
+       {\r
+               vTaskDelete( xTaskToDelete );\r
+               xTaskToDelete = NULL;\r
+       }\r
+\r
+       ( void ) ulReadData;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOldStyleUserModeTask( void *pvParameters )\r
+{\r
+/*const volatile uint32_t *pulStandardPeripheralRegister = ( volatile uint32_t * ) 0x40000000;*/\r
+volatile const uint32_t *pul;\r
+volatile uint32_t ulReadData;\r
+\r
+/* The following lines are commented out to prevent the unused variable\r
+compiler warnings when the tests that use the variable are also commented out. */\r
+/* extern uint32_t __privileged_functions_start__[]; */\r
+/* const volatile uint32_t *pulSystemPeripheralRegister = ( volatile uint32_t * ) 0xe000e014; */\r
+\r
+       ( void ) pvParameters;\r
+\r
+       /* This task is created in User mode using the original xTaskCreate() API\r
+       function.  It should have access to all Flash and RAM except that marked\r
+       as Privileged access only.  Reading from the start and end of the non-\r
+       privileged RAM should not cause a problem (the privileged RAM is the first\r
+       block at the bottom of the RAM memory). */\r
+       pul = __privileged_data_end__ + 1;\r
+       ulReadData = *pul;\r
+       pul = __SRAM_segment_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Likewise reading from the start and end of the non-privileged Flash\r
+       should not be a problem (the privileged Flash is the first block at the\r
+       bottom of the Flash memory). */\r
+       pul = __privileged_functions_end__ + 1;\r
+       ulReadData = *pul;\r
+       pul = __FLASH_segment_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Standard peripherals are accessible. */\r
+       /*ulReadData = *pulStandardPeripheralRegister;*/\r
+\r
+       /* System peripherals are not accessible.  Uncomment the following line\r
+       to test.  Also uncomment the declaration of pulSystemPeripheralRegister\r
+       at the top of this function.\r
+       ulReadData = *pulSystemPeripheralRegister; */\r
+\r
+       /* Reading from anywhere inside the privileged Flash or RAM should cause a\r
+       fault.  This can be tested by uncommenting any of the following pairs of\r
+       lines.  Also uncomment the declaration of __privileged_functions_start__\r
+       at the top of this function. */\r
+\r
+       /*pul = __privileged_functions_start__;\r
+       ulReadData = *pul;*/\r
+\r
+       /*pul = __privileged_functions_end__ - 1;\r
+       ulReadData = *pul;*/\r
+\r
+       /*pul = __privileged_data_start__;\r
+       ulReadData = *pul;*/\r
+\r
+       /*pul = __privileged_data_end__ - 1;\r
+       ulReadData = *pul;*/\r
+\r
+       /* Must not just run off the end of a task function, so delete this task.\r
+       Note that because this task was created using xTaskCreate() the stack was\r
+       allocated dynamically and I have not included any code to free it again. */\r
+       vTaskDelete( NULL );\r
+\r
+       ( void ) ulReadData;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOldStylePrivilegedModeTask( void *pvParameters )\r
+{\r
+volatile const uint32_t *pul;\r
+volatile uint32_t ulReadData;\r
+const volatile uint32_t *pulSystemPeripheralRegister = ( volatile uint32_t * ) 0xe000e014; /* Systick */\r
+/*const volatile uint32_t *pulStandardPeripheralRegister = ( volatile uint32_t * ) 0x40000000;*/\r
+\r
+       ( void ) pvParameters;\r
+\r
+       /* This task is created in Privileged mode using the original xTaskCreate()\r
+       API     function.  It should have access to all Flash and RAM including that\r
+       marked as Privileged access only.  So reading from the start and end of the\r
+       non-privileged RAM should not cause a problem (the privileged RAM is the\r
+       first block at the bottom of the RAM memory). */\r
+       pul = __privileged_data_end__ + 1;\r
+       ulReadData = *pul;\r
+       pul = __SRAM_segment_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Likewise reading from the start and end of the non-privileged Flash\r
+       should not be a problem (the privileged Flash is the first block at the\r
+       bottom of the Flash memory). */\r
+       pul = __privileged_functions_end__ + 1;\r
+       ulReadData = *pul;\r
+       pul = __FLASH_segment_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Reading from anywhere inside the privileged Flash or RAM should also\r
+       not be a problem. */\r
+       pul = __privileged_functions_start__;\r
+       ulReadData = *pul;\r
+       pul = __privileged_functions_end__ - 1;\r
+       ulReadData = *pul;\r
+       pul = __privileged_data_start__;\r
+       ulReadData = *pul;\r
+       pul = __privileged_data_end__ - 1;\r
+       ulReadData = *pul;\r
+\r
+       /* Finally, accessing both System and normal peripherals should both be\r
+       possible. */\r
+       ulReadData = *pulSystemPeripheralRegister;\r
+       /*ulReadData = *pulStandardPeripheralRegister;*/\r
+\r
+       /* Must not just run off the end of a task function, so delete this task.\r
+       Note that because this task was created using xTaskCreate() the stack was\r
+       allocated dynamically and I have not included any code to free it again. */\r
+       vTaskDelete( NULL );\r
+\r
+       ( void ) ulReadData;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vMainDeleteMe( void )\r
+{\r
+       vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber )\r
+{\r
+       if( xHandle != NULL )\r
+       {\r
+               xQueueSend( xHandle, &ulTaskNumber, mainDONT_BLOCK );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupHardware( void )\r
+{\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+static uint32_t ulCallCount = 0;\r
+const uint32_t ulCallsBetweenSends = pdMS_TO_TICKS( 1000 );\r
+const uint32_t ulMessage = configPRINT_SYSTEM_STATUS;\r
+portBASE_TYPE xDummy;\r
+\r
+       /* If configUSE_TICK_HOOK is set to 1 then this function will get called\r
+       from each RTOS tick.  It is called from the tick interrupt and therefore\r
+       will be executing in the privileged state. */\r
+\r
+       ulCallCount++;\r
+\r
+       /* Is it time to print out the pass/fail message again? */\r
+       if( ulCallCount >= ulCallsBetweenSends )\r
+       {\r
+               ulCallCount = 0;\r
+\r
+               /* Send a message to the check task to command it to check that all\r
+               the tasks are still running then print out the status.\r
+\r
+               This is running in an ISR so has to use the "FromISR" version of\r
+               xQueueSend().  Because it is in an ISR it is running with privileges\r
+               so can access xGlobalScopeCheckQueue directly. */\r
+               xQueueSendFromISR( xGlobalScopeCheckQueue, &ulMessage, &xDummy );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
+{\r
+       /* If configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2 then this\r
+       function will automatically get called if a task overflows its stack. */\r
+       ( void ) pxTask;\r
+       ( void ) pcTaskName;\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationMallocFailedHook( void )\r
+{\r
+       /* If configUSE_MALLOC_FAILED_HOOK is set to 1 then this function will\r
+       be called automatically if a call to pvPortMalloc() fails.  pvPortMalloc()\r
+       is called automatically when a task, queue or semaphore is created. */\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTimerCallback( TaskHandle_t xExpiredTimer )\r
+{\r
+uint32_t ulCount;\r
+\r
+       /* The count of the number of times this timer has expired is saved in the\r
+       timer's ID.  Obtain the current count. */\r
+       ulCount = ( uint32_t ) pvTimerGetTimerID( xTimer );\r
+\r
+       /* Increment the count, and save it back into the timer's ID. */\r
+       ulCount++;\r
+       vTimerSetTimerID( xTimer, ( void * ) ulCount );\r
+\r
+       /* Let the check task know the timer is still running. */\r
+       vMainSendImAlive( xGlobalScopeCheckQueue, configTIMER_STILL_EXECUTING );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an\r
+implementation of vApplicationGetIdleTaskMemory() to provide the memory that is\r
+used by the Idle task. */\r
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )\r
+{\r
+/* If the buffers to be provided to the Idle task are declared inside this\r
+function then they must be declared static - otherwise they will be allocated on\r
+the stack and so not exists after this function exits. */\r
+static StaticTask_t xIdleTaskTCB;\r
+static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];\r
+\r
+       /* Pass out a pointer to the StaticTask_t structure in which the Idle task's\r
+       state will be stored. */\r
+       *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;\r
+\r
+       /* Pass out the array that will be used as the Idle task's stack. */\r
+       *ppxIdleTaskStackBuffer = uxIdleTaskStack;\r
+\r
+       /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.\r
+       Note that, as the array is necessarily of type StackType_t,\r
+       configMINIMAL_STACK_SIZE is specified in words, not bytes. */\r
+       *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the\r
+application must provide an implementation of vApplicationGetTimerTaskMemory()\r
+to provide the memory that is used by the Timer service task. */\r
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )\r
+{\r
+/* If the buffers to be provided to the Timer task are declared inside this\r
+function then they must be declared static - otherwise they will be allocated on\r
+the stack and so not exists after this function exits. */\r
+static StaticTask_t xTimerTaskTCB;\r
+static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];\r
+\r
+       /* Pass out a pointer to the StaticTask_t structure in which the Timer\r
+       task's state will be stored. */\r
+       *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;\r
+\r
+       /* Pass out the array that will be used as the Timer task's stack. */\r
+       *ppxTimerTaskStackBuffer = uxTimerTaskStack;\r
+\r
+       /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.\r
+       Note that, as the array is necessarily of type StackType_t,\r
+       configMINIMAL_STACK_SIZE is specified in words, not bytes. */\r
+       *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTest3Task( void *pvParameters )\r
+{\r
+       /* Although the regtest task is written in assembler, its entry point is\r
+       written in C for convenience of checking the task parameter is being passed\r
+       in correctly. */\r
+       if( pvParameters == configREG_TEST_TASK_3_PARAMETER )\r
+       {\r
+               /* Start the part of the test that is written in assembler. */\r
+               vRegTest3Implementation();\r
+       }\r
+\r
+       /* The following line will only execute if the task parameter is found to\r
+       be incorrect.  The check task will detect that the regtest loop counter is\r
+       not being incremented and flag an error. */\r
+       vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTest4Task( void *pvParameters )\r
+{\r
+       /* Although the regtest task is written in assembler, its entry point is\r
+       written in C for convenience of checking the task parameter is being passed\r
+       in correctly. */\r
+       if( pvParameters == configREG_TEST_TASK_4_PARAMETER )\r
+       {\r
+               /* Start the part of the test that is written in assembler. */\r
+               vRegTest4Implementation();\r
+       }\r
+\r
+       /* The following line will only execute if the task parameter is found to\r
+       be incorrect.  The check task will detect that the regtest loop counter is\r
+       not being incremented and flag an error. */\r
+       vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r