]> git.sur5r.net Git - freertos/blobdiff - Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c
Ethernet working in the Kinetis K60 demo.
[freertos] / Demo / CORTEX_MPU_LM3Sxxxx_Rowley / main.c
index 36d18ee12fff13217cf10feab0509c1793fb2a41..da12dc643da35d7f27ff292376a67ce61914fbaa 100644 (file)
@@ -1,97 +1,73 @@
 /*\r
-       FreeRTOS V5.4.2 - Copyright (C) 2009 Real Time Engineers Ltd.\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
-       **NOTE** The exception to the GPL is included to allow you to distribute a\r
-       combined work that includes FreeRTOS without being obliged to provide the\r
-       source code for proprietary components outside of the FreeRTOS kernel.\r
-       Alternative commercial license and support terms are also available upon\r
-       request.  See the licensing section of http://www.FreeRTOS.org for full\r
-       license details.\r
-\r
-       FreeRTOS is distributed in the hope that it will be useful,     but WITHOUT\r
-       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
-       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
-       more details.\r
-\r
-       You should have received a copy of the GNU General Public License along\r
-       with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59\r
-       Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
-\r
-\r
-       ***************************************************************************\r
-       *                                                                         *\r
-       * Looking for a quick start?  Then check out the FreeRTOS eBook!          *\r
-       * See http://www.FreeRTOS.org/Documentation for details                   *\r
-       *                                                                         *\r
-       ***************************************************************************\r
-\r
-       1 tab == 4 spaces!\r
-\r
-       Please ensure to read the configuration and relevant port sections of the\r
-       online documentation.\r
-\r
-       http://www.FreeRTOS.org - Documentation, latest information, license and\r
-       contact details.\r
-\r
-       http://www.SafeRTOS.com - A version that is certified for use in safety\r
-       critical systems.\r
-\r
-       http://www.OpenRTOS.com - Commercial support, development, porting,\r
-       licensing and training services.\r
+    FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+       \r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
+     *    Complete, revised, and edited pdf reference manuals are also       *\r
+     *    available.                                                         *\r
+     *                                                                       *\r
+     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
+     *    ensuring you get running as quickly as possible and with an        *\r
+     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
+     *    the FreeRTOS project to continue with its mission of providing     *\r
+     *    professional grade, cross platform, de facto standard solutions    *\r
+     *    for microcontrollers - completely free of charge!                  *\r
+     *                                                                       *\r
+     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
+     *                                                                       *\r
+     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\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
+    >>>NOTE<<< The modification to the GPL is included to allow you to\r
+    distribute a combined work that includes FreeRTOS without being obliged to\r
+    provide the source code for proprietary components outside of the FreeRTOS\r
+    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
+    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+    more details. You should have received a copy of the GNU General Public\r
+    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+    by writing to Richard Barry, contact details for whom are available on the\r
+    FreeRTOS WEB site.\r
+\r
+    1 tab == 4 spaces!\r
+\r
+    http://www.FreeRTOS.org - Documentation, latest information, license and\r
+    contact details.\r
+\r
+    http://www.SafeRTOS.com - A version that is certified for use in safety\r
+    critical systems.\r
+\r
+    http://www.OpenRTOS.com - Commercial support, development, porting,\r
+    licensing and training services.\r
 */\r
 \r
 \r
 /*\r
- * Creates all the demo application tasks, then starts the scheduler.  The WEB\r
- * documentation provides more details of the standard demo application tasks.\r
- * In addition to the standard demo tasks, the following tasks and tests are\r
- * defined and/or created within this file:\r
- *\r
- * "Fast Interrupt Test" - A high frequency periodic interrupt is generated\r
- * using a free running timer to demonstrate the use of the\r
- * configKERNEL_INTERRUPT_PRIORITY configuration constant.  The interrupt\r
- * service routine measures the number of processor clocks that occur between\r
- * each interrupt - and in so doing measures the jitter in the interrupt timing.\r
- * The maximum measured jitter time is latched in the ulMaxJitter variable, and\r
- * displayed on the OLED display by the 'OLED' task as described below.  The\r
- * fast interrupt is configured and handled in the timertest.c source file.\r
- *\r
- * "OLED" task - the OLED task is a 'gatekeeper' task.  It is the only task that\r
- * is permitted to access the display directly.  Other tasks wishing to write a\r
- * message to the OLED send the message on a queue to the OLED task instead of\r
- * accessing the OLED themselves.  The OLED task just blocks on the queue waiting\r
- * for messages - waking and displaying the messages as they arrive.\r
- *\r
- * "Check" hook -  This only executes every five seconds from the tick hook.\r
- * Its main function is to check that all the standard demo tasks are still\r
- * operational.  Should any unexpected behaviour within a demo task be discovered\r
- * the tick hook will write an error to the OLED (via the OLED task).  If all the\r
- * demo tasks are executing with their expected behaviour then the check task\r
- * writes PASS to the OLED (again via the OLED task), as described above.\r
- *\r
- * "uIP" task -  This is the task that handles the uIP stack.  All TCP/IP\r
- * processing is performed in this task.\r
+ * This file demonstrates the use of FreeRTOS-MPU.  It creates tasks in both\r
+ * User mode and Privileged mode, and using both the original xTaskCreate() and\r
+ * the new xTaskCreateRestricted() API functions.  The purpose of each created\r
+ * task is documented in the comments above the task function prototype (in\r
+ * this file), with the task behaviour demonstrated and documented within the \r
+ * task function itself.  In addition a queue is used to demonstrate passing\r
+ * data between protected/restricted tasks as well as passing data between an\r
+ * interrupt and a protected/restricted task.\r
  */\r
 \r
 \r
 \r
