/*\r
- FreeRTOS V6.0.0 - Copyright (C) 2009 Real Time Engineers Ltd.\r
+ FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd.\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 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
+ * *\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
- 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
+ This file is part of the FreeRTOS distribution.\r
\r
- ***************************************************************************\r
- * *\r
- * The FreeRTOS eBook and reference manual are available to purchase for a *\r
- * small fee. Help yourself get started quickly while also helping the *\r
- * FreeRTOS project! See http://www.FreeRTOS.org/Documentation for details *\r
- * *\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
- 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
licensing and training services.\r
*/\r
\r
+\r
+/*\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
/* Standard includes. */\r
#include <string.h>\r
#include <__cross_studio_io.h>\r
#include "hw_sysctl.h"\r
#include "sysctl.h"\r
\r
-/*\r
- * This file demonstrates the use of MPU using just three tasks - two 'reg test'\r
- * tasks and one 'check' task. Read the comments above the\r
- * function prototypes for more information.\r
- */\r
-\r
/*-----------------------------------------------------------*/\r
\r
/* Misc constants. */\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.\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
* Prototype for the check task. The check task demonstrates various features\r
- * of the MPU before entering a loop where it waits for commands to arrive on a\r
+ * of the MPU before entering a loop where it waits for messages to arrive on a\r
* queue.\r
*\r
- * The check task will periodically be commanded to print out a status message.\r
- * If both the reg tests tasks are executing as expected the check task will\r
- * print "PASS" to the debug port, otherwise it will print 'FAIL'. Debug port\r
- * messages can be viewed within the CrossWorks IDE.\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
+ * 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
+static void prvOldStyleUserModeTask( void *pvParameters );\r
+\r
+/*\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 prvOldStylePrivilegedModeTask( void *pvParameters );\r
\r
\r
/*-----------------------------------------------------------*/\r
\r
/*\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 sending is still functioning correctly.\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
static xQueueHandle xFileScopeCheckQueue = NULL;\r
\r
\r
-\r
/*-----------------------------------------------------------*/\r
/* Data used by the 'check' task. ---------------------------*/\r
/*-----------------------------------------------------------*/\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. Note that the arrays allocate \r
-slightly more RAM than is actually assigned to the MPU region. This is to \r
-permit writes off the end of the array to be detected even when the arrays are \r
-placed in adjacent memory locations (with no gaps between them). The align \r
-size must be a power of two. */\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
#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. */\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
prvCheckTask, /* pvTaskCode - the function that implements the task. */\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. */\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
( 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. */\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
( 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. */\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
/* 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. */\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
xTaskCreateRestricted( &xRegTest2Parameters, NULL );\r
xTaskCreateRestricted( &xCheckTaskParameters, NULL );\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, although the idle task is yet to be created.\r\n", xPortGetFreeHeapSize() );\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
/* 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 is set down to user mode within this function. */\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
long l;\r
char cTemp;\r
\r
- /* The check task is created in the privileged mode. The privileged array \r
- can be both read from and written to while this task is privileged. */\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
{\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
+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
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 check task uses a different \r
+passing data into a protected task, the other reg test task uses a different \r
method. */\r
xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
\r
}\r
/*-----------------------------------------------------------*/\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
+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
-void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *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