--- /dev/null
+/*****************************************************************************\r
+ * Copyright (c) 2006 Rowley Associates Limited. *\r
+ * *\r
+ * This file may be distributed under the terms of the License Agreement *\r
+ * provided with this software. *\r
+ * *\r
+ * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE *\r
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *\r
+ *****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ * Preprocessor Definitions\r
+ * ------------------------\r
+ *\r
+ * STARTUP_FROM_RESET\r
+ *\r
+ * If defined, the program will startup from power-on/reset. If not defined\r
+ * the program will just loop endlessly from power-on/reset.\r
+ *\r
+ * This definition is not defined by default on this target because the\r
+ * debugger is unable to reset this target and maintain control of it over the\r
+ * JTAG interface. The advantage of doing this is that it allows the debugger\r
+ * to reset the CPU and run programs from a known reset CPU state on each run.\r
+ * It also acts as a safety net if you accidently download a program in FLASH\r
+ * that crashes and prevents the debugger from taking control over JTAG\r
+ * rendering the target unusable over JTAG. The obvious disadvantage of doing\r
+ * this is that your application will not startup without the debugger.\r
+ *\r
+ * We advise that on this target you keep STARTUP_FROM_RESET undefined whilst\r
+ * you are developing and only define STARTUP_FROM_RESET when development is\r
+ * complete.\r
+ *\r
+ *****************************************************************************/\r
+\r
+.extern xPortPendSVHandler\r
+.extern xPortSysTickHandler\r
+.extern vPortSVCHandler\r
+\r
+.global reset_handler\r
+\r
+.macro DEFAULT_ISR_HANDLER name=\r
+ .thumb_func\r
+ .weak \name\r
+\name:\r
+1: b 1b /* endless loop */\r
+.endm\r
+\r
+ .section .vectors, "ax"\r
+ .code 16\r
+ .align 0\r
+ .global _vectors\r
+\r
+_vectors:\r
+ .word __stack_end__\r
+#ifdef STARTUP_FROM_RESET\r
+ .word reset_handler\r
+#else\r
+ .word reset_wait\r
+#endif /* STARTUP_FROM_RESET */\r
+ .word Nmi_ISR\r
+ .word Fault_ISR\r
+ .word MPU_Fault_ISR\r
+ .word 0 /* Populate if using Bus fault */\r
+ .word 0 /* Populate if using Usage fault */\r
+ .word 0 /* Reserved */\r
+ .word 0 /* Reserved */\r
+ .word 0 /* Reserved */\r
+ .word 0 /* Reserved */\r
+ .word vPortSVCHandler\r
+ .word 0 /* Populate if using a debug monitor */\r
+ .word 0 /* Reserved */\r
+ .word xPortPendSVHandler\r
+ .word xPortSysTickHandler\r
+ .word GPIO_Port_A_ISR\r
+ .word GPIO_Port_B_ISR\r
+ .word GPIO_Port_C_ISR\r
+ .word GPIO_Port_D_ISR\r
+ .word GPIO_Port_E_ISR\r
+ .word UART0_ISR\r
+ .word UART1_ISR\r
+ .word SSI_ISR\r
+ .word I2C_ISR\r
+ .word PWM_Fault_ISR\r
+ .word PWM_Generator_0_ISR\r
+ .word PWM_Generator_1_ISR\r
+ .word PWM_Generator_2_ISR\r
+ .word QEI_ISR\r
+ .word ADC_Sequence_0_ISR\r
+ .word ADC_Sequence_1_ISR\r
+ .word ADC_Sequence_2_ISR\r
+ .word ADC_Sequence_3_ISR\r
+ .word Watchdog_Timer_ISR\r
+ .word Timer0A_ISR\r
+ .word Timer0B_ISR\r
+ .word Timer1A_ISR\r
+ .word Timer1B_ISR\r
+ .word Timer2A_ISR\r
+ .word Timer2B_ISR\r
+ .word Analog_Comparator_0_ISR\r
+ .word Analog_Comparator_1_ISR\r
+ .word Analog_Comparator_2_ISR\r
+ .word System_Control_ISR\r
+ .word FLASH_Control_ISR\r
+ .word GPIO_Port_F_ISR\r
+ .word GPIO_Port_G_ISR\r
+ .word GPIO_Port_H_ISR\r
+ .word UART2_ISR\r
+ .word SSI1_ISR\r
+ .word Timer3A_ISR\r
+ .word Timer3B_ISR\r
+ .word I2C1_ISR\r
+ .word QEI1_ISR\r
+ .word CAN0_ISR\r
+ .word CAN1_ISR\r
+ .word CAN2_ISR\r
+ .word EMAC_ISR\r
+ .word HIBERNATE_ISR\r
+ .word USB0_ISR\r
+ .word PWM_Generator_3_ISR\r
+ .word uDMA_Software_Transfer_ISR\r
+ .word uDMA_Error_ISR\r
+_vectors_end:\r
+\r
+ .section .init, "ax"\r
+ .thumb_func\r
+\r
+reset_handler:\r
+#ifdef __RAM_BUILD\r
+ /* If this is a RAM build, configure vector table offset register to point\r
+ to the RAM vector table. */\r
+ ldr r0, =0xE000ED08\r
+ ldr r1, =_vectors\r
+ str r1, [r0]\r
+#endif\r
+ b _start\r
+\r
+DEFAULT_ISR_HANDLER Nmi_ISR\r
+/*DEFAULT_ISR_HANDLER Fault_ISR*/\r
+/*DEFAULT_ISR_HANDLER MPU_Fault_ISR*/\r
+DEFAULT_ISR_HANDLER SVCall_ISR\r
+DEFAULT_ISR_HANDLER SysTick_ISR\r
+DEFAULT_ISR_HANDLER PendSV_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_A_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_B_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_C_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_D_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_E_ISR\r
+DEFAULT_ISR_HANDLER UART0_ISR\r
+DEFAULT_ISR_HANDLER UART1_ISR\r
+DEFAULT_ISR_HANDLER SSI_ISR\r
+DEFAULT_ISR_HANDLER I2C_ISR\r
+DEFAULT_ISR_HANDLER PWM_Fault_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_0_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_1_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_2_ISR\r
+DEFAULT_ISR_HANDLER QEI_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_0_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_1_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_2_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_3_ISR\r
+DEFAULT_ISR_HANDLER Watchdog_Timer_ISR\r
+DEFAULT_ISR_HANDLER Timer0A_ISR\r
+DEFAULT_ISR_HANDLER Timer0B_ISR\r
+DEFAULT_ISR_HANDLER Timer1A_ISR\r
+DEFAULT_ISR_HANDLER Timer1B_ISR\r
+DEFAULT_ISR_HANDLER Timer2A_ISR\r
+DEFAULT_ISR_HANDLER Timer2B_ISR\r
+DEFAULT_ISR_HANDLER Analog_Comparator_0_ISR\r
+DEFAULT_ISR_HANDLER Analog_Comparator_1_ISR\r
+DEFAULT_ISR_HANDLER Analog_Comparator_2_ISR\r
+DEFAULT_ISR_HANDLER System_Control_ISR\r
+DEFAULT_ISR_HANDLER FLASH_Control_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_F_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_G_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_H_ISR\r
+DEFAULT_ISR_HANDLER UART2_ISR\r
+DEFAULT_ISR_HANDLER SSI1_ISR\r
+DEFAULT_ISR_HANDLER Timer3A_ISR\r
+DEFAULT_ISR_HANDLER Timer3B_ISR\r
+DEFAULT_ISR_HANDLER I2C1_ISR\r
+DEFAULT_ISR_HANDLER QEI1_ISR\r
+DEFAULT_ISR_HANDLER CAN0_ISR\r
+DEFAULT_ISR_HANDLER CAN1_ISR\r
+DEFAULT_ISR_HANDLER CAN2_ISR\r
+DEFAULT_ISR_HANDLER ETHERNET_ISR\r
+DEFAULT_ISR_HANDLER HIBERNATE_ISR\r
+DEFAULT_ISR_HANDLER USB0_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_3_ISR\r
+DEFAULT_ISR_HANDLER uDMA_Software_Transfer_ISR\r
+DEFAULT_ISR_HANDLER uDMA_Error_ISR\r
+DEFAULT_ISR_HANDLER EMAC_ISR\r
+\r
+#ifndef STARTUP_FROM_RESET\r
+DEFAULT_ISR_HANDLER reset_wait\r
+#endif /* STARTUP_FROM_RESET */\r
+\r
--- /dev/null
+/*\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
+*/\r
+\r
+/* Standard includes. */\r
+#include <string.h>\r
+#include <__cross_studio_io.h>\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Hardware library includes. */\r
+#include "hw_types.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
+#define mainDONT_BLOCK ( 0 )\r
+\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
+/* GCC specifics. */\r
+#define mainALIGN_TO( x ) __attribute__((aligned(x)))\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for functions that implement tasks. -----------*/\r
+/*-----------------------------------------------------------*/\r
+\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.\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
+ * 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
+ */\r
+static void prvCheckTask( void *pvParameters );\r
+\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for other misc functions. --------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Just configures any clocks and IO necessary.\r
+ */\r
+static void prvSetupHardware( void );\r
+\r
+/*\r
+ * Simply deletes the calling task. The function is provided only because it\r
+ * is simpler to call from asm code than the normal vTaskDelete() API function.\r
+ * It has the noinline attribute because it is called from asm code.\r
+ */\r
+static void prvDeleteMe( void ) __attribute__((noinline));\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
+ * 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 void prvSendImAlive( xQueueHandle xHandle, unsigned long ulTaskNumber );\r
+\r
+/*\r
+ * The check task is created with access to three memory regions (plus its\r
+ * stack). Each memory region is configured with different parameters and\r
+ * prvTestMemoryRegions() demonstrates what can and cannot be accessed for each\r
+ * region. prvTestMemoryRegions() also demonstrates a task that was created\r
+ * as a privileged task settings its own privilege level down to that of a user\r
+ * task.\r
+ */\r
+static void prvTestMemoryRegions( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\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
+/*-----------------------------------------------------------*/\r
+/* Data used by the 'check' task. ---------------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Define the constants used to allocate the check task stack. Note that the\r
+stack size is defined in words, not bytes. */\r
+#define mainCHECK_TASK_STACK_SIZE_WORDS 128\r
+#define mainCHECK_TASK_STACK_ALIGNMENT ( mainCHECK_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )\r
+\r
+/* Declare the stack that will be used by the check task. The kernel will\r
+ automatically create an MPU region for the stack. The stack alignment must \r
+ match its size, so if 128 words are reserved for the stack then it must be \r
+ aligned to ( 128 * 4 ) bytes. */\r
+static portSTACK_TYPE xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainCHECK_TASK_STACK_ALIGNMENT );\r
+\r
+/* Declare 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
+#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. */\r
+static const xTaskParameters xCheckTaskParameters =\r
+{\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. */\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
+\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. */\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. */\r
+ /* Base address Length Parameters */\r
+ { 0x00, 0x00, 0x00 },\r
+ { 0x00, 0x00, 0x00 },\r
+ { 0x00, 0x00, 0x00 }\r
+ }\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\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. */\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
+ /* Start the scheduler. */\r
+ vTaskStartScheduler();\r
+\r
+ /* Will only get here if there was insufficient memory to create the idle\r
+ task. */\r
+ for( ;; );\r
+ return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckTask( void *pvParameters )\r
+{\r
+/* This task is created in privileged mode so can access the file scope\r
+queue variable. Take a stack copy of this before the task is set into user\r
+mode. Once that task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+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
+ /* 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
+ 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
+static void prvTestMemoryRegions( void )\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
+ cPrivilegedOnlyAccessArray[ 0 ] = 'a';\r
+ if( cPrivilegedOnlyAccessArray[ 0 ] != 'a' )\r
+ {\r
+ /* Something unexpected happened. Delete this task so the error is\r
+ apparent (no output will be displayed). */\r
+ prvDeleteMe();\r
+ }\r
+\r
+ /* Writing off the end of the RAM allocated to this task will *NOT* cause a\r
+ protection fault because the task is still executing in a privileged mode. \r
+ Uncomment the following to test. */\r
+ /*cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] = 'a';*/\r
+\r
+ /* Now set the task into user mode. */\r
+ portSWITCH_TO_USER_MODE();\r
+ \r
+ /* Accessing the privileged only array will now cause a fault. Uncomment \r
+ the following line to test. */ \r
+ /*cPrivilegedOnlyAccessArray[ 0 ] = 'a';*/\r
+\r
+ /* The read/write array can still be successfully read and written. */\r
+ for( l = 0; l < mainREAD_WRITE_ALIGN_SIZE; l++ )\r
+ {\r
+ cReadWriteArray[ l ] = 'a';\r
+ if( cReadWriteArray[ l ] != 'a' )\r
+ {\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
+ /* 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
+static void prvRegTest1Task( void *pvParameters )\r
+{\r
+/* This task is created in privileged mode so can access the file scope\r
+queue variable. Take a stack copy of this before the task is set into user\r
+mode. Once that task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+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
+ /* Error detected. Delete the task so it stops communicating with\r
+ the check task. */\r
+ prvDeleteMe();\r
+ }\r
+\r
+\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
+ );\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 check task uses a different \r
+method. */\r
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
+\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, #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
+ );\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
+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
+{\r
+ /* If configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2 then this \r
+ function will automatically get called if a task overflows its stack. */\r
+ ( void ) pxTask;\r
+ ( void ) pcTaskName;\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationMallocFailedHook( void )\r
+{\r
+ /* If configUSE_MALLOC_FAILED_HOOK is set to 1 then this function will\r
+ be called automatically if a call to pvPortMalloc() fails. pvPortMalloc()\r
+ is called automatically when a task, queue or semaphore is created. */\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* 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
+unsigned int stacked_r0;\r
+unsigned int stacked_r1;\r
+unsigned int stacked_r2;\r
+unsigned int stacked_r3;\r
+unsigned int stacked_r12;\r
+unsigned int stacked_lr;\r
+unsigned int stacked_pc;\r
+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