-\r
-/*************************************************************************\r
- * Please ensure to read http://www.freertos.org/portLM3Sxxxx_Eclipse.html\r
- * which provides information on configuring and running this demo for the\r
- * various Luminary Micro EKs.\r
- *************************************************************************/\r
-\r
-\r
-\r
-\r
 /* Standard includes. */\r
-#include <stdio.h>\r
+#include <string.h>\r
+#include <__cross_studio_io.h>\r
 \r
 /* Scheduler includes. */\r
 #include "FreeRTOS.h"\r
 #include "semphr.h"\r
 \r
 /* Hardware library includes. */\r
-#include "hw_memmap.h"\r
 #include "hw_types.h"\r
 #include "hw_sysctl.h"\r
 #include "sysctl.h"\r
-#include "gpio.h"\r
-#include "grlib.h"\r
-#include "rit128x96x4.h"\r
-#include "osram128x64x4.h"\r
-#include "formike128x128x16.h"\r
-\r
-/* Demo app includes. */\r
-#include "BlockQ.h"\r
-#include "death.h"\r
-#include "integer.h"\r
-#include "blocktim.h"\r
-#include "flash.h"\r
-#include "partest.h"\r
-#include "semtest.h"\r
-#include "PollQ.h"\r
-#include "lcd_message.h"\r
-#include "bitmap.h"\r
-#include "GenQTest.h"\r
-#include "QPeek.h"\r
-#include "recmutex.h"\r
-#include "IntQueue.h"\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-/* The time between cycles of the 'check' functionality (defined within the\r
-tick hook. */\r
-#define mainCHECK_DELAY                                                ( ( portTickType ) 5000 / portTICK_RATE_MS )\r
+/* Misc constants. */\r
+#define mainDONT_BLOCK                                 ( 0 )\r
 \r
-/* Size of the stack allocated to the uIP task. */\r
-#define mainBASIC_WEB_STACK_SIZE            ( configMINIMAL_STACK_SIZE * 3 )\r
+/* Definitions for the messages that can be sent to the check task. */\r
+#define mainREG_TEST_1_STILL_EXECUTING ( 0 )\r
+#define mainREG_TEST_2_STILL_EXECUTING ( 1 )\r
+#define mainPRINT_SYSTEM_STATUS                        ( 2 )\r
 \r
-/* The OLED task uses the sprintf function so requires a little more stack too. */\r
-#define mainOLED_TASK_STACK_SIZE                       ( configMINIMAL_STACK_SIZE + 50 )\r
+/* GCC specifics. */\r
+#define mainALIGN_TO( x )                              __attribute__((aligned(x)))\r
 \r
-/* Task priorities. */\r
-#define mainQUEUE_POLL_PRIORITY                                ( tskIDLE_PRIORITY + 2 )\r
-#define mainCHECK_TASK_PRIORITY                                ( tskIDLE_PRIORITY + 3 )\r
-#define mainSEM_TEST_PRIORITY                          ( tskIDLE_PRIORITY + 1 )\r
-#define mainBLOCK_Q_PRIORITY                           ( tskIDLE_PRIORITY + 2 )\r
-#define mainCREATOR_TASK_PRIORITY           ( tskIDLE_PRIORITY + 3 )\r
-#define mainINTEGER_TASK_PRIORITY           ( tskIDLE_PRIORITY )\r
-#define mainGEN_QUEUE_TASK_PRIORITY                    ( tskIDLE_PRIORITY )\r
 \r
-/* The maximum number of message that can be waiting for display at any one\r
-time. */\r
-#define mainOLED_QUEUE_SIZE                                    ( 3 )\r
-\r
-/* Dimensions the buffer into which the jitter time is written. */\r
-#define mainMAX_MSG_LEN                                                25\r
-\r
-/* The period of the system clock in nano seconds.  This is used to calculate\r
-the jitter time in nano seconds. */\r
-#define mainNS_PER_CLOCK                                       ( ( unsigned portLONG ) ( ( 1.0 / ( double ) configCPU_CLOCK_HZ ) * 1000000000.0 ) )\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for functions that implement tasks. -----------*/\r
+/*-----------------------------------------------------------*/\r
 \r
-/* Constants used when writing strings to the display. */\r
-#define mainCHARACTER_HEIGHT                           ( 9 )\r
-#define mainMAX_ROWS_128                                       ( mainCHARACTER_HEIGHT * 14 )\r
-#define mainMAX_ROWS_96                                                ( mainCHARACTER_HEIGHT * 10 )\r
-#define mainMAX_ROWS_64                                                ( mainCHARACTER_HEIGHT * 7 )\r
-#define mainFULL_SCALE                                         ( 15 )\r
-#define ulSSI_FREQUENCY                                                ( 3500000UL )\r
+/* \r
+ * Prototype for the reg test tasks.  Amongst other things, these fill the CPU\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 reg test tasks execute\r
+ * at the idle priority so will get preempted regularly.  Each task repeatedly\r
+ * sends a message on a queue so long as it remains functioning correctly.  If\r
+ * an error is detected within the task the task is simply deleted.\r
+ */\r
+static void prvRegTest1Task( void *pvParameters );\r
+static void prvRegTest2Task( void *pvParameters );\r
 \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 reg test tasks, indicating that the\r
