From 5acf205d2565cb9b384267320f360659b67720ce Mon Sep 17 00:00:00 2001 From: rtel Date: Tue, 20 Sep 2016 13:54:28 +0000 Subject: [PATCH] Add support for statically allocated memory protected tasks - previously only dynamically allocated tasks could be memory protected. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2471 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../FreeRTOSConfig.h | 220 +++ .../GCC_Specific/RTOSDemo.uvoptx | 369 +++++ .../GCC_Specific/RTOSDemo.uvprojx | 348 +++++ .../GCC_Specific/RegTest.c | 692 ++++++++++ .../GCC_Specific/sections.ld | 356 +++++ .../GCC_Specific/startup_ARMCM4.S | 217 +++ .../Keil_Specific/RTOSDemo.sct | 23 + .../Keil_Specific/RTOSDemo.uvoptx | 358 +++++ .../Keil_Specific/RTOSDemo.uvprojx | 451 +++++++ .../Keil_Specific/RegTest.c | 703 ++++++++++ .../Keil_Specific/startup_MPS_CM4.S | 172 +++ .../main.c | 1196 +++++++++++++++++ FreeRTOS/Source/include/mpu_prototypes.h | 1 + FreeRTOS/Source/include/mpu_wrappers.h | 5 +- FreeRTOS/Source/include/task.h | 96 ++ .../Source/portable/Common/mpu_wrappers.c | 73 +- FreeRTOS/Source/tasks.c | 58 +- 17 files changed, 5302 insertions(+), 36 deletions(-) create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S create mode 100644 FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h new file mode 100644 index 000000000..a8df38e6c --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/FreeRTOSConfig.h @@ -0,0 +1,220 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +/* The MPU version of port.c includes and excludes functions depending on the +settings within this file. Therefore, to ensure all the functions in port.c +build, this configuration file has all options turned on. */ + +#define configUSE_PREEMPTION 1 +#define configTICK_RATE_HZ ( 1000 ) +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_QUEUE_SETS 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configCPU_CLOCK_HZ 48000000 +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 10 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 5 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_TICKLESS_IDLE 0 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 2 + +/* This demo shows the MPU being used without any dynamic memory allocation. */ +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Run time stats gathering definitions. */ +#define configGENERATE_RUN_TIME_STATS 1 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#define portGET_RUN_TIME_COUNTER_VALUE() 0 + +/* This demo makes use of one or more example stats formatting functions. These +format the raw data provided by the uxTaskGetSystemState() function in to human +readable ASCII form. See the notes in the implementation of vTaskList() within +FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( 2 ) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE ) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTimerPendFunctionCall 0 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS +standard names. */ +#define xPortPendSVHandler PendSV_Handler +#define vPortSVCHandler SVC_Handler +#define xPortSysTickHandler SysTick_Handler + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT( x ) if( ( x ) == 0UL ) { taskDISABLE_INTERRUPTS(); for( ;; ); } + +/* LED not used at present, so just increment a variable to keep a count of the +number of times the LED would otherwise have been toggled. */ +#define configTOGGLE_LED() ulLED++ + +/* Definitions for the messages that can be sent to the check task. */ +#define configREG_TEST_1_STILL_EXECUTING ( 0 ) +#define configREG_TEST_2_STILL_EXECUTING ( 1 ) +#define configTIMER_STILL_EXECUTING ( 2 ) +#define configPRINT_SYSTEM_STATUS ( 3 ) + +/* Parameters that are passed into the third and fourth register check tasks +solely for the purpose of ensuring parameters are passed into tasks correctly. */ +#define configREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x11112222 ) +#define configREG_TEST_TASK_3_PARAMETER ( ( void * ) 0x12345678 ) +#define configREG_TEST_TASK_4_PARAMETER ( ( void * ) 0x87654321 ) + +#ifdef __cplusplus +} +#endif + +#endif /* FREERTOS_CONFIG_H */ + diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx new file mode 100644 index 000000000..c9679d2b4 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvoptx @@ -0,0 +1,369 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c;*.S + + *.obj + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + RTOSDemo_GCC_MPU + 0x3 + ARM-GNU + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 120 + 65 + 8 + .\Listings\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 7 + + 1 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + + + BIN\UL2CM3.DLL + + + + 0 + DLGDARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=1215,201,1680,501,0) + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=120,149,354,683,0)(1012=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + -T0 + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + + + 0 + UL2CM3 + -UV1115SAE -O2983 -S0 -C0 -P00 -N00("ARM CoreSight JTAG-DP") -D00(4BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO11 -FN1 -FC1000 -FD20000000 -FF0NEW_DEVICE -FL080000 -FS00 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM) + + + + + + 0 + 1 + xTickCount + + + 1 + 1 + ulCycleCount + + + + + 1 + 2 + 0x100000 + 4 + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + + + 0 + + 1 + 0 + 2 + 10000000 + + + + + + System + 1 + 0 + 0 + 0 + + 1 + 1 + 2 + 0 + 0 + 0 + .\startup_ARMCM4.S + startup_ARMCM4.S + 0 + 0 + + + + + application_and_config + 1 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\main.c + main.c + 0 + 0 + + + 2 + 3 + 5 + 0 + 0 + 0 + ..\FreeRTOSConfig.h + FreeRTOSConfig.h + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + .\RegTest.c + RegTest.c + 0 + 0 + + + + + FreeRTOS_Source + 1 + 0 + 0 + 0 + + 3 + 5 + 1 + 0 + 0 + 0 + ..\..\..\Source\event_groups.c + event_groups.c + 0 + 0 + + + 3 + 6 + 1 + 0 + 0 + 0 + ..\..\..\Source\list.c + list.c + 0 + 0 + + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\Source\queue.c + queue.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\Source\tasks.c + tasks.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\Source\timers.c + timers.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\Source\portable\Common\mpu_wrappers.c + mpu_wrappers.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\Source\portable\GCC\ARM_CM4_MPU\port.c + port.c + 0 + 0 + + + +
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx new file mode 100644 index 000000000..645d4826d --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RTOSDemo.uvprojx @@ -0,0 +1,348 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + RTOSDemo_GCC_MPU + 0x3 + ARM-GNU + 5060061::V5.06 update 1 (build 61)::ARMCC + + + ARMCM4_FP + ARM + ARM.CMSIS.5.0.0-Beta4 + http://www.keil.com/pack/ + IROM(0x00000000,0x80000) IRAM(0x20000000,0x20000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ESEL ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0NEW_DEVICE -FS00 -FL080000 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM)) + 0 + $$Device:ARMCM4_FP$Device\ARM\ARMCM4\Include\ARMCM4_FP.h + + + + + + + + + + $$Device:ARMCM4_FP$Device\ARM\SVD\ARMCM4.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + RTOSDemo + 1 + 0 + 0 + 1 + 0 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + "Cortex-M4" + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x0 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 1 + 0x200000 + 0x4000 + + + + + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 2 + 1 + + -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -ffunction-sections -fdata-sections -O0 -g + + + ..;..\..\..\Source\include;..\..\..\Source\portable\GCC\ARM_CM4_MPU;..\..\Common\include;..\peripheral_library;..\CMSIS;..\main_full;..\peripheral_library\interrupt + + + + 0 + 1 + + + + + + + + + 1 + 0 + 1 + 0 + 1 + + + + + + -Xlinker --gc-sections + .\sections.ld + + + + + + System + + + startup_ARMCM4.S + 2 + .\startup_ARMCM4.S + + + + + application_and_config + + + main.c + 1 + ..\main.c + + + FreeRTOSConfig.h + 5 + ..\FreeRTOSConfig.h + + + RegTest.c + 1 + .\RegTest.c + + + + + FreeRTOS_Source + + + event_groups.c + 1 + ..\..\..\Source\event_groups.c + + + list.c + 1 + ..\..\..\Source\list.c + + + queue.c + 1 + ..\..\..\Source\queue.c + + + tasks.c + 1 + ..\..\..\Source\tasks.c + + + timers.c + 1 + ..\..\..\Source\timers.c + + + mpu_wrappers.c + 1 + ..\..\..\Source\portable\Common\mpu_wrappers.c + + + port.c + 1 + ..\..\..\Source\portable\GCC\ARM_CM4_MPU\port.c + + + + + + + +
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c new file mode 100644 index 000000000..5b45ce166 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/RegTest.c @@ -0,0 +1,692 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" + +/* + * "Reg test" tasks - These fill the registers with known values, then check + * that each register maintains its expected value for the lifetime of the + * task. Each task uses a different set of values. The reg test tasks execute + * with a very low priority, so get preempted very frequently. A register + * containing an unexpected value is indicative of an error in the context + * switching mechanism. + */ + +void vRegTest1Implementation( void *pvParameters ); +void vRegTest2Implementation( void *pvParameters ); +void vRegTest3Implementation( void ) __attribute__ ((naked)); +void vRegTest4Implementation( void ) __attribute__ ((naked)); + +/* + * Used as an easy way of deleting a task from inline assembly. + */ +extern void vMainDeleteMe( void ) __attribute__((noinline)); + +/* + * Used by the first two reg test tasks and a software timer callback function + * to send messages to the check task. The message just lets the check task + * know that the tasks and timer are 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. + */ +extern void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber ); + +/* The queue used to send a message to the check task. */ +extern QueueHandle_t xGlobalScopeCheckQueue; + +/*-----------------------------------------------------------*/ + +void vRegTest1Implementation( 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 this task is in user mode the file scope queue variable will no +longer be accessible but the stack copy will. */ +QueueHandle_t xQueue = xGlobalScopeCheckQueue; + + /* Now the queue handle has been obtained the task can switch to user + mode. This is just one method of passing a handle into a protected + task, the other reg test task uses the task parameter instead. */ + portSWITCH_TO_USER_MODE(); + + /* First check that the parameter value is as expected. */ + if( pvParameters != ( void * ) configREG_TEST_TASK_1_PARAMETER ) + { + /* Error detected. Delete the task so it stops communicating with + the check task. */ + vMainDeleteMe(); + } + + for( ;; ) + { + /* This task tests the kernel context switch mechanism by reading and + writing directly to registers - which requires the test to be written + in assembly code. */ + __asm volatile + ( + " MOV R4, #104 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */ + " MOV R5, #105 \n" + " MOV R6, #106 \n" + " MOV R8, #108 \n" + " MOV R9, #109 \n" + " MOV R10, #110 \n" + " MOV R11, #111 \n" + "reg1loop: \n" + " MOV R0, #100 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */ + " MOV R1, #101 \n" + " MOV R2, #102 \n" + " MOV R3, #103 \n" + " MOV R12, #112 \n" + " SVC #1 \n" /* Yield just to increase test coverage. */ + " CMP R0, #100 \n" /* Check all the registers still contain their expected values. */ + " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */ + " CMP R1, #101 \n" + " BNE vMainDeleteMe \n" + " CMP R2, #102 \n" + " BNE vMainDeleteMe \n" + " CMP R3, #103 \n" + " BNE vMainDeleteMe \n" + " CMP R4, #104 \n" + " BNE vMainDeleteMe \n" + " CMP R5, #105 \n" + " BNE vMainDeleteMe \n" + " CMP R6, #106 \n" + " BNE vMainDeleteMe \n" + " CMP R8, #108 \n" + " BNE vMainDeleteMe \n" + " CMP R9, #109 \n" + " BNE vMainDeleteMe \n" + " CMP R10, #110 \n" + " BNE vMainDeleteMe \n" + " CMP R11, #111 \n" + " BNE vMainDeleteMe \n" + " CMP R12, #112 \n" + " BNE vMainDeleteMe \n" + :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); + + /* Send configREG_TEST_1_STILL_EXECUTING to the check task to indicate that this + task is still functioning. */ + vMainSendImAlive( xQueue, configREG_TEST_1_STILL_EXECUTING ); + + /* Go back to check all the register values again. */ + __asm volatile( " B reg1loop " ); + } +} +/*-----------------------------------------------------------*/ + +void vRegTest2Implementation( 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 reg test task uses a different +method. */ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; + + for( ;; ) + { + /* This task tests the kernel context switch mechanism by reading and + writing directly to registers - which requires the test to be written + in assembly code. */ + __asm volatile + ( + " MOV R4, #4 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */ + " MOV R5, #5 \n" + " MOV R6, #6 \n" + " MOV R8, #8 \n" /* Frame pointer is omitted as it must not be changed. */ + " MOV R9, #9 \n" + " MOV R10, 10 \n" + " MOV R11, #11 \n" + "reg2loop: \n" + " MOV R0, #13 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */ + " MOV R1, #1 \n" + " MOV R2, #2 \n" + " MOV R3, #3 \n" + " MOV R12, #12 \n" + " CMP R0, #13 \n" /* Check all the registers still contain their expected values. */ + " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task */ + " CMP R1, #1 \n" + " BNE vMainDeleteMe \n" + " CMP R2, #2 \n" + " BNE vMainDeleteMe \n" + " CMP R3, #3 \n" + " BNE vMainDeleteMe \n" + " CMP R4, #4 \n" + " BNE vMainDeleteMe \n" + " CMP R5, #5 \n" + " BNE vMainDeleteMe \n" + " CMP R6, #6 \n" + " BNE vMainDeleteMe \n" + " CMP R8, #8 \n" + " BNE vMainDeleteMe \n" + " CMP R9, #9 \n" + " BNE vMainDeleteMe \n" + " CMP R10, #10 \n" + " BNE vMainDeleteMe \n" + " CMP R11, #11 \n" + " BNE vMainDeleteMe \n" + " CMP R12, #12 \n" + " BNE vMainDeleteMe \n" + :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); + + /* Send configREG_TEST_2_STILL_EXECUTING to the check task to indicate that this + task is still functioning. */ + vMainSendImAlive( xQueue, configREG_TEST_2_STILL_EXECUTING ); + + /* Go back to check all the register values again. */ + __asm volatile( " B reg2loop " ); + } +} +/*-----------------------------------------------------------*/ + +void vRegTest3Implementation( void ) +{ + __asm volatile + ( + ".extern pulRegTest3LoopCounter \n" + "/* Fill the core registers with known values. */ \n" + "mov r0, #100 \n" + "mov r1, #101 \n" + "mov r2, #102 \n" + "mov r3, #103 \n" + "mov r4, #104 \n" + "mov r5, #105 \n" + "mov r6, #106 \n" + "mov r7, #107 \n" + "mov r8, #108 \n" + "mov r9, #109 \n" + "mov r10, #110 \n" + "mov r11, #111 \n" + "mov r12, #112 \n" + + "/* Fill the VFP registers with known values. */ \n" + "vmov d0, r0, r1 \n" + "vmov d1, r2, r3 \n" + "vmov d2, r4, r5 \n" + "vmov d3, r6, r7 \n" + "vmov d4, r8, r9 \n" + "vmov d5, r10, r11 \n" + "vmov d6, r0, r1 \n" + "vmov d7, r2, r3 \n" + "vmov d8, r4, r5 \n" + "vmov d9, r6, r7 \n" + "vmov d10, r8, r9 \n" + "vmov d11, r10, r11 \n" + "vmov d12, r0, r1 \n" + "vmov d13, r2, r3 \n" + "vmov d14, r4, r5 \n" + "vmov d15, r6, r7 \n" + + "reg1_loop: \n" + "/* Check all the VFP registers still contain the values set above. \n" + "First save registers that are clobbered by the test. */ \n" + "push { r0-r1 } \n" + + "vmov r0, r1, d0 \n" + "cmp r0, #100 \n" + "bne reg1_error_loopf \n" + "cmp r1, #101 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d1 \n" + "cmp r0, #102 \n" + "bne reg1_error_loopf \n" + "cmp r1, #103 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d2 \n" + "cmp r0, #104 \n" + "bne reg1_error_loopf \n" + "cmp r1, #105 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d3 \n" + "cmp r0, #106 \n" + "bne reg1_error_loopf \n" + "cmp r1, #107 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d4 \n" + "cmp r0, #108 \n" + "bne reg1_error_loopf \n" + "cmp r1, #109 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d5 \n" + "cmp r0, #110 \n" + "bne reg1_error_loopf \n" + "cmp r1, #111 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d6 \n" + "cmp r0, #100 \n" + "bne reg1_error_loopf \n" + "cmp r1, #101 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d7 \n" + "cmp r0, #102 \n" + "bne reg1_error_loopf \n" + "cmp r1, #103 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d8 \n" + "cmp r0, #104 \n" + "bne reg1_error_loopf \n" + "cmp r1, #105 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d9 \n" + "cmp r0, #106 \n" + "bne reg1_error_loopf \n" + "cmp r1, #107 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d10 \n" + "cmp r0, #108 \n" + "bne reg1_error_loopf \n" + "cmp r1, #109 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d11 \n" + "cmp r0, #110 \n" + "bne reg1_error_loopf \n" + "cmp r1, #111 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d12 \n" + "cmp r0, #100 \n" + "bne reg1_error_loopf \n" + "cmp r1, #101 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d13 \n" + "cmp r0, #102 \n" + "bne reg1_error_loopf \n" + "cmp r1, #103 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d14 \n" + "cmp r0, #104 \n" + "bne reg1_error_loopf \n" + "cmp r1, #105 \n" + "bne reg1_error_loopf \n" + "vmov r0, r1, d15 \n" + "cmp r0, #106 \n" + "bne reg1_error_loopf \n" + "cmp r1, #107 \n" + "bne reg1_error_loopf \n" + + "/* Restore the registers that were clobbered by the test. */ \n" + "pop {r0-r1} \n" + + "/* VFP register test passed. Jump to the core register test. */ \n" + "b reg1_loopf_pass \n" + + "reg1_error_loopf: \n" + "/* If this line is hit then a VFP register value was found to be incorrect. */ \n" + "b reg1_error_loopf \n" + + "reg1_loopf_pass: \n" + + "cmp r0, #100 \n" + "bne reg1_error_loop \n" + "cmp r1, #101 \n" + "bne reg1_error_loop \n" + "cmp r2, #102 \n" + "bne reg1_error_loop \n" + "cmp r3, #103 \n" + "bne reg1_error_loop \n" + "cmp r4, #104 \n" + "bne reg1_error_loop \n" + "cmp r5, #105 \n" + "bne reg1_error_loop \n" + "cmp r6, #106 \n" + "bne reg1_error_loop \n" + "cmp r7, #107 \n" + "bne reg1_error_loop \n" + "cmp r8, #108 \n" + "bne reg1_error_loop \n" + "cmp r9, #109 \n" + "bne reg1_error_loop \n" + "cmp r10, #110 \n" + "bne reg1_error_loop \n" + "cmp r11, #111 \n" + "bne reg1_error_loop \n" + "cmp r12, #112 \n" + "bne reg1_error_loop \n" + + "/* Everything passed, increment the loop counter. */ \n" + "push { r0-r1 } \n" + "ldr r0, =pulRegTest3LoopCounter \n" + "ldr r0, [r0] \n" + "ldr r1, [r0] \n" + "adds r1, r1, #1 \n" + "str r1, [r0] \n" + "pop { r0-r1 } \n" + + "/* Start again. */ \n" + "b reg1_loop \n" + + "reg1_error_loop: \n" + "/* If this line is hit then there was an error in a core register value. \n" + "The loop ensures the loop counter stops incrementing. */ \n" + "b reg1_error_loop \n" + "nop " + ); /* __asm volatile. */ +} +/*-----------------------------------------------------------*/ + +void vRegTest4Implementation( void ) +{ + __asm volatile + ( + ".extern pulRegTest4LoopCounter \n" + "/* Set all the core registers to known values. */ \n" + "mov r0, #-1 \n" + "mov r1, #1 \n" + "mov r2, #2 \n" + "mov r3, #3 \n" + "mov r4, #4 \n" + "mov r5, #5 \n" + "mov r6, #6 \n" + "mov r7, #7 \n" + "mov r8, #8 \n" + "mov r9, #9 \n" + "mov r10, #10 \n" + "mov r11, #11 \n" + "mov r12, #12 \n" + + "/* Set all the VFP to known values. */ \n" + "vmov d0, r0, r1 \n" + "vmov d1, r2, r3 \n" + "vmov d2, r4, r5 \n" + "vmov d3, r6, r7 \n" + "vmov d4, r8, r9 \n" + "vmov d5, r10, r11 \n" + "vmov d6, r0, r1 \n" + "vmov d7, r2, r3 \n" + "vmov d8, r4, r5 \n" + "vmov d9, r6, r7 \n" + "vmov d10, r8, r9 \n" + "vmov d11, r10, r11 \n" + "vmov d12, r0, r1 \n" + "vmov d13, r2, r3 \n" + "vmov d14, r4, r5 \n" + "vmov d15, r6, r7 \n" + + "reg2_loop: \n" + + "/* Check all the VFP registers still contain the values set above. \n" + "First save registers that are clobbered by the test. */ \n" + "push { r0-r1 } \n" + + "vmov r0, r1, d0 \n" + "cmp r0, #-1 \n" + "bne reg2_error_loopf \n" + "cmp r1, #1 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d1 \n" + "cmp r0, #2 \n" + "bne reg2_error_loopf \n" + "cmp r1, #3 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d2 \n" + "cmp r0, #4 \n" + "bne reg2_error_loopf \n" + "cmp r1, #5 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d3 \n" + "cmp r0, #6 \n" + "bne reg2_error_loopf \n" + "cmp r1, #7 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d4 \n" + "cmp r0, #8 \n" + "bne reg2_error_loopf \n" + "cmp r1, #9 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d5 \n" + "cmp r0, #10 \n" + "bne reg2_error_loopf \n" + "cmp r1, #11 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d6 \n" + "cmp r0, #-1 \n" + "bne reg2_error_loopf \n" + "cmp r1, #1 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d7 \n" + "cmp r0, #2 \n" + "bne reg2_error_loopf \n" + "cmp r1, #3 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d8 \n" + "cmp r0, #4 \n" + "bne reg2_error_loopf \n" + "cmp r1, #5 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d9 \n" + "cmp r0, #6 \n" + "bne reg2_error_loopf \n" + "cmp r1, #7 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d10 \n" + "cmp r0, #8 \n" + "bne reg2_error_loopf \n" + "cmp r1, #9 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d11 \n" + "cmp r0, #10 \n" + "bne reg2_error_loopf \n" + "cmp r1, #11 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d12 \n" + "cmp r0, #-1 \n" + "bne reg2_error_loopf \n" + "cmp r1, #1 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d13 \n" + "cmp r0, #2 \n" + "bne reg2_error_loopf \n" + "cmp r1, #3 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d14 \n" + "cmp r0, #4 \n" + "bne reg2_error_loopf \n" + "cmp r1, #5 \n" + "bne reg2_error_loopf \n" + "vmov r0, r1, d15 \n" + "cmp r0, #6 \n" + "bne reg2_error_loopf \n" + "cmp r1, #7 \n" + "bne reg2_error_loopf \n" + + "/* Restore the registers that were clobbered by the test. */ \n" + "pop {r0-r1} \n" + + "/* VFP register test passed. Jump to the core register test. */ \n" + "b reg2_loopf_pass \n" + + "reg2_error_loopf: \n" + "/* If this line is hit then a VFP register value was found to be \n" + "incorrect. */ \n" + "b reg2_error_loopf \n" + + "reg2_loopf_pass: \n" + + "cmp r0, #-1 \n" + "bne reg2_error_loop \n" + "cmp r1, #1 \n" + "bne reg2_error_loop \n" + "cmp r2, #2 \n" + "bne reg2_error_loop \n" + "cmp r3, #3 \n" + "bne reg2_error_loop \n" + "cmp r4, #4 \n" + "bne reg2_error_loop \n" + "cmp r5, #5 \n" + "bne reg2_error_loop \n" + "cmp r6, #6 \n" + "bne reg2_error_loop \n" + "cmp r7, #7 \n" + "bne reg2_error_loop \n" + "cmp r8, #8 \n" + "bne reg2_error_loop \n" + "cmp r9, #9 \n" + "bne reg2_error_loop \n" + "cmp r10, #10 \n" + "bne reg2_error_loop \n" + "cmp r11, #11 \n" + "bne reg2_error_loop \n" + "cmp r12, #12 \n" + "bne reg2_error_loop \n" + + "/* Increment the loop counter so the check task knows this task is \n" + "still running. */ \n" + "push { r0-r1 } \n" + "ldr r0, =pulRegTest4LoopCounter \n" + "ldr r0, [r0] \n" + "ldr r1, [r0] \n" + "adds r1, r1, #1 \n" + "str r1, [r0] \n" + "pop { r0-r1 } \n" + + "/* Yield to increase test coverage. */ \n" + "SVC #1 \n" + + "/* Start again. */ \n" + "b reg2_loop \n" + + "reg2_error_loop: \n" + "/* If this line is hit then there was an error in a core register value. \n" + "This loop ensures the loop counter variable stops incrementing. */ \n" + "b reg2_error_loop \n" + ); /* __asm volatile */ +} +/*-----------------------------------------------------------*/ + +/* Fault handlers are here for convenience as they use compiler specific syntax +and this file is specific to the GCC compiler. */ +void hard_fault_handler( uint32_t * hardfault_args ) +{ +volatile uint32_t stacked_r0; +volatile uint32_t stacked_r1; +volatile uint32_t stacked_r2; +volatile uint32_t stacked_r3; +volatile uint32_t stacked_r12; +volatile uint32_t stacked_lr; +volatile uint32_t stacked_pc; +volatile uint32_t stacked_psr; + + stacked_r0 = ((uint32_t) hardfault_args[ 0 ]); + stacked_r1 = ((uint32_t) hardfault_args[ 1 ]); + stacked_r2 = ((uint32_t) hardfault_args[ 2 ]); + stacked_r3 = ((uint32_t) hardfault_args[ 3 ]); + + stacked_r12 = ((uint32_t) hardfault_args[ 4 ]); + stacked_lr = ((uint32_t) hardfault_args[ 5 ]); + stacked_pc = ((uint32_t) hardfault_args[ 6 ]); + stacked_psr = ((uint32_t) hardfault_args[ 7 ]); + + /* Inspect stacked_pc to locate the offending instruction. */ + for( ;; ); + + ( void ) stacked_psr; + ( void ) stacked_pc; + ( void ) stacked_lr; + ( void ) stacked_r12; + ( void ) stacked_r0; + ( void ) stacked_r1; + ( void ) stacked_r2; + ( void ) stacked_r3; +} +/*-----------------------------------------------------------*/ + +void HardFault_Handler( void ) __attribute__((naked)); +void HardFault_Handler( void ) +{ + __asm volatile + ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, handler_address_const \n" + " bx r2 \n" + " handler_address_const: .word hard_fault_handler \n" + ); +} +/*-----------------------------------------------------------*/ + +void MemManage_Handler( void ) __attribute__((naked)); +void MemManage_Handler( void ) +{ + __asm volatile + ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, handler2_address_const \n" + " bx r2 \n" + " handler2_address_const: .word hard_fault_handler \n" + ); +}/*-----------------------------------------------------------*/ + diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld new file mode 100644 index 000000000..5ba471449 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/sections.ld @@ -0,0 +1,356 @@ +/* Default memory layout. */ +MEMORY +{ + ROM (rx) : ORIGIN = 0x00, LENGTH = 0x80000 + RAM (rw) : ORIGIN = 0x20000000, LENGTH = 0x8000 +} + +/* Variables used by FreeRTOS-MPU. */ +_Privileged_Functions_Region_Size = 32K; +_Privileged_Data_Region_Size = 2048; + +__FLASH_segment_start__ = ORIGIN( ROM ); +__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( ROM ); + +__privileged_functions_start__ = ORIGIN( ROM ); +__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size; + +__SRAM_segment_start__ = ORIGIN( RAM ); +__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( RAM ); + +__privileged_data_start__ = ORIGIN( RAM ); +__privileged_data_end__ = ORIGIN( RAM ) + _Privileged_Data_Region_Size; + + +/* + * The '__stack' definition is required by crt0, do not remove it. + */ +__stack = ORIGIN(RAM) + LENGTH(RAM); +_estack = __stack; + +/* + * Default stack sizes. + * These are used by the startup in order to allocate stacks + * for the different modes. + */ + +__Main_Stack_Size = 2048 ; + +PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ; + +__Main_Stack_Limit = __stack - __Main_Stack_Size ; + +/*"PROVIDE" allows to easily override these values from an object file or the command line. */ +PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ; + +/* + * There will be a link error if there is not this amount of + * RAM free at the end. + */ +_Minimum_Stack_Size = 1024 ; + +/* + * Default heap definitions. + * The heap start immediately after the last statically allocated + * .sbss/.noinit section, and extends up to the main stack limit. + */ +PROVIDE ( _Heap_Begin = _end_noinit ) ; +PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ; + +/* + * The entry point is informative, for debuggers and simulators, + * since the Cortex-M vector points to it anyway. + */ +ENTRY(_start) + +/* Sections Definitions */ + +SECTIONS +{ + /* + * For Cortex-M devices, the beginning of the startup code is stored in + * the .isr_vector section, which goes to ROM + */ + privileged_functions : + { + . = ALIGN(4); + _isr_vector = .; + KEEP(*(.isr_vector)) + *(privileged_functions) + . = ALIGN(4); + + /* Non privileged code is after _Privileged_Functions_Region_Size. */ + __privileged_functions_actual_end__ = .; + . = _Privileged_Functions_Region_Size; + } > ROM + + + + .text : + { + . = ALIGN(4); + + + /* + * This section is here for convenience, to store the + * startup code at the beginning of the flash area, hoping that + * this will increase the readability of the listing. + */ + KEEP(*(.after_vectors .after_vectors.*)) /* Startup code and ISR */ + + . = ALIGN(4); + + /* + * These are the old initialisation sections, intended to contain + * naked code, with the prologue/epilogue added by crti.o/crtn.o + * when linking with startup files. The standalone startup code + * currently does not run these, better use the init arrays below. + */ + KEEP(*(.init)) + KEEP(*(.fini)) + + . = ALIGN(4); + + /* + * The preinit code, i.e. an array of pointers to initialisation + * functions to be performed before constructors. + */ + PROVIDE_HIDDEN (__preinit_array_start = .); + + /* + * Used to run the SystemInit() before anything else. + */ + KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*)) + + /* + * Used for other platform inits. + */ + KEEP(*(.preinit_array_platform .preinit_array_platform.*)) + + /* + * The application inits. If you need to enforce some order in + * execution, create new sections, as before. + */ + KEEP(*(.preinit_array .preinit_array.*)) + + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + + /* + * The init code, i.e. an array of pointers to static constructors. + */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + + /* + * The fini code, i.e. an array of pointers to static destructors. + */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + + . = ALIGN(4); + + *(.text*) /* all remaining code */ + + *(vtable) /* C++ virtual tables */ + + } >ROM + + .rodata : + { + *(.rodata*) /* read-only data (constants) */ + } >ROM + + .glue : + { + KEEP(*(.eh_frame*)) + + /* + * Stub sections generated by the linker, to glue together + * ARM and Thumb code. .glue_7 is used for ARM code calling + * Thumb code, and .glue_7t is used for Thumb code calling + * ARM code. Apparently always generated by the linker, for some + * architectures, so better leave them here. + */ + *(.glue_7) + *(.glue_7t) + } >ROM + + /* ARM magic sections */ + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM + __exidx_end = .; + + . = ALIGN(4); + _etext = .; + __etext = .; + + /* + * This address is used by the startup code to + * initialise the .data section. + */ + _sidata = _etext; + + /* MEMORY_ARRAY */ + /* + .ROarraySection : + { + *(.ROarraySection .ROarraySection.*) + } >MEMORY_ARRAY + */ + + + privileged_data : + { + *(privileged_data) + /* Non kernel data is kept out of the first _Privileged_Data_Region_Size + bytes of SRAM. */ + __privileged_data_actual_end__ = .; + . = _Privileged_Data_Region_Size; + } > RAM + + /* + * The initialised data section. + * The program executes knowing that the data is in the RAM + * but the loader puts the initial values in the ROM (inidata). + * It is one task of the startup to copy the initial values from + * ROM to RAM. + */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + + /* This is used by the startup code to initialise the .data section */ + _sdata = . ; /* STM specific definition */ + __data_start__ = . ; + *(.data_begin .data_begin.*) + + *(.data .data.*) + + *(.data_end .data_end.*) + . = ALIGN(4); + + /* This is used by the startup code to initialise the .data section */ + _edata = . ; /* STM specific definition */ + __data_end__ = . ; + + } >RAM + + + /* + * The uninitialised data section. NOLOAD is used to avoid + * the "section `.bss' type changed to PROGBITS" warning + */ + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start__ = .; /* standard newlib definition */ + _sbss = .; /* STM specific definition */ + *(.bss_begin .bss_begin.*) + + *(.bss .bss.*) + *(COMMON) + + *(.bss_end .bss_end.*) + . = ALIGN(4); + __bss_end__ = .; /* standard newlib definition */ + _ebss = . ; /* STM specific definition */ + } >RAM + + .noinit (NOLOAD) : + { + . = ALIGN(4); + _noinit = .; + + *(.noinit .noinit.*) + + . = ALIGN(4) ; + _end_noinit = .; + } > RAM + + /* Mandatory to be word aligned, _sbrk assumes this */ + PROVIDE ( end = _end_noinit ); /* was _ebss */ + PROVIDE ( _end = _end_noinit ); + PROVIDE ( __end = _end_noinit ); + PROVIDE ( __end__ = _end_noinit ); + PROVIDE ( ROM_DATA_START = __data_start__ ); + + /* + * Used for validation only, do not allocate anything here! + * + * This is just to check that there is enough RAM left for the Main + * stack. It should generate an error if it's full. + */ + ._check_stack : + { + . = ALIGN(4); + + . = . + _Minimum_Stack_Size ; + + . = ALIGN(4); + } >RAM + + /* After that there are only debugging sections. */ + + /* This can remove the debugging information from the standard libraries */ + /* + DISCARD : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* + * DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. + */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S new file mode 100644 index 000000000..fb2af495a --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/GCC_Specific/startup_ARMCM4.S @@ -0,0 +1,217 @@ +/* File: startup_ARMCM4.S + * Purpose: startup file for Cortex-M4 devices. Should use with + * GCC for ARM Embedded Processors + * Version: V2.0 + * Date: 16 August 2013 + * +/* Copyright (c) 2011 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + .syntax unified + .arch armv7e-m + + .extern __SRAM_segment_end__ + + .section .isr_vector + .align 4 + .globl __isr_vector +__isr_vector: + .long __SRAM_segment_end__ - 4 /* Top of Stack at top of RAM*/ + .long Reset_Handler /* Reset Handler */ + .long NMI_Handler /* NMI Handler */ + .long HardFault_Handler /* Hard Fault Handler */ + .long MemManage_Handler /* MPU Fault Handler */ + .long BusFault_Handler /* Bus Fault Handler */ + .long UsageFault_Handler /* Usage Fault Handler */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long 0 /* Reserved */ + .long SVC_Handler /* SVCall Handler */ + .long DebugMon_Handler /* Debug Monitor Handler */ + .long 0 /* Reserved */ + .long PendSV_Handler /* PendSV Handler */ + .long SysTick_Handler /* SysTick Handler */ + + /* External interrupts */ + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + .long DummyHandler + + + .text + .thumb + .thumb_func + .align 2 + .globl _start + .extern main + .globl Reset_Handler + .type Reset_Handler, %function +_start: +Reset_Handler: +/* Firstly it copies data from read only memory to RAM. There are two schemes + * to copy. One can copy more than one sections. Another can only copy + * one section. The former scheme needs more instructions and read-only + * data to implement than the latter. + * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ + +/* Single section scheme. + * + * The ranges of copy from/to are specified by following symbols + * __etext: LMA of start of the section to copy from. Usually end of text + * __data_start__: VMA of start of the section to copy to + * __data_end__: VMA of end of the section to copy to + * + * All addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__etext + ldr r2, =__data_start__ + ldr r3, =__data_end__ + +.L_loop1: + cmp r2, r3 + ittt lt + ldrlt r0, [r1], #4 + strlt r0, [r2], #4 + blt .L_loop1 + +/* This part of work usually is done in C library startup code. Otherwise, + * define this macro to enable it in this startup. + * + * There are two schemes too. One can clear multiple BSS sections. Another + * can only clear one section. The former is more size expensive than the + * latter. + * + * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. + * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. + */ + + /* Single BSS section scheme. + * + * The BSS section is specified by following symbols + * __bss_start__: start of the BSS section. + * __bss_end__: end of the BSS section. + * + * Both addresses must be aligned to 4 bytes boundary. + */ + ldr r1, =__bss_start__ + ldr r2, =__bss_end__ + + movs r0, 0 +.L_loop3: + cmp r1, r2 + itt lt + strlt r0, [r1], #4 + blt .L_loop3 + +#ifndef __NO_SYSTEM_INIT +/* bl SystemInit */ +#endif + + bl main + + .pool + .size Reset_Handler, . - Reset_Handler + + .align 1 + .thumb_func + .weak Default_Handler + .type Default_Handler, %function +Default_Handler: + b . + .size Default_Handler, . - Default_Handler + +/* Macro to define default handlers. Default handler + * will be weak symbol and just dead loops. They can be + * overwritten by other handlers */ + .macro def_irq_handler handler_name + .weak \handler_name + .set \handler_name, Default_Handler + .endm + + def_irq_handler NMI_Handler + def_irq_handler HardFault_Handler + def_irq_handler MemManage_Handler + def_irq_handler BusFault_Handler + def_irq_handler UsageFault_Handler + def_irq_handler SVC_Handler + def_irq_handler DebugMon_Handler + def_irq_handler PendSV_Handler + def_irq_handler SysTick_Handler + def_irq_handler DEF_IRQHandler + def_irq_handler DummyHandler + + + .end diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct new file mode 100644 index 000000000..ee30fbd50 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.sct @@ -0,0 +1,23 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + + +LR_IROM1 0x00000000 { ; load region size_region + ER_IROM1 0x00000000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + *( privileged_functions ) + } + ER_IROM2 0x8000 FIXED { + .ANY (+RO) + } + RW_IRAM1 0x20000000 { ; RW data + *( privileged_data ) + } + RW_IRAM2 0x20000800 { ; RW data + .ANY (+RW +ZI) + } +} + + diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx new file mode 100644 index 000000000..58cf95293 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvoptx @@ -0,0 +1,358 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + RTOSDemo + 0x4 + ARM-ADS + + 48000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\Listings\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 7 + + 1 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + + + BIN\UL2CM3.DLL + + + + 0 + DLGDARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=1231,224,1641,767,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=1199,245,1664,545,0) + + + 0 + ARMDBGFLAGS + -T0 + + + 0 + UL2CM3 + -UV1115SAE -O3047 -S0 -C0 -P00 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO19 -TC48000000 -TP21 -TDS8028 -TDT0 -TDC1F -TIE1 -TIP8 -FO11 -FD118000 -FC8000 -FN1 -FF0NEW_DEVICE.FLM -FS0E0000 -FL038000 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM) + + + + + + 0 + 1 + ulCycleCount + + + + + 1 + 2 + 0xe000e284 + 4 + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + + + 0 + + + + + System + 1 + 0 + 0 + 0 + + 1 + 1 + 2 + 0 + 0 + 0 + .\startup_MPS_CM4.S + startup_MPS_CM4.S + 0 + 0 + + + + + main_and_config + 1 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\main.c + main.c + 0 + 0 + + + 2 + 3 + 5 + 0 + 0 + 0 + ..\FreeRTOSConfig.h + FreeRTOSConfig.h + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + .\RegTest.c + RegTest.c + 0 + 0 + + + + + FreeRTOS_Source + 1 + 0 + 0 + 0 + + 3 + 5 + 1 + 0 + 0 + 0 + ..\..\..\Source\event_groups.c + event_groups.c + 0 + 0 + + + 3 + 6 + 1 + 0 + 0 + 0 + ..\..\..\Source\list.c + list.c + 0 + 0 + + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\Source\queue.c + queue.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\Source\tasks.c + tasks.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\Source\timers.c + timers.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\Source\portable\RVDS\ARM_CM4_MPU\port.c + port.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\Source\portable\Common\mpu_wrappers.c + mpu_wrappers.c + 0 + 0 + + + +
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx new file mode 100644 index 000000000..3a254da24 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RTOSDemo.uvprojx @@ -0,0 +1,451 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + RTOSDemo + 0x4 + ARM-ADS + 5060183::V5.06 update 2 (build 183)::ARMCC + + + ARMCM4_FP + ARM + ARM.CMSIS.5.0.0-Beta4 + http://www.keil.com/pack/ + IROM(0x00000000,0x80000) IRAM(0x20000000,0x20000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ESEL ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0NEW_DEVICE -FS00 -FL080000 -FP0($$Device:ARMCM4_FP$Device\ARM\Flash\NEW_DEVICE.FLM)) + 0 + $$Device:ARMCM4_FP$Device\ARM\ARMCM4\Include\ARMCM4_FP.h + + + + + + + + + + $$Device:ARMCM4_FP$Device\ARM\SVD\ARMCM4.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + RTOSDemo + 1 + 0 + 1 + 1 + 1 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 8 + 1 + 1 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x0 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x80000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x8000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + ..;..\..\..\Source\include;..\..\..\Source\portable\RVDS\ARM_CM4_MPU;..\..\Common\include;..\CMSIS;..\main_full + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x20000000 + + RTOSDemo.sct + + + + + + + + + + + System + + + startup_MPS_CM4.S + 2 + .\startup_MPS_CM4.S + + + + + main_and_config + + + main.c + 1 + ..\main.c + + + FreeRTOSConfig.h + 5 + ..\FreeRTOSConfig.h + + + RegTest.c + 1 + .\RegTest.c + + + + + FreeRTOS_Source + + + event_groups.c + 1 + ..\..\..\Source\event_groups.c + + + list.c + 1 + ..\..\..\Source\list.c + + + queue.c + 1 + ..\..\..\Source\queue.c + + + tasks.c + 1 + ..\..\..\Source\tasks.c + + + timers.c + 1 + ..\..\..\Source\timers.c + + + port.c + 1 + ..\..\..\Source\portable\RVDS\ARM_CM4_MPU\port.c + + + mpu_wrappers.c + 1 + ..\..\..\Source\portable\Common\mpu_wrappers.c + + + + + + + +
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c new file mode 100644 index 000000000..90e1625c5 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/RegTest.c @@ -0,0 +1,703 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" +#include "task.h" + +/* + * "Reg test" tasks - These fill the registers with known values, then check + * that each register maintains its expected value for the lifetime of the + * task. Each task uses a different set of values. The reg test tasks execute + * with a very low priority, so get preempted very frequently. A register + * containing an unexpected value is indicative of an error in the context + * switching mechanism. + */ + +void vRegTest1Implementation( void *pvParameters ); +void vRegTest2Implementation( void *pvParameters ); +void vRegTest3Implementation( void ); +void vRegTest4Implementation( void ); + +/* + * Used as an easy way of deleting a task from inline assembly. + */ +extern void vMainDeleteMe( void ) __attribute__((noinline)); + +/* + * Used by the first two reg test tasks and a software timer callback function + * to send messages to the check task. The message just lets the check task + * know that the tasks and timer are 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. + */ +extern void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber ); + +/* The queue used to send a message to the check task. */ +extern QueueHandle_t xGlobalScopeCheckQueue; + +/*-----------------------------------------------------------*/ + +void vRegTest1Implementation( 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 this task is in user mode the file scope queue variable will no +longer be accessible but the stack copy will. */ +QueueHandle_t xQueue = xGlobalScopeCheckQueue; +const TickType_t xDelayTime = pdMS_TO_TICKS( 100UL ); + + /* Now the queue handle has been obtained the task can switch to user + mode. This is just one method of passing a handle into a protected + task, the other reg test task uses the task parameter instead. */ + portSWITCH_TO_USER_MODE(); + + /* First check that the parameter value is as expected. */ + if( pvParameters != ( void * ) configREG_TEST_TASK_1_PARAMETER ) + { + /* Error detected. Delete the task so it stops communicating with + the check task. */ + vMainDeleteMe(); + } + + for( ;; ) + { + #if defined ( __GNUC__ ) + { + /* This task tests the kernel context switch mechanism by reading and + writing directly to registers - which requires the test to be written + in assembly code. */ + __asm volatile + ( + " MOV R4, #104 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */ + " MOV R5, #105 \n" + " MOV R6, #106 \n" + " MOV R8, #108 \n" + " MOV R9, #109 \n" + " MOV R10, #110 \n" + " MOV R11, #111 \n" + "reg1loop: \n" + " MOV R0, #100 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */ + " MOV R1, #101 \n" + " MOV R2, #102 \n" + " MOV R3, #103 \n" + " MOV R12, #112 \n" + " SVC #1 \n" /* Yield just to increase test coverage. */ + " CMP R0, #100 \n" /* Check all the registers still contain their expected values. */ + " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */ + " CMP R1, #101 \n" + " BNE vMainDeleteMe \n" + " CMP R2, #102 \n" + " BNE vMainDeleteMe \n" + " CMP R3, #103 \n" + " BNE vMainDeleteMe \n" + " CMP R4, #104 \n" + " BNE vMainDeleteMe \n" + " CMP R5, #105 \n" + " BNE vMainDeleteMe \n" + " CMP R6, #106 \n" + " BNE vMainDeleteMe \n" + " CMP R8, #108 \n" + " BNE vMainDeleteMe \n" + " CMP R9, #109 \n" + " BNE vMainDeleteMe \n" + " CMP R10, #110 \n" + " BNE vMainDeleteMe \n" + " CMP R11, #111 \n" + " BNE vMainDeleteMe \n" + " CMP R12, #112 \n" + " BNE vMainDeleteMe \n" + :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); + } + #endif /* __GNUC__ */ + + /* Send configREG_TEST_1_STILL_EXECUTING to the check task to indicate that this + task is still functioning. */ + vMainSendImAlive( xQueue, configREG_TEST_1_STILL_EXECUTING ); + vTaskDelay( xDelayTime ); + + #if defined ( __GNUC__ ) + { + /* Go back to check all the register values again. */ + __asm volatile( " B reg1loop " ); + } + #endif /* __GNUC__ */ + } +} +/*-----------------------------------------------------------*/ + +void vRegTest2Implementation( 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 reg test task uses a different +method. */ +QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters; +const TickType_t xDelayTime = pdMS_TO_TICKS( 100UL ); + + for( ;; ) + { + #if defined ( __GNUC__ ) + { + /* This task tests the kernel context switch mechanism by reading and + writing directly to registers - which requires the test to be written + in assembly code. */ + __asm volatile + ( + " MOV R4, #4 \n" /* Set registers to a known value. R0 to R1 are done in the loop below. */ + " MOV R5, #5 \n" + " MOV R6, #6 \n" + " MOV R8, #8 \n" /* Frame pointer is omitted as it must not be changed. */ + " MOV R9, #9 \n" + " MOV R10, 10 \n" + " MOV R11, #11 \n" + "reg2loop: \n" + " MOV R0, #13 \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */ + " MOV R1, #1 \n" + " MOV R2, #2 \n" + " MOV R3, #3 \n" + " MOV R12, #12 \n" + " CMP R0, #13 \n" /* Check all the registers still contain their expected values. */ + " BNE vMainDeleteMe \n" /* Value was not as expected, delete the task so it stops communicating with the check task */ + " CMP R1, #1 \n" + " BNE vMainDeleteMe \n" + " CMP R2, #2 \n" + " BNE vMainDeleteMe \n" + " CMP R3, #3 \n" + " BNE vMainDeleteMe \n" + " CMP R4, #4 \n" + " BNE vMainDeleteMe \n" + " CMP R5, #5 \n" + " BNE vMainDeleteMe \n" + " CMP R6, #6 \n" + " BNE vMainDeleteMe \n" + " CMP R8, #8 \n" + " BNE vMainDeleteMe \n" + " CMP R9, #9 \n" + " BNE vMainDeleteMe \n" + " CMP R10, #10 \n" + " BNE vMainDeleteMe \n" + " CMP R11, #11 \n" + " BNE vMainDeleteMe \n" + " CMP R12, #12 \n" + " BNE vMainDeleteMe \n" + :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12" + ); + } + #endif /* __GNUC__ */ + + /* Send configREG_TEST_2_STILL_EXECUTING to the check task to indicate + that this task is still functioning. */ + vMainSendImAlive( xQueue, configREG_TEST_2_STILL_EXECUTING ); + vTaskDelay( xDelayTime ); + + #if defined ( __GNUC__ ) + { + /* Go back to check all the register values again. */ + __asm volatile( " B reg2loop " ); + } + #endif /* __GNUC__ */ + } +} +/*-----------------------------------------------------------*/ + +__asm void vRegTest3Implementation( void ) +{ + extern pulRegTest3LoopCounter + + PRESERVE8 + + /* Fill the core registers with known values. */ + mov r0, #100 + mov r1, #101 + mov r2, #102 + mov r3, #103 + mov r4, #104 + mov r5, #105 + mov r6, #106 + mov r7, #107 + mov r8, #108 + mov r9, #109 + mov r10, #110 + mov r11, #111 + mov r12, #112 + + /* Fill the VFP registers with known values. */ + vmov d0, r0, r1 + vmov d1, r2, r3 + vmov d2, r4, r5 + vmov d3, r6, r7 + vmov d4, r8, r9 + vmov d5, r10, r11 + vmov d6, r0, r1 + vmov d7, r2, r3 + vmov d8, r4, r5 + vmov d9, r6, r7 + vmov d10, r8, r9 + vmov d11, r10, r11 + vmov d12, r0, r1 + vmov d13, r2, r3 + vmov d14, r4, r5 + vmov d15, r6, r7 + +reg1_loop + + /* Check all the VFP registers still contain the values set above. + First save registers that are clobbered by the test. */ + push { r0-r1 } + + vmov r0, r1, d0 + cmp r0, #100 + bne reg1_error_loopf + cmp r1, #101 + bne reg1_error_loopf + vmov r0, r1, d1 + cmp r0, #102 + bne reg1_error_loopf + cmp r1, #103 + bne reg1_error_loopf + vmov r0, r1, d2 + cmp r0, #104 + bne reg1_error_loopf + cmp r1, #105 + bne reg1_error_loopf + vmov r0, r1, d3 + cmp r0, #106 + bne reg1_error_loopf + cmp r1, #107 + bne reg1_error_loopf + vmov r0, r1, d4 + cmp r0, #108 + bne reg1_error_loopf + cmp r1, #109 + bne reg1_error_loopf + vmov r0, r1, d5 + cmp r0, #110 + bne reg1_error_loopf + cmp r1, #111 + bne reg1_error_loopf + vmov r0, r1, d6 + cmp r0, #100 + bne reg1_error_loopf + cmp r1, #101 + bne reg1_error_loopf + vmov r0, r1, d7 + cmp r0, #102 + bne reg1_error_loopf + cmp r1, #103 + bne reg1_error_loopf + vmov r0, r1, d8 + cmp r0, #104 + bne reg1_error_loopf + cmp r1, #105 + bne reg1_error_loopf + vmov r0, r1, d9 + cmp r0, #106 + bne reg1_error_loopf + cmp r1, #107 + bne reg1_error_loopf + vmov r0, r1, d10 + cmp r0, #108 + bne reg1_error_loopf + cmp r1, #109 + bne reg1_error_loopf + vmov r0, r1, d11 + cmp r0, #110 + bne reg1_error_loopf + cmp r1, #111 + bne reg1_error_loopf + vmov r0, r1, d12 + cmp r0, #100 + bne reg1_error_loopf + cmp r1, #101 + bne reg1_error_loopf + vmov r0, r1, d13 + cmp r0, #102 + bne reg1_error_loopf + cmp r1, #103 + bne reg1_error_loopf + vmov r0, r1, d14 + cmp r0, #104 + bne reg1_error_loopf + cmp r1, #105 + bne reg1_error_loopf + vmov r0, r1, d15 + cmp r0, #106 + bne reg1_error_loopf + cmp r1, #107 + bne reg1_error_loopf + + /* Restore the registers that were clobbered by the test. */ + pop {r0-r1} + + /* VFP register test passed. Jump to the core register test. */ + b reg1_loopf_pass + +reg1_error_loopf + /* If this line is hit then a VFP register value was found to be incorrect. */ + b reg1_error_loopf + +reg1_loopf_pass + + cmp r0, #100 + bne reg1_error_loop + cmp r1, #101 + bne reg1_error_loop + cmp r2, #102 + bne reg1_error_loop + cmp r3, #103 + bne reg1_error_loop + cmp r4, #104 + bne reg1_error_loop + cmp r5, #105 + bne reg1_error_loop + cmp r6, #106 + bne reg1_error_loop + cmp r7, #107 + bne reg1_error_loop + cmp r8, #108 + bne reg1_error_loop + cmp r9, #109 + bne reg1_error_loop + cmp r10, #110 + bne reg1_error_loop + cmp r11, #111 + bne reg1_error_loop + cmp r12, #112 + bne reg1_error_loop + + /* Everything passed, increment the loop counter. */ + push { r0-r1 } + ldr r0, =pulRegTest3LoopCounter + ldr r0, [r0] + ldr r1, [r0] + adds r1, r1, #1 + str r1, [r0] + pop { r0-r1 } + + /* Start again. */ + b reg1_loop + +reg1_error_loop + /* If this line is hit then there was an error in a core register value. + The loop ensures the loop counter stops incrementing. */ + b reg1_error_loop + nop + nop +} +/*-----------------------------------------------------------*/ + +__asm void vRegTest4Implementation( void ) +{ + extern pulRegTest4LoopCounter; + + PRESERVE8 + + /* Set all the core registers to known values. */ + mov r0, #-1 + mov r1, #1 + mov r2, #2 + mov r3, #3 + mov r4, #4 + mov r5, #5 + mov r6, #6 + mov r7, #7 + mov r8, #8 + mov r9, #9 + mov r10, #10 + mov r11, #11 + mov r12, #12 + + /* Set all the VFP to known values. */ + vmov d0, r0, r1 + vmov d1, r2, r3 + vmov d2, r4, r5 + vmov d3, r6, r7 + vmov d4, r8, r9 + vmov d5, r10, r11 + vmov d6, r0, r1 + vmov d7, r2, r3 + vmov d8, r4, r5 + vmov d9, r6, r7 + vmov d10, r8, r9 + vmov d11, r10, r11 + vmov d12, r0, r1 + vmov d13, r2, r3 + vmov d14, r4, r5 + vmov d15, r6, r7 + +reg2_loop + + /* Check all the VFP registers still contain the values set above. + First save registers that are clobbered by the test. */ + push { r0-r1 } + + vmov r0, r1, d0 + cmp r0, #-1 + bne reg2_error_loopf + cmp r1, #1 + bne reg2_error_loopf + vmov r0, r1, d1 + cmp r0, #2 + bne reg2_error_loopf + cmp r1, #3 + bne reg2_error_loopf + vmov r0, r1, d2 + cmp r0, #4 + bne reg2_error_loopf + cmp r1, #5 + bne reg2_error_loopf + vmov r0, r1, d3 + cmp r0, #6 + bne reg2_error_loopf + cmp r1, #7 + bne reg2_error_loopf + vmov r0, r1, d4 + cmp r0, #8 + bne reg2_error_loopf + cmp r1, #9 + bne reg2_error_loopf + vmov r0, r1, d5 + cmp r0, #10 + bne reg2_error_loopf + cmp r1, #11 + bne reg2_error_loopf + vmov r0, r1, d6 + cmp r0, #-1 + bne reg2_error_loopf + cmp r1, #1 + bne reg2_error_loopf + vmov r0, r1, d7 + cmp r0, #2 + bne reg2_error_loopf + cmp r1, #3 + bne reg2_error_loopf + vmov r0, r1, d8 + cmp r0, #4 + bne reg2_error_loopf + cmp r1, #5 + bne reg2_error_loopf + vmov r0, r1, d9 + cmp r0, #6 + bne reg2_error_loopf + cmp r1, #7 + bne reg2_error_loopf + vmov r0, r1, d10 + cmp r0, #8 + bne reg2_error_loopf + cmp r1, #9 + bne reg2_error_loopf + vmov r0, r1, d11 + cmp r0, #10 + bne reg2_error_loopf + cmp r1, #11 + bne reg2_error_loopf + vmov r0, r1, d12 + cmp r0, #-1 + bne reg2_error_loopf + cmp r1, #1 + bne reg2_error_loopf + vmov r0, r1, d13 + cmp r0, #2 + bne reg2_error_loopf + cmp r1, #3 + bne reg2_error_loopf + vmov r0, r1, d14 + cmp r0, #4 + bne reg2_error_loopf + cmp r1, #5 + bne reg2_error_loopf + vmov r0, r1, d15 + cmp r0, #6 + bne reg2_error_loopf + cmp r1, #7 + bne reg2_error_loopf + + /* Restore the registers that were clobbered by the test. */ + pop {r0-r1} + + /* VFP register test passed. Jump to the core register test. */ + b reg2_loopf_pass + +reg2_error_loopf + /* If this line is hit then a VFP register value was found to be + incorrect. */ + b reg2_error_loopf + +reg2_loopf_pass + + cmp r0, #-1 + bne reg2_error_loop + cmp r1, #1 + bne reg2_error_loop + cmp r2, #2 + bne reg2_error_loop + cmp r3, #3 + bne reg2_error_loop + cmp r4, #4 + bne reg2_error_loop + cmp r5, #5 + bne reg2_error_loop + cmp r6, #6 + bne reg2_error_loop + cmp r7, #7 + bne reg2_error_loop + cmp r8, #8 + bne reg2_error_loop + cmp r9, #9 + bne reg2_error_loop + cmp r10, #10 + bne reg2_error_loop + cmp r11, #11 + bne reg2_error_loop + cmp r12, #12 + bne reg2_error_loop + + /* Increment the loop counter so the check task knows this task is + still running. */ + push { r0-r1 } + ldr r0, =pulRegTest4LoopCounter + ldr r0, [r0] + ldr r1, [r0] + adds r1, r1, #1 + str r1, [r0] + pop { r0-r1 } + + /* Yield to increase test coverage. */ + SVC #1 + + /* Start again. */ + b reg2_loop + +reg2_error_loop + /* If this line is hit then there was an error in a core register value. + This loop ensures the loop counter variable stops incrementing. */ + b reg2_error_loop + nop +} +/*-----------------------------------------------------------*/ + +/* Fault handlers are here for convenience as they use compiler specific syntax +and this file is specific to the Keil compiler. */ +void hard_fault_handler( uint32_t * hardfault_args ) +{ +volatile uint32_t stacked_r0; +volatile uint32_t stacked_r1; +volatile uint32_t stacked_r2; +volatile uint32_t stacked_r3; +volatile uint32_t stacked_r12; +volatile uint32_t stacked_lr; +volatile uint32_t stacked_pc; +volatile uint32_t stacked_psr; + + stacked_r0 = ((uint32_t) hardfault_args[ 0 ]); + stacked_r1 = ((uint32_t) hardfault_args[ 1 ]); + stacked_r2 = ((uint32_t) hardfault_args[ 2 ]); + stacked_r3 = ((uint32_t) hardfault_args[ 3 ]); + + stacked_r12 = ((uint32_t) hardfault_args[ 4 ]); + stacked_lr = ((uint32_t) hardfault_args[ 5 ]); + stacked_pc = ((uint32_t) hardfault_args[ 6 ]); + stacked_psr = ((uint32_t) hardfault_args[ 7 ]); + + /* Inspect stacked_pc to locate the offending instruction. */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void HardFault_Handler( void ); +__asm void HardFault_Handler( void ) +{ + extern hard_fault_handler + + tst lr, #4 + ite eq + mrseq r0, msp + mrsne r0, psp + ldr r1, [r0, #24] + ldr r2, hard_fault_handler + bx r2 +} +/*-----------------------------------------------------------*/ + +void MemManage_Handler( void ); +__asm void MemManage_Handler( void ) +{ + extern hard_fault_handler + + tst lr, #4 + ite eq + mrseq r0, msp + mrsne r0, psp + ldr r1, [r0, #24] + ldr r2, hard_fault_handler + bx r2 +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S new file mode 100644 index 000000000..8534aa2b1 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/Keil_Specific/startup_MPS_CM4.S @@ -0,0 +1,172 @@ +;/***************************************************************************** +; * @file: startup_MPS_CM4.s +; * @purpose: CMSIS Cortex-M4 Core Device Startup File +; * for the ARM 'Microcontroller Prototyping System' +; * @version: V1.00 +; * @date: 1. Jun. 2010 +; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +; * +; * Copyright (C) 2008-2010 ARM Limited. All rights reserved. +; * ARM Limited (ARM) is supplying this software for use with Cortex-M4 +; * processor based microcontrollers. This file can be freely distributed +; * within development tools that are supporting such ARM based processors. +; * +; * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR +; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. +; * +; ****************************************************************************/ + + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; +Stack_Size EQU 0x00000800 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000000 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + + AREA RESET, DATA, READONLY + EXPORT __Vectors + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + + AREA |.text|, CODE, READONLY +; AREA RESET, CODE, READONLY + +; Reset Handler + +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT __main + + ; Remap vector table + LDR R0, =__Vectors + LDR R1, =0xE000ED08 + STR R0, [r1] + NOP + + IF {CPU} = "Cortex-M4.fp" + LDR R0, =0xE000ED88 ; Enable CP10,CP11 + LDR R1,[R0] + ORR R1,R1,#(0xF << 20) + STR R1,[R0] + ENDIF + + LDR R0, =__main + BX R0 + ENDP + + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + + + ALIGN + + +; User Initial Stack & Heap + + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + + END diff --git a/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c new file mode 100644 index 000000000..cbaaabafa --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_MPU_Static_Simulator_Keil_GCC/main.c @@ -0,0 +1,1196 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * This file demonstrates the use of FreeRTOS-MPU in a completely statically + * allocated application (with configSUPPORT_DYNAMIC_ALLOCATION set to 0). It + * creates tasks in both User mode and Privileged mode, and using both the + * xTaskCreateStatic() and xTaskCreateRestrictedStatic() 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. A software timer is also used. + */ + +/* Standard includes. */ +#include "string.h" + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" +#include "timers.h" +#include "event_groups.h" + +/*-----------------------------------------------------------*/ + +/* Misc constants. */ +#define mainDONT_BLOCK ( 0 ) + +/* GCC specifics. */ +#define mainALIGN_TO( x ) __attribute__((aligned(x))) + +/* Hardware register addresses. */ +#define mainVTOR ( * ( volatile uint32_t * ) 0xE000ED08 ) + +/* The period of the timer must be less than the rate at which +configPRINT_SYSTEM_STATUS messages are sent to the check task - otherwise the +check task will think the timer has stopped. */ +#define mainTIMER_PERIOD pdMS_TO_TICKS( 200 ) + +/* The name of the task that is deleted by the Idle task is used in a couple of +places, so is #defined. */ +#define mainTASK_TO_DELETE_NAME "DeleteMe" + +/*-----------------------------------------------------------*/ +/* Prototypes for functions that implement tasks. -----------*/ +/*-----------------------------------------------------------*/ + +/* + * NOTE: The filling and checking of the registers in the following two tasks + * is only actually performed when the GCC compiler is used. Use of the + * queue to communicate with the check task is done with all compilers. + * + * Prototype for the first two register test tasks, which execute in User mode. + * Amongst other things, these fill the CPU registers (other than the FPU + * 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 tasks execute at the + * idle priority so will get preempted regularly. Each task repeatedly sends a + * message on a queue to a 'check' task so the check task knows the register + * check task is still executing and has not detected any errors. If an error + * is detected within the task the task is simply deleted so it no longer sends + * messages. + * + * For demonstration and test purposes, both tasks obtain access to the queue + * handle in different ways; vRegTest1Implementation() is created in Privileged + * mode and copies the queue handle to its local stack before setting itself to + * User mode, and vRegTest2Implementation() receives the task handle using its + * parameter. + */ +extern void vRegTest1Implementation( void *pvParameters ); +extern void vRegTest2Implementation( void *pvParameters ); + +/* + * The second two register test tasks are similar to the first two, but do test + * the floating point registers, execute in Privileged mode, and signal their + * execution status to the 'check' task by incrementing a loop counter on each + * iteration instead of sending a message on a queue. The loop counters use a + * memory region to which the User mode 'check' task has read access. + * + * The functions ending 'Implementation' are called by the register check tasks. + * + * The tasks are created with xTaskCreateStatic(), so the stack and variables + * used to hold the task's data structures also have to be provided. + */ +static StackType_t xRegTest3Stack[ configMINIMAL_STACK_SIZE ], xRegTest4Stack[ configMINIMAL_STACK_SIZE ]; +static StaticTask_t xRegTest3Buffer, xRegTest4Buffer; +static void prvRegTest3Task( void *pvParameters ); +extern void vRegTest3Implementation( void ); +static void prvRegTest4Task( void *pvParameters ); +extern void vRegTest4Implementation( void ); + +/* + * Prototype for the check task. The check task demonstrates various features + * of the MPU before entering a loop where it waits for messages to arrive on a + * queue. + * + * Two types of messages can be processes: + * + * 1) "I'm Alive" messages sent from the first two register test tasks and a + * software timer callback, as described above. + * + * 2) "Print Status commands" sent periodically by the tick hook function (and + * therefore from within an interrupt) which commands the check task to write + * either pass or fail to the terminal, depending on the status of the reg + * test tasks (no write is performed in the simulator!). + */ +static void prvCheckTask( void *pvParameters ); + +/* + * Prototype for a task created in User mode using vTaskCreateStatic() API + * function. The task demonstrates the characteristics of such a task, + * before simply deleting itself. As the task is created without using any + * dynamic memory allocate the stack and variable in which the task's data + * structure will be stored must also be provided - however the task is + * unprivileged so the stack cannot be in a privileged section. + */ +static StackType_t xUserModeTaskStack[ configMINIMAL_STACK_SIZE ]; +static PRIVILEGED_DATA StaticTask_t xUserModeTaskBuffer; +static void prvOldStyleUserModeTask( void *pvParameters ); + +/* + * Prototype for a task created in Privileged mode using the + * xTaskCreateStatic() API function. The task demonstrates the characteristics + * of such a task, before simply deleting itself. As no dynamic memory + * allocation is used the stack and variable used to hold the task's data + * structure must also be provided. The task is privileged, so the stack can + * be in a privileged section. + */ +static PRIVILEGED_DATA StackType_t xPrivilegedModeTaskStack[ configMINIMAL_STACK_SIZE ]; +static PRIVILEGED_DATA StaticTask_t xPrivilegedModeTaskBuffer; +static void prvOldStylePrivilegedModeTask( void *pvParameters ); + +/* + * A task that exercises the API of various RTOS objects before being deleted by + * the Idle task. This is done for MPU API code coverage test purposes. + */ +static void prvTaskToDelete( void *pvParameters ); + +/* + * Functions called by prvTaskToDelete() to exercise the MPU API. + */ +static void prvExerciseEventGroupAPI( void ); +static void prvExerciseSemaphoreAPI( void ); +static void prvExerciseTaskNotificationAPI( void ); + +/* + * Just configures any clocks and IO necessary. + */ +static void prvSetupHardware( void ); + +/* + * Simply deletes the calling task. The function is provided only because it + * is simpler to call from asm code than the normal vTaskDelete() API function. + * It has the noinline attribute because it is called from asm code. + */ +void vMainDeleteMe( void ) __attribute__((noinline)); + +/* + * Used by the first two reg test tasks and a software timer callback function + * to send messages to the check task. The message just lets the check task + * know that the tasks and timer are 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. + */ +void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber ); + +/* + * The check task is created with access to three memory regions (plus its + * stack). Each memory region is configured with different parameters and + * prvTestMemoryRegions() demonstrates what can and cannot be accessed for each + * region. prvTestMemoryRegions() also demonstrates a task that was created + * as a privileged task settings its own privilege level down to that of a user + * task. + */ +static void prvTestMemoryRegions( void ); + +/* + * Callback function used with the timer that uses the queue to send messages + * to the check task. + */ +static void prvTimerCallback( TimerHandle_t xExpiredTimer ); + +/*-----------------------------------------------------------*/ + +/* The handle of the queue used to communicate between tasks and between tasks +and interrupts. Note that this is a global scope variable that falls outside of +any MPU region. As such other techniques have to be used to allow the tasks +to gain access to the queue. See the comments in the tasks themselves for +further information. */ +QueueHandle_t xGlobalScopeCheckQueue = NULL; + +/* xGlobalScopeCheckQueue is created using xQueueCreateStatic(), so the storage +area and variable used to hold the queue data structure must also be provided. +These are placed in a prviliged segment. */ +static PRIVILEGED_DATA StaticQueue_t xGlobalScopeQueueBuffer; +uint8_t PRIVILEGED_DATA ucGlobalScopeQueueStorageArea[ 1 * sizeof( uint32_t ) ]; + + +/* Holds the handle of a task that is deleted in the idle task hook - this is +done for code coverage test purposes only. */ +static TaskHandle_t xTaskToDelete = NULL; + +/* The timer that periodically sends data to the check task on the queue. This +is created with xTimerCreateStatic(), so the variable in which the timer's data +structure will be stored must also be provided. The structure is placed in the +kernel's privileged data region. */ +static TimerHandle_t xTimer = NULL; +static PRIVILEGED_DATA StaticTimer_t xTimerBuffer; + +#if defined ( __GNUC__ ) + extern uint32_t __FLASH_segment_start__[]; + extern uint32_t __FLASH_segment_end__[]; + extern uint32_t __SRAM_segment_start__[]; + extern uint32_t __SRAM_segment_end__[]; + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + extern uint32_t __privileged_data_start__[]; + extern uint32_t __privileged_data_end__[]; + extern uint32_t __privileged_functions_actual_end__[]; + extern uint32_t __privileged_data_actual_end__[]; +#else + const uint32_t * __FLASH_segment_start__ = ( uint32_t * ) 0x00UL; + const uint32_t * __FLASH_segment_end__ = ( uint32_t * ) 0x00080000UL; + const uint32_t * __SRAM_segment_start__ = ( uint32_t * ) 0x20000000UL; + const uint32_t * __SRAM_segment_end__ = ( uint32_t * ) 0x20008000UL; + const uint32_t * __privileged_functions_start__ = ( uint32_t * ) 0x00UL; + const uint32_t * __privileged_functions_end__ = ( uint32_t * ) 0x8000UL; + const uint32_t * __privileged_data_start__ = ( uint32_t * ) 0x20000000UL; + const uint32_t * __privileged_data_end__ = ( uint32_t * ) 0x20000800UL; +#endif +/*-----------------------------------------------------------*/ +/* Data used by the 'check' task. ---------------------------*/ +/*-----------------------------------------------------------*/ + +/* Define the constants used to allocate the check task stack. Note that the +stack size is defined in words, not bytes. */ +#define mainCHECK_TASK_STACK_SIZE_WORDS 128 +#define mainCHECK_TASK_STACK_ALIGNMENT ( mainCHECK_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) ) + +/* Declare the stack that will be used by the check task. The kernel will +automatically create an MPU region for the stack. The stack alignment must +match its size, so if 128 words are reserved for the stack then it must be +aligned to ( 128 * 4 ) bytes. */ +static portSTACK_TYPE xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainCHECK_TASK_STACK_ALIGNMENT ); + +/* Declare the variable in which the check task's data structures will be +stored. PRIVILEGED_DATA is used to place this in the kernel's RAM segment. */ +static PRIVILEGED_DATA StaticTask_t xCheckTaskBuffer; + +/* Declare three arrays - an MPU region will be created for each array +using the TaskParameters_t 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 ); + +#define mainREAD_ONLY_ARRAY_SIZE 260 +#define mainREAD_ONLY_ALIGN_SIZE 256 +char cReadOnlyArray[ mainREAD_ONLY_ARRAY_SIZE ] mainALIGN_TO( mainREAD_ONLY_ALIGN_SIZE ); + +#define mainPRIVILEGED_ONLY_ACCESS_ARRAY_SIZE 130 +#define mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE 128 +char cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] mainALIGN_TO( mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ); + +/* The following two variables are used to communicate the status of the second +two register check tasks (tasks 3 and 4) to the check task. If the variables +keep incrementing, then the register check tasks have not discovered any errors. +If a variable stops incrementing, then an error has been found. The variables +overlay the array that the check task has access to so they can be read by the +check task without causing a memory fault. The check task has the highest +priority so will have finished with the array before the register test tasks +start to access it. */ +volatile uint32_t *pulRegTest3LoopCounter = ( uint32_t * ) &( cReadWriteArray[ 0 ] ), *pulRegTest4LoopCounter = ( uint32_t * ) &( cReadWriteArray[ 4 ] ); + +/* Fill in a TaskParameters_t structure to define the check task - this is the +structure passed to the xTaskCreateRestricted() function. */ +static const TaskParameters_t xCheckTaskParameters = +{ + prvCheckTask, /* pvTaskCode - the function that implements the task. */ + "Check", /* pcName */ + mainCHECK_TASK_STACK_SIZE_WORDS, /* usStackDepth - defined in words, not bytes. */ + ( void * ) 0x12121212, /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */ + ( 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. */ + xCheckTaskStack, /* puxStackBuffer - the array to use as the task stack, as declared above. */ + + /* 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. 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 }, + { cReadOnlyArray, mainREAD_ONLY_ALIGN_SIZE, portMPU_REGION_READ_ONLY }, + { cPrivilegedOnlyAccessArray, mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE, portMPU_REGION_PRIVILEGED_READ_WRITE } + }, + + &xCheckTaskBuffer /* Additional structure member present when the task is being created without any dynamic memory allocation. */ +}; + + +/*-----------------------------------------------------------*/ +/* Data used by the 'reg test' tasks. -----------------------*/ +/*-----------------------------------------------------------*/ + +/* Define the constants used to allocate the reg test task stacks. Note that +that stack size is defined in words, not bytes. */ +#define mainREG_TEST_STACK_SIZE_WORDS 128 +#define mainREG_TEST_STACK_ALIGNMENT ( mainREG_TEST_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) ) + +/* Declare the stacks that will be used by the reg test tasks. The kernel will +automatically create an MPU region for the stack. The stack alignment must +match its size, so if 128 words are reserved for the stack then it must be +aligned to ( 128 * 4 ) bytes. */ +static portSTACK_TYPE xRegTest1Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT ); +static portSTACK_TYPE xRegTest2Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT ); + +/* The reg test tasks are created using the xTaskCreateRestrictedStatic() API +function, so variables that hold the task's data structures must also be +provided. The are placed in the kernel's privileged memory section. */ +static PRIVILEGED_DATA StaticTask_t xRegTest1TaskBuffer, xRegTest2TaskBuffer; + +/* Fill in a TaskParameters_t structure per reg test task to define the tasks. */ +static const TaskParameters_t xRegTest1Parameters = +{ + vRegTest1Implementation, /* pvTaskCode - the function that implements the task. */ + "RegTest1", /* pcName */ + mainREG_TEST_STACK_SIZE_WORDS, /* usStackDepth */ + ( void * ) configREG_TEST_TASK_1_PARAMETER, /* 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 hence all members are zero. */ + /* Base address Length Parameters */ + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00 } + }, + + &xRegTest1TaskBuffer /* Additional parameter required when the task is created with xTaskCreateRestrictedStatic(). */ +}; +/*-----------------------------------------------------------*/ + +static TaskParameters_t xRegTest2Parameters = +{ + vRegTest2Implementation, /* pvTaskCode - the function that implements the task. */ + "RegTest2", /* pcName */ + mainREG_TEST_STACK_SIZE_WORDS, /* usStackDepth */ + ( 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 hence all members are zero. */ + /* Base address Length Parameters */ + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00 } + }, + + &xRegTest2TaskBuffer /* Additional parameter required when the task is created with xTaskCreateRestrictedStatic(). */ +}; + +/*-----------------------------------------------------------*/ +/* Configures the task that is deleted. ---------------------*/ +/*-----------------------------------------------------------*/ + +/* Define the constants used to allocate the stack of the task that is +deleted. Note that the stack size is defined in words, not bytes. */ +#define mainDELETE_TASK_STACK_SIZE_WORDS 128 +#define mainTASK_TO_DELETE_STACK_ALIGNMENT ( mainDELETE_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) ) + +/* Declare the stack that will be used by the task that gets deleted. The +kernel will automatically create an MPU region for the stack. The stack +alignment must match its size, so if 128 words are reserved for the stack +then it must be aligned to ( 128 * 4 ) bytes. */ +static portSTACK_TYPE xDeleteTaskStack[ mainDELETE_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainTASK_TO_DELETE_STACK_ALIGNMENT ); + +/* The task that gets deleted is created using xTaskCreateRestrictedStatic(), +so the variable that stores the task's data structure must also be provided. +This is placed in the kernel's privileged data segment. */ +static PRIVILEGED_DATA StaticTask_t xStaticDeleteTaskBuffer; + +static TaskParameters_t xTaskToDeleteParameters = +{ + prvTaskToDelete, /* pvTaskCode - the function that implements the task. */ + mainTASK_TO_DELETE_NAME, /* pcName */ + mainDELETE_TASK_STACK_SIZE_WORDS, /* usStackDepth */ + ( void * ) NULL, /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */ + tskIDLE_PRIORITY + 1, /* uxPriority */ + xDeleteTaskStack, /* puxStackBuffer - the array to use as the task stack, as declared above. */ + { /* 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 }, + { 0x00, 0x00, 0x00 } + }, + + &xStaticDeleteTaskBuffer /* Additional parameter required when xTaskCreateRestrictedStatic() is used. */ +}; + +/*-----------------------------------------------------------*/ + +volatile uint32_t ul1 = 0x123, ul2 = 0; + +int main( void ) +{ + configASSERT( ul1 == 0x123 ); + configASSERT( ul2 == 0 ); + prvSetupHardware(); + + /* Create the queue used to pass "I'm alive" messages to the check task. */ + xGlobalScopeCheckQueue = xQueueCreateStatic( 1, sizeof( uint32_t ), ucGlobalScopeQueueStorageArea, &xGlobalScopeQueueBuffer ); + + /* 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 so is set here. */ + xRegTest2Parameters.pvParameters = xGlobalScopeCheckQueue; + + /* Create three test tasks. Handles to the created tasks are not required, + hence the second parameter is NULL. */ + xTaskCreateRestrictedStatic( &xRegTest1Parameters, NULL ); + xTaskCreateRestrictedStatic( &xRegTest2Parameters, NULL ); + xTaskCreateRestrictedStatic( &xCheckTaskParameters, NULL ); + + /* Create a task that does nothing but ensure some of the MPU API functions + can be called correctly, then get deleted. This is done for code coverage + test purposes only. The task's handle is saved in xTaskToDelete so it can + get deleted in the idle task hook. */ + xTaskCreateRestrictedStatic( &xTaskToDeleteParameters, &xTaskToDelete ); + + /* Create the tasks that are created using the original xTaskCreate() API + function. */ + xTaskCreateStatic( prvOldStyleUserModeTask, /* The function that implements the task. */ + "Task1", /* Text name for the task. */ + 100, /* Stack depth in words. */ + NULL, /* Task parameters. */ + 3, /* Priority and mode (user in this case). */ + xUserModeTaskStack, /* Used as the task's stack. */ + &xUserModeTaskBuffer /* Used to hold the task's data structure. */ + ); + + xTaskCreateStatic( prvOldStylePrivilegedModeTask, /* The function that implements the task. */ + "Task2", /* Text name for the task. */ + 100, /* Stack depth in words. */ + NULL, /* Task parameters. */ + ( 3 | portPRIVILEGE_BIT ), /* Priority and mode. */ + xPrivilegedModeTaskStack, /* Used as the task's stack. */ + &xPrivilegedModeTaskBuffer /* Used to hold the task's data structure. */ + ); + + /* Create the third and fourth register check tasks, as described at the top + of this file. */ + xTaskCreateStatic( prvRegTest3Task, "Reg3", configMINIMAL_STACK_SIZE, configREG_TEST_TASK_3_PARAMETER, tskIDLE_PRIORITY, xRegTest3Stack, &xRegTest3Buffer ); + xTaskCreateStatic( prvRegTest4Task, "Reg4", configMINIMAL_STACK_SIZE, configREG_TEST_TASK_4_PARAMETER, tskIDLE_PRIORITY, xRegTest4Stack, &xRegTest4Buffer ); + + /* Create and start the software timer. */ + xTimer = xTimerCreateStatic( "Timer", /* Test name for the timer. */ + mainTIMER_PERIOD, /* Period of the timer. */ + pdTRUE, /* The timer will auto-reload itself. */ + ( void * ) 0, /* The timer's ID is used to count the number of times it expires - initialise this to 0. */ + prvTimerCallback, /* The function called when the timer expires. */ + &xTimerBuffer ); /* The variable in which the created timer's data structure will be stored. */ + configASSERT( xTimer ); + xTimerStart( xTimer, mainDONT_BLOCK ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Will only get here if there was insufficient memory to create the idle + task. */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +static void prvCheckTask( 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 +longer be accessible but the stack copy will. */ +QueueHandle_t xQueue = xGlobalScopeCheckQueue; +int32_t lMessage; +uint32_t ulStillAliveCounts[ 3 ] = { 0 }; +const char *pcStatusMessage = "PASS\r\n"; +uint32_t ulLastRegTest3CountValue = 0, ulLastRegTest4Value = 0; + +/* The register test tasks that also test the floating point registers increment +a counter on each iteration of their loop. The counters are inside the array +that this task has access to. */ +volatile uint32_t *pulOverlaidCounter3 = ( uint32_t * ) &( cReadWriteArray[ 0 ] ), *pulOverlaidCounter4 = ( uint32_t * ) &( cReadWriteArray[ 4 ] ); + +/* ulCycleCount is incremented on each cycle of the check task. It can be +viewed updating in the Keil watch window as the simulator does not print to +the ITM port. */ +volatile uint32_t ulCycleCount = 0; + + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + /* Demonstrate how the various memory regions can and can't be accessed. + The task privilege level is set down to user mode within this function. */ + prvTestMemoryRegions(); + + /* Clear overlaid reg test counters before entering the loop below. */ + *pulOverlaidCounter3 = 0UL; + *pulOverlaidCounter4 = 0UL; + + /* This loop performs the main function of the task, which is blocking + on a message queue then processing each message as it arrives. */ + for( ;; ) + { + /* Wait for the next message to arrive. */ + xQueueReceive( xQueue, &lMessage, portMAX_DELAY ); + + switch( lMessage ) + { + case configREG_TEST_1_STILL_EXECUTING : + case configREG_TEST_2_STILL_EXECUTING : + case configTIMER_STILL_EXECUTING : + /* Message from the first or second register check task, or + the timer callback function. Increment the count of the + number of times the message source has sent the message as + the message source must still be executed. */ + ( ulStillAliveCounts[ lMessage ] )++; + break; + + case configPRINT_SYSTEM_STATUS : + /* Message from tick hook, time to print out the system + status. If messages have stopped arriving from either of + the first two reg test task or the timer callback then the + status must be set to fail. */ + if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 ) || ( ulStillAliveCounts[ 2 ] == 0 ) ) + { + /* One or both of the test tasks are no longer sending + 'still alive' messages. */ + pcStatusMessage = "FAIL\r\n"; + } + else + { + /* Reset the count of 'still alive' messages. */ + memset( ( void * ) ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) ); + } + + /* Check that the register test 3 task is still incrementing + its counter, and therefore still running. */ + if( ulLastRegTest3CountValue == *pulOverlaidCounter3 ) + { + pcStatusMessage = "FAIL\r\n"; + } + ulLastRegTest3CountValue = *pulOverlaidCounter3; + + /* Check that the register test 4 task is still incrementing + its counter, and therefore still running. */ + if( ulLastRegTest4Value == *pulOverlaidCounter4 ) + { + pcStatusMessage = "FAIL\r\n"; + } + ulLastRegTest4Value = *pulOverlaidCounter4; + + /**** Print pcStatusMessage here. ****/ + ( void ) pcStatusMessage; + + /* The cycle count can be viewed updating in the Keil watch + window if ITM printf is not being used. */ + ulCycleCount++; + break; + + default : + /* Something unexpected happened. Delete this task so the + error is apparent (no output will be displayed). */ + vMainDeleteMe(); + break; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvTestMemoryRegions( void ) +{ +int32_t x; +char cTemp; + + /* 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' ) + { + /* Something unexpected happened. Delete this task so the error is + apparent (no output will be displayed). */ + vMainDeleteMe(); + } + + /* Writing off the end of the RAM allocated to this task will *NOT* cause a + protection fault because the task is still executing in a privileged mode. + Uncomment the following to test. */ + /*cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] = 'a';*/ + + /* Now set the task into user mode. */ + portSWITCH_TO_USER_MODE(); + + /* Accessing the privileged only array will now cause a fault. Uncomment + the following line to test. */ + /*cPrivilegedOnlyAccessArray[ 0 ] = 'a';*/ + + /* The read/write array can still be successfully read and written. */ + for( x = 0; x < mainREAD_WRITE_ALIGN_SIZE; x++ ) + { + cReadWriteArray[ x ] = 'a'; + if( cReadWriteArray[ x ] != 'a' ) + { + /* Something unexpected happened. Delete this task so the error is + apparent (no output will be displayed). */ + vMainDeleteMe(); + } + } + + /* But attempting to read or write off the end of the RAM allocated to this + task will cause a fault. Uncomment either of the following two lines to + test. */ + /* cReadWriteArray[ 0 ] = cReadWriteArray[ -1 ]; */ + /* cReadWriteArray[ mainREAD_WRITE_ALIGN_SIZE ] = 0x00; */ + + /* The read only array can be successfully read... */ + for( x = 0; x < mainREAD_ONLY_ALIGN_SIZE; x++ ) + { + cTemp = cReadOnlyArray[ x ]; + } + + /* ...but cannot be written. Uncomment the following line to test. */ + /* cReadOnlyArray[ 0 ] = 'a'; */ + + /* Writing to the first and last locations in the stack array should not + cause a protection fault. Note that doing this will cause the kernel to + detect a stack overflow if configCHECK_FOR_STACK_OVERFLOW is greater than + 1, hence the test is commented out by default. */ + /* xCheckTaskStack[ 0 ] = 0; + xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS - 1 ] = 0; */ + + /* Writing off either end of the stack array should cause a protection + fault, uncomment either of the following two lines to test. */ + /* xCheckTaskStack[ -1 ] = 0; */ + /* xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] = 0; */ + + ( void ) cTemp; +} +/*-----------------------------------------------------------*/ + +static void prvExerciseEventGroupAPI( void ) +{ +EventGroupHandle_t xEventGroup; +StaticEventGroup_t xEventGroupBuffer; +EventBits_t xBits; +const EventBits_t xBitsToWaitFor = ( EventBits_t ) 0xff, xBitToClear = ( EventBits_t ) 0x01; + + /* Exercise some event group functions. */ + xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer ); + configASSERT( xEventGroup ); + + /* No bits should be set. */ + xBits = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdFALSE, mainDONT_BLOCK ); + configASSERT( xBits == ( EventBits_t ) 0 ); + + /* Set bits and read back to ensure the bits were set. */ + xEventGroupSetBits( xEventGroup, xBitsToWaitFor ); + xBits = xEventGroupGetBits( xEventGroup ); + configASSERT( xBits == xBitsToWaitFor ); + + /* Clear a bit and read back again using a different API function. */ + xEventGroupClearBits( xEventGroup, xBitToClear ); + xBits = xEventGroupSync( xEventGroup, 0x00, xBitsToWaitFor, mainDONT_BLOCK ); + configASSERT( xBits == ( xBitsToWaitFor & ~xBitToClear ) ); + + /* Finished with the event group. */ + vEventGroupDelete( xEventGroup ); +} +/*-----------------------------------------------------------*/ + +static void prvExerciseSemaphoreAPI( void ) +{ +SemaphoreHandle_t xSemaphore; +StaticSemaphore_t xSemaphoreBuffer; +const UBaseType_t uxMaxCount = 5, uxInitialCount = 0; + + /* Most of the semaphore API is common to the queue API and is already being + used. This function uses a few semaphore functions that are unique to the + RTOS objects, rather than generic and used by queues also. + + First create and use a counting semaphore. */ + xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, &xSemaphoreBuffer ); + configASSERT( xSemaphore ); + + /* Give the semaphore a couple of times and ensure the count is returned + correctly. */ + xSemaphoreGive( xSemaphore ); + xSemaphoreGive( xSemaphore ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 2 ); + vSemaphoreDelete( xSemaphore ); + + /* Create a recursive mutex, and ensure the mutex holder and count are + returned returned correctly. */ + xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 ); + configASSERT( xSemaphore ); + xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK ); + xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK ); + configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() ); + configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetHandle( mainTASK_TO_DELETE_NAME ) ); + xSemaphoreGiveRecursive( xSemaphore ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); + xSemaphoreGiveRecursive( xSemaphore ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 ); + configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL ); + vSemaphoreDelete( xSemaphore ); + + /* Create a normal mutex, and sure the mutex holder and count are returned + returned correctly. */ + xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer ); + configASSERT( xSemaphore ); + xSemaphoreTake( xSemaphore, mainDONT_BLOCK ); + xSemaphoreTake( xSemaphore, mainDONT_BLOCK ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); /* Not recursive so can only be 1. */ + configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() ); + xSemaphoreGive( xSemaphore ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 ); + configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL ); + vSemaphoreDelete( xSemaphore ); +} +/*-----------------------------------------------------------*/ + +static void prvExerciseTaskNotificationAPI( void ) +{ +uint32_t ulNotificationValue; +BaseType_t xReturned; + + /* The task should not yet have a notification pending. */ + xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK ); + configASSERT( xReturned == pdFAIL ); + configASSERT( ulNotificationValue == 0UL ); + + /* Exercise the 'give' and 'take' versions of the notification API. */ + xTaskNotifyGive( xTaskGetCurrentTaskHandle() ); + xTaskNotifyGive( xTaskGetCurrentTaskHandle() ); + ulNotificationValue = ulTaskNotifyTake( pdTRUE, mainDONT_BLOCK ); + configASSERT( ulNotificationValue == 2 ); + + /* Exercise the 'notify' and 'clear' API. */ + ulNotificationValue = 20; + xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite ); + ulNotificationValue = 0; + xReturned = xTaskNotifyWait( 0, 0, &ulNotificationValue, mainDONT_BLOCK ); + configASSERT( xReturned == pdPASS ); + configASSERT( ulNotificationValue == 20 ); + xTaskNotify( xTaskGetCurrentTaskHandle(), ulNotificationValue, eSetValueWithOverwrite ); + xReturned = xTaskNotifyStateClear( NULL ); + configASSERT( xReturned == pdTRUE ); /* First time a notification was pending. */ + xReturned = xTaskNotifyStateClear( NULL ); + configASSERT( xReturned == pdFALSE ); /* Second time the notification was already clear. */ +} +/*-----------------------------------------------------------*/ + +static void prvTaskToDelete( void *pvParameters ) +{ + /* Remove compiler warnings about unused parameters. */ + ( void ) pvParameters; + + /* Check the enter and exit critical macros are working correctly. If the + SVC priority is below configMAX_SYSCALL_INTERRUPT_PRIORITY then this will + fault. */ + taskENTER_CRITICAL(); + taskEXIT_CRITICAL(); + + /* Exercise the API of various RTOS objects. */ + prvExerciseEventGroupAPI(); + prvExerciseSemaphoreAPI(); + prvExerciseTaskNotificationAPI(); + + /* For code coverage test purposes it is deleted by the Idle task. */ + configASSERT( uxTaskGetStackHighWaterMark( NULL ) > 0 ); + vTaskSuspend( NULL ); +} +/*-----------------------------------------------------------*/ + +void vApplicationIdleHook( void ) +{ +volatile const uint32_t *pul; +volatile uint32_t ulReadData; + + /* The idle task, and therefore this function, run in Supervisor mode and + can therefore access all memory. Try reading from corners of flash and + RAM to ensure a memory fault does not occur. + + Start with the edges of the privileged data area. */ + pul = __privileged_data_start__; + ulReadData = *pul; + pul = __privileged_data_end__ - 1; + ulReadData = *pul; + + /* Next the standard SRAM area. */ + pul = __SRAM_segment_end__ - 1; + ulReadData = *pul; + + /* And the standard Flash area - the start of which is marked for + privileged access only. */ + pul = __FLASH_segment_start__; + ulReadData = *pul; + pul = __FLASH_segment_end__ - 1; + ulReadData = *pul; + + /* Reading off the end of Flash or SRAM space should cause a fault. + Uncomment one of the following two pairs of lines to test. */ + + /* pul = __FLASH_segment_end__ + 4; + ulReadData = *pul; */ + + /* pul = __SRAM_segment_end__ + 1; + ulReadData = *pul; */ + + /* One task is created purely so it can be deleted - done for code coverage + test purposes. */ + if( xTaskToDelete != NULL ) + { + vTaskDelete( xTaskToDelete ); + xTaskToDelete = NULL; + } + + ( void ) ulReadData; +} +/*-----------------------------------------------------------*/ + +static void prvOldStyleUserModeTask( void *pvParameters ) +{ +/*const volatile uint32_t *pulStandardPeripheralRegister = ( volatile uint32_t * ) 0x40000000;*/ +volatile const uint32_t *pul; +volatile uint32_t ulReadData; + +/* 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 uint32_t __privileged_functions_start__[]; */ +/* const volatile uint32_t *pulSystemPeripheralRegister = ( volatile uint32_t * ) 0xe000e014; */ + + ( void ) pvParameters; + + /* This task is created in User mode using the original xTaskCreate() API + function. It should have access to all Flash and RAM except that marked + as Privileged access only. 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; + + /* 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. Also uncomment the declaration of __privileged_functions_start__ + at the top of this function. */ + + /*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;*/ + + /* 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 ); + + ( void ) ulReadData; +} +/*-----------------------------------------------------------*/ + +static void prvOldStylePrivilegedModeTask( void *pvParameters ) +{ +volatile const uint32_t *pul; +volatile uint32_t ulReadData; +const volatile uint32_t *pulSystemPeripheralRegister = ( volatile uint32_t * ) 0xe000e014; /* Systick */ +/*const volatile uint32_t *pulStandardPeripheralRegister = ( volatile uint32_t * ) 0x40000000;*/ + + ( 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 ); + + ( void ) ulReadData; +} +/*-----------------------------------------------------------*/ + +void vMainDeleteMe( void ) +{ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber ) +{ + if( xHandle != NULL ) + { + xQueueSend( xHandle, &ulTaskNumber, mainDONT_BLOCK ); + } +} +/*-----------------------------------------------------------*/ + +static void prvSetupHardware( void ) +{ +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ +static uint32_t ulCallCount = 0; +const uint32_t ulCallsBetweenSends = pdMS_TO_TICKS( 1000 ); +const uint32_t ulMessage = configPRINT_SYSTEM_STATUS; +portBASE_TYPE xDummy; + + /* If configUSE_TICK_HOOK is set to 1 then this function will get called + from each RTOS tick. It is called from the tick interrupt and therefore + will be executing in the privileged state. */ + + ulCallCount++; + + /* Is it time to print out the pass/fail message again? */ + if( ulCallCount >= ulCallsBetweenSends ) + { + ulCallCount = 0; + + /* Send a message to the check task to command it to check that all + the tasks are still running then print out the status. + + This is running in an ISR so has to use the "FromISR" version of + xQueueSend(). Because it is in an ISR it is running with privileges + so can access xGlobalScopeCheckQueue directly. */ + xQueueSendFromISR( xGlobalScopeCheckQueue, &ulMessage, &xDummy ); + } +} +/*-----------------------------------------------------------*/ + +void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ) +{ + /* If configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2 then this + function will automatically get called if a task overflows its stack. */ + ( void ) pxTask; + ( void ) pcTaskName; + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vApplicationMallocFailedHook( void ) +{ + /* If configUSE_MALLOC_FAILED_HOOK is set to 1 then this function will + be called automatically if a call to pvPortMalloc() fails. pvPortMalloc() + is called automatically when a task, queue or semaphore is created. */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +static void prvTimerCallback( TaskHandle_t xExpiredTimer ) +{ +uint32_t ulCount; + + /* The count of the number of times this timer has expired is saved in the + timer's ID. Obtain the current count. */ + ulCount = ( uint32_t ) pvTimerGetTimerID( xTimer ); + + /* Increment the count, and save it back into the timer's ID. */ + ulCount++; + vTimerSetTimerID( xTimer, ( void * ) ulCount ); + + /* Let the check task know the timer is still running. */ + vMainSendImAlive( xGlobalScopeCheckQueue, configTIMER_STILL_EXECUTING ); +} +/*-----------------------------------------------------------*/ + +/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an +implementation of vApplicationGetIdleTaskMemory() to provide the memory that is +used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ +/* If the buffers to be provided to the Idle task are declared inside this +function then they must be declared static - otherwise they will be allocated on +the stack and so not exists after this function exits. */ +static StaticTask_t xIdleTaskTCB; +static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} +/*-----------------------------------------------------------*/ + +/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the +application must provide an implementation of vApplicationGetTimerTaskMemory() +to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) +{ +/* If the buffers to be provided to the Timer task are declared inside this +function then they must be declared static - otherwise they will be allocated on +the stack and so not exists after this function exits. */ +static StaticTask_t xTimerTaskTCB; +static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} +/*-----------------------------------------------------------*/ + +static void prvRegTest3Task( void *pvParameters ) +{ + /* Although the regtest task is written in assembler, its entry point is + written in C for convenience of checking the task parameter is being passed + in correctly. */ + if( pvParameters == configREG_TEST_TASK_3_PARAMETER ) + { + /* Start the part of the test that is written in assembler. */ + vRegTest3Implementation(); + } + + /* The following line will only execute if the task parameter is found to + be incorrect. The check task will detect that the regtest loop counter is + not being incremented and flag an error. */ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvRegTest4Task( void *pvParameters ) +{ + /* Although the regtest task is written in assembler, its entry point is + written in C for convenience of checking the task parameter is being passed + in correctly. */ + if( pvParameters == configREG_TEST_TASK_4_PARAMETER ) + { + /* Start the part of the test that is written in assembler. */ + vRegTest4Implementation(); + } + + /* The following line will only execute if the task parameter is found to + be incorrect. The check task will detect that the regtest loop counter is + not being incremented and flag an error. */ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + + diff --git a/FreeRTOS/Source/include/mpu_prototypes.h b/FreeRTOS/Source/include/mpu_prototypes.h index b4a1d0980..205995757 100644 --- a/FreeRTOS/Source/include/mpu_prototypes.h +++ b/FreeRTOS/Source/include/mpu_prototypes.h @@ -83,6 +83,7 @@ BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ); TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ); BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); +BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ); void MPU_vTaskDelay( const TickType_t xTicksToDelay ); diff --git a/FreeRTOS/Source/include/mpu_wrappers.h b/FreeRTOS/Source/include/mpu_wrappers.h index 7d3334282..622b0e2e0 100644 --- a/FreeRTOS/Source/include/mpu_wrappers.h +++ b/FreeRTOS/Source/include/mpu_wrappers.h @@ -177,8 +177,11 @@ only for ports that are using the MPU. */ #define xEventGroupSync MPU_xEventGroupSync #define vEventGroupDelete MPU_vEventGroupDelete - /* Remove the privileged function macro. */ + /* Remove the privileged function macro, but keep the PRIVILEGED_DATA + macro so applications can place data in privileged access sections + (useful when using statically allocated objects). */ #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h index dd7cd0322..172e0b6d5 100644 --- a/FreeRTOS/Source/include/task.h +++ b/FreeRTOS/Source/include/task.h @@ -160,6 +160,9 @@ typedef struct xTASK_PARAMETERS UBaseType_t uxPriority; StackType_t *puxStackBuffer; MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; + #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + StaticTask_t * const pxTaskBuffer; + #endif } TaskParameters_t; /* Used with the uxTaskGetSystemState() function to return the state of each task @@ -487,6 +490,8 @@ is used in assert() statements. */ *
  BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
* + * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. + * * xTaskCreateRestricted() should only be used in systems that include an MPU * implementation. * @@ -494,6 +499,9 @@ is used in assert() statements. */ * The function parameters define the memory regions and associated access * permissions allocated to the task. * + * See xTaskCreateRestrictedStatic() for a version that does not use any + * dynamic memory allocation. + * * @param pxTaskDefinition Pointer to a structure that contains a member * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API * documentation) plus an optional stack buffer and the memory region @@ -553,6 +561,94 @@ TaskHandle_t xHandle; BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; #endif +/** + * task. h + *
+ BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * + * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. + * + * xTaskCreateRestrictedStatic() should only be used in systems that include an + * MPU implementation. + * + * Internally, within the FreeRTOS implementation, tasks use two blocks of + * memory. The first block is used to hold the task's data structures. The + * second block is used by the task as its stack. If a task is created using + * xTaskCreateRestricted() then the stack is provided by the application writer, + * and the memory used to hold the task's data structure is automatically + * dynamically allocated inside the xTaskCreateRestricted() function. If a task + * is created using xTaskCreateRestrictedStatic() then the application writer + * must provide the memory used to hold the task's data structures too. + * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be + * created without using any dynamic memory allocation. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure + * contains an additional member, which is used to point to a variable of type + * StaticTask_t - which is then used to hold the task's data structure. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+// Create an TaskParameters_t structure that defines the task to be created.
+// The StaticTask_t variable is only included in the structure when
+// configSUPPORT_STATIC_ALLOCATION is set to 1.  The PRIVILEGED_DATA macro can
+// be used to force the variable into the RTOS kernel's privileged data area.
+static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
+static const TaskParameters_t xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+
+	&xTaskBuffer; // Holds the task's data structure.
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// and/or timer task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic + * \ingroup Tasks + */ +#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif + /** * task. h *
diff --git a/FreeRTOS/Source/portable/Common/mpu_wrappers.c b/FreeRTOS/Source/portable/Common/mpu_wrappers.c
index 8a5115b78..0fae3c65c 100644
--- a/FreeRTOS/Source/portable/Common/mpu_wrappers.c
+++ b/FreeRTOS/Source/portable/Common/mpu_wrappers.c
@@ -96,15 +96,30 @@ extern BaseType_t xPortRaisePrivilege( void );
 
 /*-----------------------------------------------------------*/
 
-BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
-{
-BaseType_t xReturn;
-BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+	{
+	BaseType_t xReturn;
+	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 
-	xReturn = xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
-	vPortResetPrivilege( xRunningPrivileged );
-	return xReturn;
-}
+		xReturn = xTaskCreateRestricted( pxTaskDefinition, pxCreatedTask );
+		vPortResetPrivilege( xRunningPrivileged );
+		return xReturn;
+	}
+#endif /* conifgSUPPORT_DYNAMIC_ALLOCATION */
+/*-----------------------------------------------------------*/
+
+#if( configSUPPORT_STATIC_ALLOCATION == 1 )
+	BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+	{
+	BaseType_t xReturn;
+	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+
+		xReturn = xTaskCreateRestrictedStatic( pxTaskDefinition, pxCreatedTask );
+		vPortResetPrivilege( xRunningPrivileged );
+		return xReturn;
+	}
+#endif /* conifgSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
@@ -337,7 +352,7 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 #endif
 /*-----------------------------------------------------------*/
 
-#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 	void MPU_vTaskList( char *pcWriteBuffer )
 	{
 	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@@ -348,7 +363,7 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 #endif
 /*-----------------------------------------------------------*/
 
-#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 	void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer )
 	{
 	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@@ -726,7 +741,7 @@ void * xReturn;
 #endif
 /*-----------------------------------------------------------*/
 
-#if ( configUSE_QUEUE_SETS == 1 )
+#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 	QueueSetHandle_t MPU_xQueueCreateSet( UBaseType_t uxEventQueueLength )
 	{
 	QueueSetHandle_t xReturn;
@@ -827,7 +842,6 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 /*-----------------------------------------------------------*/
 
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-
 	void *MPU_pvPortMalloc( size_t xSize )
 	{
 	void *pvReturn;
@@ -839,12 +853,10 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 
 		return pvReturn;
 	}
-
 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-
 	void MPU_vPortFree( void *pv )
 	{
 	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
@@ -853,31 +865,34 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 
 		vPortResetPrivilege( xRunningPrivileged );
 	}
-
 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
-void MPU_vPortInitialiseBlocks( void )
-{
-BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	void MPU_vPortInitialiseBlocks( void )
+	{
+	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 
-	vPortInitialiseBlocks();
+		vPortInitialiseBlocks();
 
-	vPortResetPrivilege( xRunningPrivileged );
-}
+		vPortResetPrivilege( xRunningPrivileged );
+	}
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
-size_t MPU_xPortGetFreeHeapSize( void )
-{
-size_t xReturn;
-BaseType_t xRunningPrivileged = xPortRaisePrivilege();
+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+	size_t MPU_xPortGetFreeHeapSize( void )
+	{
+	size_t xReturn;
+	BaseType_t xRunningPrivileged = xPortRaisePrivilege();
 
-	xReturn = xPortGetFreeHeapSize();
+		xReturn = xPortGetFreeHeapSize();
 
-	vPortResetPrivilege( xRunningPrivileged );
+		vPortResetPrivilege( xRunningPrivileged );
 
-	return xReturn;
-}
+		return xReturn;
+	}
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_TIMERS == 1 ) )
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c
index 8a296ba53..1cdb016db 100644
--- a/FreeRTOS/Source/tasks.c
+++ b/FreeRTOS/Source/tasks.c
@@ -134,7 +134,7 @@ that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
 a statically allocated stack and a dynamically allocated TCB.
 !!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
 changed then the definition of StaticTask_t must also be updated. */
-#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE   ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB 		( ( uint8_t ) 0 )
 #define tskSTATICALLY_ALLOCATED_STACK_ONLY 			( ( uint8_t ) 1 )
 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB		( ( uint8_t ) 2 )
@@ -667,7 +667,53 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 #endif /* SUPPORT_STATIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
-#if( portUSING_MPU_WRAPPERS == 1 )
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+	BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+	{
+	TCB_t *pxNewTCB;
+	BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+		configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
+		configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
+
+		if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
+		{
+			/* Allocate space for the TCB.  Where the memory comes from depends
+			on the implementation of the port malloc function and whether or
+			not static allocation is being used. */
+			pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
+
+			/* Store the stack location in the TCB. */
+			pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+			{
+				/* Tasks can be created statically or dynamically, so note this
+				task was created statically in case the task is later deleted. */
+				pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+			}
+			#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+			
+			prvInitialiseNewTask(	pxTaskDefinition->pvTaskCode,
+									pxTaskDefinition->pcName,
+									( uint32_t ) pxTaskDefinition->usStackDepth,
+									pxTaskDefinition->pvParameters,
+									pxTaskDefinition->uxPriority,
+									pxCreatedTask, pxNewTCB,
+									pxTaskDefinition->xRegions );
+
+			prvAddNewTaskToReadyList( pxNewTCB );
+			xReturn = pdPASS;
+		}
+
+		return xReturn;
+	}
+
+#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+/*-----------------------------------------------------------*/
+
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
 	{
@@ -3987,7 +4033,7 @@ TCB_t *pxTCB;
 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
 /*-----------------------------------------------------------*/
 
-#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	void vTaskList( char * pcWriteBuffer )
 	{
@@ -4079,10 +4125,10 @@ TCB_t *pxTCB;
 		}
 	}
 
-#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
 /*----------------------------------------------------------*/
 
-#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	void vTaskGetRunTimeStats( char *pcWriteBuffer )
 	{
@@ -4206,7 +4252,7 @@ TCB_t *pxTCB;
 		}
 	}
 
-#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
 TickType_t uxTaskResetEventItemValue( void )
-- 
2.39.2