From: richardbarry Date: Sun, 11 Oct 2009 09:30:12 +0000 (+0000) Subject: Add a few more tests and demos. X-Git-Tag: V6.0.0~13 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f1fe163eacd57e7775c5fb61d6badadb9665583a;p=freertos Add a few more tests and demos. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@916 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h index 19d573dd3..d973c007f 100644 --- a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h +++ b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h @@ -67,7 +67,7 @@ #define configCPU_CLOCK_HZ ( ( unsigned long ) 50000000 ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 100 ) -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2048 ) ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2560 ) ) #define configMAX_TASK_NAME_LEN ( 12 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c index 3c7f5fb09..c65631fa7 100644 --- a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c +++ b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c @@ -46,6 +46,20 @@ licensing and training services. */ + +/* + * This file demonstrates the use of FreeRTOS-MPU. It creates tasks in both + * User mode and Privileged mode, and using both the original xTaskCreate() and + * the new xTaskCreateRestricted() API functions. The purpose of each created + * task is documented in the comments above the task function prototype (in + * this file), with the task behaviour demonstrated and documented within the + * task function itself. In addition a queue is used to demonstrate passing + * data between protected/restricted tasks as well as passing data between an + * interrupt and a protected/restricted task. + */ + + + /* Standard includes. */ #include #include <__cross_studio_io.h> @@ -61,12 +75,6 @@ #include "hw_sysctl.h" #include "sysctl.h" -/* - * This file demonstrates the use of MPU using just three tasks - two 'reg test' - * tasks and one 'check' task. Read the comments above the - * function prototypes for more information. - */ - /*-----------------------------------------------------------*/ /* Misc constants. */ @@ -90,29 +98,45 @@ * registers with known values before checking that the registers still contain * the expected values. Each of the two tasks use different values so an error * in the context switch mechanism can be caught. Both reg test tasks execute - * at the idle priority so will get preempted regularly. + * at the idle priority so will get preempted regularly. Each task repeatedly + * sends a message on a queue so long as it remains functioning correctly. If + * an error is detected within the task the task is simply deleted. */ static void prvRegTest1Task( void *pvParameters ); static void prvRegTest2Task( void *pvParameters ); /* * Prototype for the check task. The check task demonstrates various features - * of the MPU before entering a loop where it waits for commands to arrive on a + * of the MPU before entering a loop where it waits for messages to arrive on a * queue. * - * The check task will periodically be commanded to print out a status message. - * If both the reg tests tasks are executing as expected the check task will - * print "PASS" to the debug port, otherwise it will print 'FAIL'. Debug port - * messages can be viewed within the CrossWorks IDE. + * Two types of messages can be processes: + * + * 1) "I'm Alive" messages sent from the reg test tasks, indicating that the + * task is still operational. + * + * 2) "Print Status commands" sent periodically by the tick hook function (and + * therefore from within an interrupt) which command the check task to write + * either pass or fail to the terminal, depending on the status of the reg + * test tasks. */ static void prvCheckTask( void *pvParameters ); /* - * Prototype for the User mode task that is created using the original - * vTaskCreate() API function. + * Prototype for a task created in User mode using the original vTaskCreate() + * API function. The task demonstrates the characteristics of such a task, + * before simply deleting itself. */ static void prvOldStyleUserModeTask( void *pvParameters ); +/* + * Prototype for a task created in Privileged mode using the original + * vTaskCreate() API function. The task demonstrates the characteristics of + * such a task, before simply deleting itself. + */ +static void prvOldStylePrivilegedModeTask( void *pvParameters ); + + /*-----------------------------------------------------------*/ /* Prototypes for other misc functions. --------------------*/ /*-----------------------------------------------------------*/ @@ -131,7 +155,7 @@ static void prvDeleteMe( void ) __attribute__((noinline)); /* * Used by both reg test tasks to send messages to the check task. The message - * just lets the check task know that the sending is still functioning correctly. + * just lets the check task know that the task is still functioning correctly. * If a reg test task detects an error it will delete itself, and in so doing * prevent itself from sending any more 'I'm Alive' messages to the check task. */ @@ -157,7 +181,6 @@ further information. */ static xQueueHandle xFileScopeCheckQueue = NULL; - /*-----------------------------------------------------------*/ /* Data used by the 'check' task. ---------------------------*/ /*-----------------------------------------------------------*/ @@ -174,11 +197,14 @@ stack size is defined in words, not bytes. */ static portSTACK_TYPE xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainCHECK_TASK_STACK_ALIGNMENT ); /* Declare three arrays - an MPU region will be created for each array - using the xTaskParameters structure below. Note that the arrays allocate -slightly more RAM than is actually assigned to the MPU region. This is to -permit writes off the end of the array to be detected even when the arrays are -placed in adjacent memory locations (with no gaps between them). The align -size must be a power of two. */ +using the xTaskParameters structure below. THIS IS JUST TO DEMONSTRATE THE +MPU FUNCTIONALITY, the data is not used by the check tasks primary function +of monitoring the reg test tasks and printing out status information. + +Note that the arrays allocate slightly more RAM than is actually assigned to +the MPU region. This is to permit writes off the end of the array to be +detected even when the arrays are placed in adjacent memory locations (with no +gaps between them). The align size must be a power of two. */ #define mainREAD_WRITE_ARRAY_SIZE 130 #define mainREAD_WRITE_ALIGN_SIZE 128 char cReadWriteArray[ mainREAD_WRITE_ARRAY_SIZE ] mainALIGN_TO( mainREAD_WRITE_ALIGN_SIZE ); @@ -191,7 +217,8 @@ char cReadOnlyArray[ mainREAD_ONLY_ARRAY_SIZE ] mainALIGN_TO( mainREAD_ONLY_ALIG #define mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE 128 char cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] mainALIGN_TO( mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ); -/* Fill in a xTaskParameters structure to define the check task. */ +/* Fill in a xTaskParameters structure to define the check task - this is the +structure passed to the xTaskCreateRestricted() function. */ static const xTaskParameters xCheckTaskParameters = { prvCheckTask, /* pvTaskCode - the function that implements the task. */ @@ -203,7 +230,9 @@ static const xTaskParameters xCheckTaskParameters = /* xRegions - In this case the xRegions array is used to create MPU regions for all three of the arrays declared directly above. Each MPU region is - created with different parameters. */ + created with different parameters. Again, THIS IS JUST TO DEMONSTRATE THE + MPU FUNCTIONALITY, the data is not used by the check tasks primary function + of monitoring the reg test tasks and printing out status information.*/ { /* Base address Length Parameters */ { cReadWriteArray, mainREAD_WRITE_ALIGN_SIZE, portMPU_REGION_READ_WRITE }, @@ -256,7 +285,7 @@ static const xTaskParameters xRegTest1Parameters = ( void * ) 0x12345678, /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */ tskIDLE_PRIORITY | portPRIVILEGE_BIT, /* uxPriority - note that this task is created with privileges to demonstrate one method of passing a queue handle into the task. */ xRegTest1Stack, /* puxStackBuffer - the array to use as the task stack, as declared above. */ - { /* xRegions - this task does not use any non-stack data. */ + { /* xRegions - this task does not use any non-stack data hence all members are zero. */ /* Base address Length Parameters */ { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, @@ -273,7 +302,7 @@ static xTaskParameters xRegTest2Parameters = ( void * ) NULL, /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */ tskIDLE_PRIORITY, /* uxPriority */ xRegTest2Stack, /* puxStackBuffer - the array to use as the task stack, as declared above. */ - { /* xRegions - this task does not use any non-stack data. */ + { /* xRegions - this task does not use any non-stack data hence all members are zero. */ /* Base address Length Parameters */ { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, @@ -293,7 +322,7 @@ int main( void ) /* One check task uses the task parameter to receive the queue handle. This allows the file scope variable to be accessed from within the task. The pvParameters member of xRegTest2Parameters can only be set after the - queue has been created. */ + queue has been created so is set here. */ xRegTest2Parameters.pvParameters = xFileScopeCheckQueue; /* Create the three test tasks. Handles to the created tasks are not @@ -308,15 +337,17 @@ int main( void ) ( signed char * ) "Task1", /* Text name for the task. */ 100, /* Stack depth in words. */ NULL, /* Task parameters. */ - 3, /* Priority. */ + 3, /* Priority and mode (user in this case). */ NULL /* Handle. */ ); - /* Print out the amount of free heap space so configTOTAL_HEAP_SIZE can be - tuned. The heap size is set to be very small in this example and will need - to be increased before many more tasks, queues or semaphores can be - created. */ - debug_printf( "There are %d bytes of unused heap space, although the idle task is yet to be created.\r\n", xPortGetFreeHeapSize() ); + xTaskCreate( prvOldStylePrivilegedModeTask, /* The function that implements the task. */ + ( signed char * ) "Task2", /* Text name for the task. */ + 100, /* Stack depth in words. */ + NULL, /* Task parameters. */ + ( 3 | portPRIVILEGE_BIT ), /* Priority and mode. */ + NULL /* Handle. */ + ); /* Start the scheduler. */ vTaskStartScheduler(); @@ -342,8 +373,14 @@ const char *pcStatusMessage = "PASS\r\n"; /* Just to remove compiler warning. */ ( void ) pvParameters; + /* Print out the amount of free heap space so configTOTAL_HEAP_SIZE can be + tuned. The heap size is set to be very small in this example and will need + to be increased before many more tasks, queues or semaphores can be + created. */ + debug_printf( "There are %d bytes of unused heap space.\r\n", xPortGetFreeHeapSize() ); + /* Demonstrate how the various memory regions can and can't be accessed. - The task privilege is set down to user mode within this function. */ + The task privilege level is set down to user mode within this function. */ prvTestMemoryRegions(); /* Change the memory regions allocated to this task to those initially @@ -403,8 +440,9 @@ static void prvTestMemoryRegions( void ) long l; char cTemp; - /* The check task is created in the privileged mode. The privileged array - can be both read from and written to while this task is privileged. */ + /* The check task (from which this function is called) is created in the + Privileged mode. The privileged array can be both read from and written + to while this task is privileged. */ cPrivilegedOnlyAccessArray[ 0 ] = 'a'; if( cPrivilegedOnlyAccessArray[ 0 ] != 'a' ) { @@ -470,7 +508,7 @@ static void prvRegTest1Task( void *pvParameters ) { /* This task is created in privileged mode so can access the file scope queue variable. Take a stack copy of this before the task is set into user -mode. Once that task is in user mode the file scope queue variable will no +mode. Once this task is in user mode the file scope queue variable will no longer be accessible but the stack copy will. */ xQueueHandle xQueue = xFileScopeCheckQueue; @@ -549,7 +587,7 @@ xQueueHandle xQueue = xFileScopeCheckQueue; static void prvRegTest2Task( void *pvParameters ) { /* The queue handle is passed in as the task parameter. This is one method of -passing data into a protected task, the other check task uses a different +passing data into a protected task, the other reg test task uses a different method. */ xQueueHandle xQueue = ( xQueueHandle ) pvParameters; @@ -660,12 +698,14 @@ extern unsigned long __SRAM_segment_end__[]; extern unsigned long __privileged_functions_end__[]; extern unsigned long __FLASH_segment_start__[]; extern unsigned long __FLASH_segment_end__[]; +const volatile unsigned long *pulStandardPeripheralRegister = ( volatile unsigned long * ) 0x400FC0C4; /* PCONP */ volatile unsigned long *pul; volatile unsigned long ulReadData; -/* The following line is commented out to prevent the unused variable compiler -warning when the test that uses the variable is commented out. -extern unsigned long __privileged_functions_start__[]; */ +/* The following lines are commented out to prevent the unused variable +compiler warnings when the tests that use the variable are also commented out. +extern unsigned long __privileged_functions_start__[]; +const volatile unsigned long *pulSystemPeripheralRegister = ( volatile unsigned long * ) 0xe000e014; */ ( void ) pvParameters; @@ -687,9 +727,18 @@ extern unsigned long __privileged_functions_start__[]; */ pul = __FLASH_segment_end__ - 1; ulReadData = *pul; + /* Standard peripherals are accessible. */ + ulReadData = *pulStandardPeripheralRegister; + + /* System peripherals are not accessible. Uncomment the following line + to test. Also uncomment the declaration of pulSystemPeripheralRegister + at the top of this function. */ + /* ulReadData = *pulSystemPeripheralRegister; */ + /* Reading from anywhere inside the privileged Flash or RAM should cause a fault. This can be tested by uncommenting any of the following pairs of - lines. */ + lines. Also uncomment the declaration of __privileged_functions_start__ + at the top of this function. */ /* pul = __privileged_functions_start__; ulReadData = *pul; */ @@ -703,7 +752,66 @@ extern unsigned long __privileged_functions_start__[]; */ /* pul = __privileged_data_end__ - 1; ulReadData = *pul; */ - /* Must not just run off the end of a task function, so delete this task. */ + /* Must not just run off the end of a task function, so delete this task. + Note that because this task was created using xTaskCreate() the stack was + allocated dynamically and I have not included any code to free it again. */ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvOldStylePrivilegedModeTask( void *pvParameters ) +{ +extern unsigned long __privileged_data_start__[]; +extern unsigned long __privileged_data_end__[]; +extern unsigned long __SRAM_segment_end__[]; +extern unsigned long __privileged_functions_start__[]; +extern unsigned long __privileged_functions_end__[]; +extern unsigned long __FLASH_segment_start__[]; +extern unsigned long __FLASH_segment_end__[]; +volatile unsigned long *pul; +volatile unsigned long ulReadData; +const volatile unsigned long *pulSystemPeripheralRegister = ( volatile unsigned long * ) 0xe000e014; /* Systick */ +const volatile unsigned long *pulStandardPeripheralRegister = ( volatile unsigned long * ) 0x400FC0C4; /* PCONP */ + + ( void ) pvParameters; + + /* This task is created in Privileged mode using the original xTaskCreate() + API function. It should have access to all Flash and RAM including that + marked as Privileged access only. So reading from the start and end of the + non-privileged RAM should not cause a problem (the privileged RAM is the + first block at the bottom of the RAM memory). */ + pul = __privileged_data_end__ + 1; + ulReadData = *pul; + pul = __SRAM_segment_end__ - 1; + ulReadData = *pul; + + /* Likewise reading from the start and end of the non-privileged Flash + should not be a problem (the privileged Flash is the first block at the + bottom of the Flash memory). */ + pul = __privileged_functions_end__ + 1; + ulReadData = *pul; + pul = __FLASH_segment_end__ - 1; + ulReadData = *pul; + + /* Reading from anywhere inside the privileged Flash or RAM should also + not be a problem. */ + pul = __privileged_functions_start__; + ulReadData = *pul; + pul = __privileged_functions_end__ - 1; + ulReadData = *pul; + pul = __privileged_data_start__; + ulReadData = *pul; + pul = __privileged_data_end__ - 1; + ulReadData = *pul; + + /* Finally, accessing both System and normal peripherals should both be + possible. */ + ulReadData = *pulSystemPeripheralRegister; + ulReadData = *pulStandardPeripheralRegister; + + /* Must not just run off the end of a task function, so delete this task. + Note that because this task was created using xTaskCreate() the stack was + allocated dynamically and I have not included any code to free it again. */ vTaskDelete( NULL ); } /*-----------------------------------------------------------*/