+ *    task is still operational.\r
+ *\r
+ * 2) "Print Status commands" sent periodically by the tick hook function (and\r
+ *    therefore from within an interrupt) which command the check task to write\r
+ *    either pass or fail to the terminal, depending on the status of the reg\r
+ *    test tasks.\r
+ */\r
+static void prvCheckTask( void *pvParameters );\r
 \r
 /*\r
- * The task that handles the uIP stack.  All TCP/IP processing is performed in\r
- * this task.\r
+ * Prototype for a task created in User mode using the original vTaskCreate() \r
+ * API function.  The task demonstrates the characteristics of such a task,\r
+ * before simply deleting itself.\r
  */\r
-extern void vuIP_Task( void *pvParameters );\r
+static void prvOldStyleUserModeTask( void *pvParameters );\r
 \r
 /*\r
- * The display is written two by more than one task so is controlled by a\r
- * 'gatekeeper' task.  This is the only task that is actually permitted to\r
- * access the display directly.  Other tasks wanting to display a message send\r
- * the message to the gatekeeper.\r
+ * Prototype for a task created in Privileged mode using the original \r
+ * vTaskCreate() API function.  The task demonstrates the characteristics of \r
+ * such a task, before simply deleting itself.\r
  */\r
-static void vOLEDTask( void *pvParameters );\r
+static void prvOldStylePrivilegedModeTask( void *pvParameters );\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for other misc functions.  --------------------*/\r
+/*-----------------------------------------------------------*/\r
 \r
 /*\r
- * Configure the hardware for the demo.\r
+ * Just configures any clocks and IO necessary.\r
  */\r
 static void prvSetupHardware( void );\r
 \r
 /*\r
- * Configures the high frequency timers - those used to measure the timing\r
- * jitter while the real time kernel is executing.\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
-extern void vSetupHighFrequencyTimer( void );\r
+static void prvDeleteMe( void ) __attribute__((noinline));\r
 \r
 /*\r
- * The idle hook is used to run a test of the scheduler context switch\r
- * mechanism.\r
+ * Used by both reg test tasks to send messages to the check task.  The message\r
+ * just lets the check task know that the task is still functioning correctly.\r
+ * If a reg test task detects an error it will delete itself, and in so doing\r
+ * prevent itself from sending any more 'I'm Alive' messages to the check task.\r
  */\r
-void vApplicationIdleHook( void ) __attribute__((naked));\r
-/*-----------------------------------------------------------*/\r
+static void prvSendImAlive( xQueueHandle xHandle, unsigned long ulTaskNumber );\r
 \r
-/* The queue used to send messages to the OLED task. */\r
-xQueueHandle xOLEDQueue;\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
-/* The welcome text. */\r
-const portCHAR * const pcWelcomeMessage = "   www.FreeRTOS.org";\r
+/*-----------------------------------------------------------*/\r
 \r
-/* Variables used to detect the test in the idle hook failing. */\r
-unsigned portLONG ulIdleError = pdFALSE;\r
+/* The handle of the queue used to communicate between tasks and between tasks\r
+and interrupts.  Note that this is a file 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
+static xQueueHandle xFileScopeCheckQueue = NULL;\r
 \r
+\r
+/*-----------------------------------------------------------*/\r
+/* Data used by the 'check' task. ---------------------------*/\r
 /*-----------------------------------------------------------*/\r
 \r
