licensing and training services.\r
*/\r
\r
+#error The batch file Demo\CORTEX_LPC1768_GCC_RedSuite\CreateProjectDirectoryStructure.bat must be executed before the first build. After executing the batch file hit F5 to refrech the Eclipse project, then delete this line.\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
-//#error The batch file Demo\CORTEX_LPC1768_GCC_RedSuite\CreateProjectDirectoryStructure.bat must be executed before the first build. After executing the batch file hit F5 to refrech the Eclipse project, then delete this line.\r
\r
/* Library includes. */\r
#include <string.h>\r
#include "lcd_driver.h"\r
#include "lcd.h"\r
\r
-/*-----------------------------------------------------------*/\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
/* Hardware specifics. The start and end address are chosen to ensure the\r
required GPIO are covered while also ensuring the necessary alignment is\r
achieved. */\r
-#define mainGPIO_START_ADDRESS ( 0x2009c000UL )\r
+#define mainGPIO_START_ADDRESS ( ( unsigned long * ) 0x2009c000 )\r
#define mainGPIO_END_ADDRESS ( mainGPIO_START_ADDRESS + ( 64 * 1024 ) )\r
+\r
+\r
/*-----------------------------------------------------------*/\r
/* Prototypes for functions that implement tasks. -----------*/\r
/*-----------------------------------------------------------*/\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 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
+ /* 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
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