-/*************************************************************************\r
- * Please ensure to read http://www.freertos.org/portLM3Sxxxx_Eclipse.html\r
- * which provides information on configuring and running this demo for the\r
- * various Luminary Micro EKs.\r
- *************************************************************************/\r
-int main( void )\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 three arrays - an MPU region will be created for each array\r
+using the xTaskParameters 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
+/* Fill in a xTaskParameters structure to define the check task - this is the\r
+structure passed to the xTaskCreateRestricted() function. */\r
+static const xTaskParameters xCheckTaskParameters =\r
 {\r
-       prvSetupHardware();\r
+       prvCheckTask,                                                           /* pvTaskCode - the function that implements the task. */\r
+       ( signed char * ) "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
+\r
+/* Three MPU regions are defined for use by the 'check' task when the task is \r
+created.  These are only used to demonstrate the MPU features and are not\r
+actually necessary for the check task to fulfill its primary purpose.  Instead\r
+the MPU regions are replaced with those defined by xAltRegions prior to the \r
+check task receiving any data on the queue or printing any messages to the\r
+debug console.  The region configured by xAltRegions just gives the check task\r
+access to the debug variables that form part of the Rowley library, and are\r
+accessed within the debug_printf() function. */\r
+extern unsigned long dbgCntrlWord_mempoll;\r
+static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =\r
+{                                                                                      \r
+       /* Base address                                         Length          Parameters */\r
+       { ( void * ) &dbgCntrlWord_mempoll,     32,                     portMPU_REGION_READ_WRITE },\r
+       { 0,                                                            0,                      0 },\r
+       { 0,                                                            0,                      0 }\r
+};\r
 \r
-       /* Create the queue used by the OLED task.  Messages for display on the OLED\r
-       are received via this queue. */\r
-       xOLEDQueue = xQueueCreate( mainOLED_QUEUE_SIZE, sizeof( xOLEDMessage ) );\r
 \r
-       /* Create the uIP task if running on a processor that includes a MAC and\r
-       PHY. */\r
-       if( SysCtlPeripheralPresent( SYSCTL_PERIPH_ETH ) )\r
-       {\r
-               xTaskCreate( vuIP_Task, ( signed portCHAR * ) "uIP", mainBASIC_WEB_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL );\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
+/* Fill in a xTaskParameters structure per reg test task to define the tasks. */\r
+static const xTaskParameters xRegTest1Parameters =\r
+{\r
+       prvRegTest1Task,                                                /* pvTaskCode - the function that implements the task. */\r
+       ( signed char * ) "RegTest1",                   /* pcName                       */\r
+       mainREG_TEST_STACK_SIZE_WORDS,                  /* usStackDepth         */\r
+       ( void * ) 0x12345678,                                  /* 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
+/*-----------------------------------------------------------*/\r
+\r
+static xTaskParameters xRegTest2Parameters =\r
+{\r
+       prvRegTest2Task,                                /* pvTaskCode - the function that implements the task. */\r
+       ( signed char * ) "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
+\r
+/*-----------------------------------------------------------*/\r
 \r
-       /* Start the standard demo tasks. */\r
-       vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
-    vCreateBlockTimeTasks();\r
-    vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
-    vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
-    vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
-    vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
-    vStartQueuePeekTasks();\r
-    vStartRecursiveMutexTasks();\r
-    vStartInterruptQueueTasks();\r
-\r
-       /* Start the tasks defined within this file/specific to this demo. */\r
-       xTaskCreate( vOLEDTask, ( signed portCHAR * ) "OLED", mainOLED_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
-\r
-       /* The suicide tasks must be created last as they need to know how many\r
-       tasks were running prior to their creation in order to ascertain whether\r
-       or not the correct/expected number of tasks are running at any given time. */\r
-    vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );\r
-\r
-       /* Configure the high frequency interrupt used to measure the interrupt\r
-       jitter time. */\r
-       vSetupHighFrequencyTimer();\r
+int main( void )\r
+{\r
+       prvSetupHardware();\r
+\r
+       /* Create the queue used to pass "I'm alive" messages to the check task. */\r
+       xFileScopeCheckQueue = xQueueCreate( 1, sizeof( unsigned long ) );\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 = xFileScopeCheckQueue;\r
+\r
+       /* Create the three test tasks.  Handles to the created tasks are not\r
+       required, hence the second parameter is NULL. */\r
+       xTaskCreateRestricted( &xRegTest1Parameters, NULL );\r
+    xTaskCreateRestricted( &xRegTest2Parameters, NULL );\r
+       xTaskCreateRestricted( &xCheckTaskParameters, NULL );\r
+\r
+       /* Create the tasks that are created using the original xTaskCreate() API\r
+       function. */\r
+       xTaskCreate(    prvOldStyleUserModeTask,        /* The function that implements the task. */\r
+                                       ( signed char * ) "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
+                                       NULL                                            /* Handle. */\r
+                               );\r
+\r
+       xTaskCreate(    prvOldStylePrivilegedModeTask,  /* The function that implements the task. */\r
+                                       ( signed char * ) "Task2",              /* Text name for the task. */\r
+                                       100,                                                    /* Stack depth in words. */\r
+                                       NULL,                                                   /* Task parameters. */\r
+                                       ( 3 | portPRIVILEGE_BIT ),              /* Priority and mode. */\r
+                                       NULL                                                    /* Handle. */\r
+                               );\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
+       /* Will only get here if there was insufficient memory to create the idle\r
+       task. */\r
        for( ;; );\r
        return 0;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void prvSetupHardware( void )\r
+static void prvCheckTask( void *pvParameters )\r
 {\r
-    /* If running on Rev A2 silicon, turn the LDO voltage up to 2.75V.  This is\r
-    a workaround to allow the PLL to operate reliably. */\r
-    if( DEVICE_IS_REVA2 )\r
-    {\r
-        SysCtlLDOSet( SYSCTL_LDO_2_75V );\r
-    }\r
-\r
-       /* Set the clocking to run from the PLL at 50 MHz */\r
-       SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ );\r
-\r
-       /*      Enable Port F for Ethernet LEDs\r
-               LED0        Bit 3   Output\r
-               LED1        Bit 2   Output */\r
-       SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOF );\r
-       GPIODirModeSet( GPIO_PORTF_BASE, (GPIO_PIN_2 | GPIO_PIN_3), GPIO_DIR_MODE_HW );\r
-       GPIOPadConfigSet( GPIO_PORTF_BASE, (GPIO_PIN_2 | GPIO_PIN_3 ), GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD );\r
-\r
-       vParTestInitialise();\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
+xQueueHandle xQueue = xFileScopeCheckQueue;\r
+long lMessage;\r
+unsigned long ulStillAliveCounts[ 2 ] = { 0 };\r
+const char *pcStatusMessage = "PASS\r\n";\r
+\r
+       /* Just to remove compiler warning. */\r
+       ( void ) pvParameters;\r
+\r
+       /* Print out the amount of free heap space so configTOTAL_HEAP_SIZE can be\r
+       tuned.  The heap size is set to be very small in this example and will need\r
+       to be increased before many more tasks, queues or semaphores can be \r
+       created. */\r
+       debug_printf( "There are %d bytes of unused heap space.\r\n", xPortGetFreeHeapSize() );\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
+       /* Change the memory regions allocated to this task to those initially\r
+       set up for demonstration purposes to those actually required by the task. */\r
+       vTaskAllocateMPURegions( NULL, xAltRegions );\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 mainREG_TEST_1_STILL_EXECUTING     :       \r
+                                       /* Message from task 1, so task 1 must still be executing. */\r
+                                       ( ulStillAliveCounts[ 0 ] )++;\r
+                                       break;\r
+\r
+                       case mainREG_TEST_2_STILL_EXECUTING     :                                               \r
+                                       /* Message from task 2, so task 2 must still be executing. */\r
+                                       ( ulStillAliveCounts[ 1 ] )++;\r
+                                       break;\r
+\r
+                       case mainPRINT_SYSTEM_STATUS            :       \r
+                                       /* Message from tick hook, time to print out the system\r
+                                       status.  If messages has stopped arriving from either reg\r
+                                       test task then the status must be set to fail. */\r
+                                       if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 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
+\r
+                                       /* Print a pass/fail message to the terminal.  This will be\r
+                                       visible in the CrossWorks IDE. */\r
+                                       debug_printf( pcStatusMessage );\r
+\r
+                                       /* Reset the count of 'still alive' messages. */\r
+                                       memset( ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );\r
+                                       break;\r
+\r
+               default :\r
+                                       /* Something unexpected happened.  Delete this task so the \r
+                                       error is apparent (no output will be displayed). */\r
+                                       prvDeleteMe();\r
+                                       break;\r
+               }\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vApplicationTickHook( void )\r
+static void prvTestMemoryRegions( void )\r
 {\r
-static xOLEDMessage xMessage = { "PASS" };\r
-static unsigned portLONG ulTicksSinceLastDisplay = 0;\r
-portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
-\r
-       /* Called from every tick interrupt.  Have enough ticks passed to make it\r
-       time to perform our health status check again? */\r
-       ulTicksSinceLastDisplay++;\r
-       if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )\r
+long l;\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
-               ulTicksSinceLastDisplay = 0;\r
+               /* Something unexpected happened.  Delete this task so the error is\r
+               apparent (no output will be displayed). */\r
+               prvDeleteMe();\r
+       }\r
 \r
-               /* Has an error been found in any task? */\r
-               if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
-               {\r
-                       xMessage.pcMessage = "ERROR IN GEN Q";\r
-               }\r
-               else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
-               {\r
-                       xMessage.pcMessage = "ERROR IN PEEK Q";\r
-               }\r
-               else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
-               {\r
-                       xMessage.pcMessage = "ERROR IN BLOCK Q";\r
-               }\r
-               else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
-               {\r
-                       xMessage.pcMessage = "ERROR IN BLOCK TIME";\r
-               }\r
-           else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
-           {\r
-               xMessage.pcMessage = "ERROR IN SEMAPHORE";\r
-           }\r
-           else if( xArePollingQueuesStillRunning() != pdTRUE )\r
-           {\r
-               xMessage.pcMessage = "ERROR IN POLL Q";\r
-           }\r
-           else if( xIsCreateTaskStillRunning() != pdTRUE )\r
-           {\r
-               xMessage.pcMessage = "ERROR IN CREATE";\r
-           }\r
-           else if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
-           {\r
-               xMessage.pcMessage = "ERROR IN MATH";\r
-           }\r
-           else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
-           {\r
-               xMessage.pcMessage = "ERROR IN REC MUTEX";\r
-           }\r
-               else if( ulIdleError != pdFALSE )\r
-               {\r
-                       xMessage.pcMessage = "ERROR IN HOOK";\r
-               }\r
-               else if( xAreIntQueueTasksStillRunning() != pdTRUE )\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( l = 0; l < mainREAD_WRITE_ALIGN_SIZE; l++ )\r
+       {\r
+               cReadWriteArray[ l ] = 'a';\r
+               if( cReadWriteArray[ l ] != 'a' )\r
                {\r
-                       xMessage.pcMessage = "ERROR IN INT QUEUE";\r
+                       /* Something unexpected happened.  Delete this task so the error is\r
+                       apparent (no output will be displayed). */\r
+                       prvDeleteMe();\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
-               /* Send the message to the OLED gatekeeper for display. */\r
-               xHigherPriorityTaskWoken = pdFALSE;\r
-               xQueueSendFromISR( xOLEDQueue, &xMessage, &xHigherPriorityTaskWoken );\r
+       /* The read only array can be successfully read... */\r
+       for( l = 0; l < mainREAD_ONLY_ALIGN_SIZE; l++ )\r
+       {\r
+               cTemp = cReadOnlyArray[ l ];\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. */\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
 /*-----------------------------------------------------------*/\r
 \r
-void vOLEDTask( void *pvParameters )\r
+static void prvRegTest1Task( void *pvParameters )\r
 {\r
-xOLEDMessage xMessage;\r
-unsigned portLONG ulY, ulMaxY;\r
-static portCHAR cMessage[ mainMAX_MSG_LEN ];\r
-extern volatile unsigned portLONG ulMaxJitter;\r
-unsigned portBASE_TYPE uxUnusedStackOnEntry, uxUnusedStackNow;\r
-const unsigned portCHAR *pucImage;\r
-\r
-/* Functions to access the OLED.  The one used depends on the dev kit\r
-being used. */\r
-void ( *vOLEDInit )( unsigned portLONG ) = NULL;\r
-void ( *vOLEDStringDraw )( const portCHAR *, unsigned portLONG, unsigned portLONG, unsigned portCHAR ) = NULL;\r
-void ( *vOLEDImageDraw )( const unsigned portCHAR *, unsigned portLONG, unsigned portLONG, unsigned portLONG, unsigned portLONG ) = NULL;\r
-void ( *vOLEDClear )( void ) = NULL;\r
-\r
-       /* Just for demo purposes. */\r
-       uxUnusedStackOnEntry = uxTaskGetStackHighWaterMark( NULL );\r
-\r
-       /* Map the OLED access functions to the driver functions that are appropriate\r
-       for the evaluation kit being used. */\r
-       switch( HWREG( SYSCTL_DID1 ) & SYSCTL_DID1_PRTNO_MASK )\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 this task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+xQueueHandle xQueue = xFileScopeCheckQueue;\r
+\r
+       /* Now the queue handle has been obtained the task can switch to user \r
+       mode.  This is just one method of passing a handle into a protected\r
+       task, the other reg test task uses the task parameter instead. */\r
+    portSWITCH_TO_USER_MODE();\r
+\r
+       /* First check that the parameter value is as expected. */\r
+       if( pvParameters != ( void * ) 0x12345678 )\r
        {\r
-               case SYSCTL_DID1_PRTNO_6965     :\r
-               case SYSCTL_DID1_PRTNO_2965     :       vOLEDInit = OSRAM128x64x4Init;\r
-                                                                               vOLEDStringDraw = OSRAM128x64x4StringDraw;\r
-                                                                               vOLEDImageDraw = OSRAM128x64x4ImageDraw;\r
-                                                                               vOLEDClear = OSRAM128x64x4Clear;\r
-                                                                               ulMaxY = mainMAX_ROWS_64;\r
-                                                                               pucImage = pucBasicBitmap;\r
-                                                                               break;\r
-\r
-               case SYSCTL_DID1_PRTNO_1968     :\r
-               case SYSCTL_DID1_PRTNO_8962 :   vOLEDInit = RIT128x96x4Init;\r
-                                                                               vOLEDStringDraw = RIT128x96x4StringDraw;\r
-                                                                               vOLEDImageDraw = RIT128x96x4ImageDraw;\r
-                                                                               vOLEDClear = RIT128x96x4Clear;\r
-                                                                               ulMaxY = mainMAX_ROWS_96;\r
-                                                                               pucImage = pucBasicBitmap;\r
-                                                                               break;\r
-\r
-               default                                         :       vOLEDInit = vFormike128x128x16Init;\r
-                                                                               vOLEDStringDraw = vFormike128x128x16StringDraw;\r
-                                                                               vOLEDImageDraw = vFormike128x128x16ImageDraw;\r
-                                                                               vOLEDClear = vFormike128x128x16Clear;\r
-                                                                               ulMaxY = mainMAX_ROWS_128;\r
-                                                                               pucImage = pucGrLibBitmap;\r
-                                                                               break;\r
+               /* Error detected.  Delete the task so it stops communicating with\r
+               the check task. */\r
+               prvDeleteMe();\r
        }\r
 \r
-       ulY = ulMaxY;\r
 \r
-       /* Initialise the OLED and display a startup message. */\r
-       vOLEDInit( ulSSI_FREQUENCY );\r
-       vOLEDStringDraw( "POWERED BY FreeRTOS", 0, 0, mainFULL_SCALE );\r
-       vOLEDImageDraw( pucImage, 0, mainCHARACTER_HEIGHT + 1, bmpBITMAP_WIDTH, bmpBITMAP_HEIGHT );\r
+       for( ;; )\r
+       {               \r
+               /* This task tests the kernel context switch mechanism by reading and\r
+               writing directly to registers - which requires the test to be written\r
+               in assembly code. */\r
+               __asm volatile \r
+               (       \r
+                       "               MOV     R4, #104                        \n" /* Set registers to a known value.  R0 to R1 are done in the loop below. */\r
+                       "               MOV     R5, #105                        \n"\r
+                       "               MOV     R6, #106                        \n"\r
+                       "               MOV     R8, #108                        \n"\r
+                       "               MOV     R9, #109                        \n"\r
+                       "               MOV     R10, #110                       \n"\r
+                       "               MOV     R11, #111                       \n"\r
+                       "reg1loop:                                              \n"\r
+                       "               MOV     R0, #100                        \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */\r
+                       "               MOV     R1, #101                        \n"\r
+                       "               MOV     R2, #102                        \n"\r
+                       "               MOV R3, #103                    \n"\r
+                       "               MOV     R12, #112                       \n"\r
+                       "               SVC #1                                  \n" /* Yield just to increase test coverage. */\r
+                       "               CMP     R0, #100                        \n" /* Check all the registers still contain their expected values. */\r
+                       "               BNE     prvDeleteMe                     \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */\r
+                       "               CMP     R1, #101                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R2, #102                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP R3, #103                    \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R4, #104                        \n" \r
+                       "               BNE     prvDeleteMe                     \n" \r
+                       "               CMP     R5, #105                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R6, #106                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R8, #108                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R9, #109                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R10, #110                       \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R11, #111                       \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R12, #112                       \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"\r
+               );\r
+\r
+               /* Send mainREG_TEST_1_STILL_EXECUTING to the check task to indicate that this \r
+               task is still functioning. */\r
+               prvSendImAlive( xQueue, mainREG_TEST_1_STILL_EXECUTING );\r
+\r
+               /* Go back to check all the register values again. */\r
+               __asm volatile( "               B reg1loop      " );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTest2Task( void *pvParameters )\r
+{\r
+/* The queue handle is passed in as the task parameter.  This is one method of\r
+passing data into a protected task, the other reg test task uses a different \r
+method. */\r
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
 \r
        for( ;; )\r
        {\r
-               /* Wait for a message to arrive that requires displaying. */\r
-               xQueueReceive( xOLEDQueue, &xMessage, portMAX_DELAY );\r
+               /* This task tests the kernel context switch mechanism by reading and\r
+               writing directly to registers - which requires the test to be written\r
+               in assembly code. */\r
+               __asm volatile \r
+               (       \r
+                       "               MOV     R4, #4                          \n" /* Set registers to a known value.  R0 to R1 are done in the loop below. */\r
+                       "               MOV     R5, #5                          \n"\r
+                       "               MOV     R6, #6                          \n"\r
+                       "               MOV     R8, #8                          \n" /* Frame pointer is omitted as it must not be changed. */\r
+                       "               MOV     R9, #9                          \n"\r
+                       "               MOV     R10, 10                         \n"\r
+                       "               MOV     R11, #11                        \n"                                             \r
+                       "reg2loop:                                              \n"\r
+                       "               MOV     R0, #13                         \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */\r
+                       "               MOV     R1, #1                          \n"\r
+                       "               MOV     R2, #2                          \n"\r
+                       "               MOV R3, #3                              \n"\r
+                       "               MOV     R12, #12                        \n"\r
+                       "               CMP     R0, #13                         \n" /* Check all the registers still contain their expected values. */\r
+                       "               BNE     prvDeleteMe                     \n" /* Value was not as expected, delete the task so it stops communicating with the check task */\r
+                       "               CMP     R1, #1                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R2, #2                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP R3, #3                              \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R4, #4                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R5, #5                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R6, #6                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R8, #8                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R9, #9                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R10, #10                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R11, #11                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R12, #12                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+            :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"\r
+               );\r
+\r
+               /* Send mainREG_TEST_2_STILL_EXECUTING to the check task to indicate that this \r
+               task is still functioning. */\r
+               prvSendImAlive( xQueue, mainREG_TEST_2_STILL_EXECUTING );\r
+\r
+               /* Go back to check all the register values again. */\r
+               __asm volatile( "               B reg2loop      " );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-               /* Write the message on the next available row. */\r
-               ulY += mainCHARACTER_HEIGHT;\r
-               if( ulY >= ulMaxY )\r
-               {\r
-                       ulY = mainCHARACTER_HEIGHT;\r
-                       vOLEDClear();\r
-                       vOLEDStringDraw( pcWelcomeMessage, 0, 0, mainFULL_SCALE );\r
-               }\r
+void vApplicationIdleHook( void )\r
+{\r
+extern unsigned long __SRAM_segment_end__[];\r
+extern unsigned long __privileged_data_start__[];\r
+extern unsigned long __privileged_data_end__[];\r
+extern unsigned long __FLASH_segment_start__[];\r
+extern unsigned long __FLASH_segment_end__[];\r
+volatile unsigned long *pul;\r
+volatile unsigned long 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
+/*-----------------------------------------------------------*/\r
 \r
-               /* Display the message along with the maximum jitter time from the\r
-               high priority time test. */\r
-               sprintf( cMessage, "%s [%uns]", xMessage.pcMessage, ulMaxJitter * mainNS_PER_CLOCK );\r
-               vOLEDStringDraw( cMessage, 0, ulY, mainFULL_SCALE );\r
+static void prvOldStyleUserModeTask( void *pvParameters )\r
+{\r
+extern unsigned long __privileged_data_start__[];\r
+extern unsigned long __privileged_data_end__[];\r
+extern unsigned long __SRAM_segment_end__[];\r
+extern unsigned long __privileged_functions_end__[];\r
+extern unsigned long __FLASH_segment_start__[];\r
+extern unsigned long __FLASH_segment_end__[];\r
+const volatile unsigned long *pulStandardPeripheralRegister = ( volatile unsigned long * ) 0x400FC0C4; /* PCONP */\r
+volatile unsigned long *pul;\r
+volatile unsigned long 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 unsigned long __privileged_functions_start__[];\r
+const volatile unsigned long *pulSystemPeripheralRegister = ( volatile unsigned long * ) 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
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOldStylePrivilegedModeTask( void *pvParameters )\r
+{\r
+extern unsigned long __privileged_data_start__[];\r
+extern unsigned long __privileged_data_end__[];\r
+extern unsigned long __SRAM_segment_end__[];\r
+extern unsigned long __privileged_functions_start__[];\r
+extern unsigned long __privileged_functions_end__[];\r
+extern unsigned long __FLASH_segment_start__[];\r
+extern unsigned long __FLASH_segment_end__[];\r
+volatile unsigned long *pul;\r
+volatile unsigned long ulReadData;\r
+const volatile unsigned long *pulSystemPeripheralRegister = ( volatile unsigned long * ) 0xe000e014; /* Systick */\r
+const volatile unsigned long *pulStandardPeripheralRegister = ( volatile unsigned long * ) 0x400FC0C4; /* PCONP */\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
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDeleteMe( void )\r
+{\r
+       vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendImAlive( xQueueHandle xHandle, unsigned long ulTaskNumber )\r
+{\r
+       if( xHandle != NULL )\r
+       {\r
+               xQueueSend( xHandle, &ulTaskNumber, mainDONT_BLOCK );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupHardware( void )\r
+{\r
+       /* If running on Rev A2 silicon, turn the LDO voltage up to 2.75V.  This is\r
+       a workaround to allow the PLL to operate reliably. */\r
+       if( DEVICE_IS_REVA2 )\r
+       {\r
+               SysCtlLDOSet( SYSCTL_LDO_2_75V );\r
+       }\r
+\r
+       /* Set the clocking to run from the PLL at 50 MHz */\r
+       SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+static unsigned long ulCallCount;\r
+const unsigned long ulCallsBetweenSends = 5000 / portTICK_RATE_MS;\r
+const unsigned long ulMessage = mainPRINT_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 xFileScopeCheckQueue directly. */\r
+               xQueueSendFromISR( xFileScopeCheckQueue, &ulMessage, &xDummy );\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )\r
+void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed 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
@@ -448,10 +901,76 @@ void vApplicationMallocFailedHook( void )
 /* Just to keep the linker happy. */\r
 void __error__( char *pcFilename, unsigned long ulLine )\r
 {\r
+       ( void ) pcFilename;\r
+       ( void ) ulLine;\r
        for( ;; );\r
 }\r
+/*-----------------------------------------------------------*/\r
 \r
+/* Just to keep the linker happy. */\r
 int uipprintf( const char *fmt, ... )\r
 {\r
+       ( void ) fmt;\r
        return( 0 );\r
 }\r
+/*-----------------------------------------------------------*/\r
+\r
+void hard_fault_handler(unsigned int * hardfault_args)\r
+{\r
+volatile unsigned int stacked_r0;\r
+volatile unsigned int stacked_r1;\r
+volatile unsigned int stacked_r2;\r
+volatile unsigned int stacked_r3;\r
+volatile unsigned int stacked_r12;\r
+volatile unsigned int stacked_lr;\r
+volatile unsigned int stacked_pc;\r
+volatile unsigned int stacked_psr;\r
+\r
+       stacked_r0 = ((unsigned long) hardfault_args[0]);\r
+       stacked_r1 = ((unsigned long) hardfault_args[1]);\r
+       stacked_r2 = ((unsigned long) hardfault_args[2]);\r
+       stacked_r3 = ((unsigned long) hardfault_args[3]);\r
+\r
+       stacked_r12 = ((unsigned long) hardfault_args[4]);\r
+       stacked_lr = ((unsigned long) hardfault_args[5]);\r
+       stacked_pc = ((unsigned long) hardfault_args[6]);\r
+       stacked_psr = ((unsigned long) hardfault_args[7]);\r
+\r
+       /* Inspect stacked_pc to locate the offending instruction. */\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void Fault_ISR( void ) __attribute__((naked));\r
+void Fault_ISR( void )\r
+{\r
+       __asm volatile\r
+       (\r
+               " tst lr, #4                                                                            \n"\r
+               " ite eq                                                                                        \n"\r
+               " mrseq r0, msp                                                                         \n"\r
+               " mrsne r0, psp                                                                         \n"\r
+               " ldr r1, [r0, #24]                                                                     \n"\r
+               " ldr r2, handler_address_const                                         \n"\r
+               " bx r2                                                                                         \n"\r
+               " handler_address_const: .word hard_fault_handler       \n"\r
+       );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void MPU_Fault_ISR( void ) __attribute__((naked));\r
+void MPU_Fault_ISR( void )\r
+{\r
+       __asm volatile\r
+       (\r
+               " tst lr, #4                                                                            \n"\r
+               " ite eq                                                                                        \n"\r
+               " mrseq r0, msp                                                                         \n"\r
+               " mrsne r0, psp                                                                         \n"\r
+               " ldr r1, [r0, #24]                                                                     \n"\r
+               " ldr r2, handler_address_const                                         \n"\r
+               " bx r2                                                                                         \n"\r
+               " handler2_address_const: .word hard_fault_handler      \n"\r
+       );\r
+}\r
+/*-----------------------------------------------------------*/
\ No newline at end of file