]> git.sur5r.net Git - freertos/commitdiff
Added CM3 MPU demo.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 28 Sep 2009 14:26:40 +0000 (14:26 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 28 Sep 2009 14:26:40 +0000 (14:26 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@856 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/LM3S_Startup.s [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/LM3S_Target.js [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/RTOSDemo.hzp [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/RTOSDemo.hzs [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/flash_placement.xml [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c [new file with mode: 0644]
Demo/CORTEX_MPU_LM3Sxxxx_Rowley/thumb_crt0.s [new file with mode: 0644]

diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/FreeRTOSConfig.h
new file mode 100644 (file)
index 0000000..c57ad43
--- /dev/null
@@ -0,0 +1,110 @@
+/*\r
+       FreeRTOS V5.4.2 - Copyright (C) 2009 Real Time Engineers Ltd.\r
+\r
+       This file is part of the FreeRTOS distribution.\r
+\r
+       FreeRTOS is free software; you can redistribute it and/or modify it     under\r
+       the terms of the GNU General Public License (version 2) as published by the\r
+       Free Software Foundation and modified by the FreeRTOS exception.\r
+       **NOTE** The exception to the GPL is included to allow you to distribute a\r
+       combined work that includes FreeRTOS without being obliged to provide the\r
+       source code for proprietary components outside of the FreeRTOS kernel.\r
+       Alternative commercial license and support terms are also available upon\r
+       request.  See the licensing section of http://www.FreeRTOS.org for full\r
+       license details.\r
+\r
+       FreeRTOS is distributed in the hope that it will be useful,     but WITHOUT\r
+       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+       more details.\r
+\r
+       You should have received a copy of the GNU General Public License along\r
+       with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59\r
+       Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
+\r
+\r
+       ***************************************************************************\r
+       *                                                                         *\r
+       * Looking for a quick start?  Then check out the FreeRTOS eBook!          *\r
+       * See http://www.FreeRTOS.org/Documentation for details                   *\r
+       *                                                                         *\r
+       ***************************************************************************\r
+\r
+       1 tab == 4 spaces!\r
+\r
+       Please ensure to read the configuration and relevant port sections of the\r
+       online documentation.\r
+\r
+       http://www.FreeRTOS.org - Documentation, latest information, license and\r
+       contact details.\r
+\r
+       http://www.SafeRTOS.com - A version that is certified for use in safety\r
+       critical systems.\r
+\r
+       http://www.OpenRTOS.com - Commercial support, development, porting,\r
+       licensing and training services.\r
+*/\r
+\r
+#ifndef FREERTOS_CONFIG_H\r
+#define FREERTOS_CONFIG_H\r
+\r
+/*-----------------------------------------------------------\r
+ * Application specific definitions.\r
+ *\r
+ * These definitions should be adjusted for your particular hardware and\r
+ * application requirements.\r
+ *\r
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE\r
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.\r
+ *\r
+ * See http://www.freertos.org/a00110.html.\r
+ *----------------------------------------------------------*/\r
+\r
+#define configUSE_PREEMPTION                   1\r
+#define configUSE_IDLE_HOOK                            0\r
+#define configUSE_TICK_HOOK                            1\r
+#define configCPU_CLOCK_HZ                             ( ( unsigned portLONG ) 50000000 )\r
+#define configTICK_RATE_HZ                             ( ( portTickType ) 1000 )\r
+#define configMINIMAL_STACK_SIZE               ( ( unsigned portSHORT ) 100 )\r
+#define configTOTAL_HEAP_SIZE                  ( ( size_t ) ( 24000 ) )\r
+#define configMAX_TASK_NAME_LEN                        ( 12 )\r
+#define configUSE_TRACE_FACILITY               1\r
+#define configUSE_16_BIT_TICKS                 0\r
+#define configIDLE_SHOULD_YIELD                        0\r
+#define configUSE_CO_ROUTINES                  0\r
+#define configUSE_MUTEXES                              1\r
+#define configCHECK_FOR_STACK_OVERFLOW 0\r
+#define configUSE_RECURSIVE_MUTEXES            1\r
+#define configQUEUE_REGISTRY_SIZE              10\r
+#define configGENERATE_RUN_TIME_STATS  0\r
+#define configUSE_MALLOC_FAILED_HOOK   1\r
+\r
+#define configMAX_PRIORITIES           ( ( unsigned portBASE_TYPE ) 5 )\r
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )\r
+\r
+/* Set the following definitions to 1 to include the API function, or zero\r
+to exclude the API function. */\r
+\r
+#define INCLUDE_vTaskPrioritySet                       1\r
+#define INCLUDE_uxTaskPriorityGet                      1\r
+#define INCLUDE_vTaskDelete                                    1\r
+#define INCLUDE_vTaskCleanUpResources          0\r
+#define INCLUDE_vTaskSuspend                           1\r
+#define INCLUDE_vTaskDelayUntil                                1\r
+#define INCLUDE_vTaskDelay                                     1\r
+#define INCLUDE_uxTaskGetStackHighWaterMark    1\r
+\r
+#ifdef __NVIC_PRIO_BITS\r
+       #define configPRIO_BITS       __NVIC_PRIO_BITS\r
+#else\r
+       #define configPRIO_BITS       3\r
+#endif\r
+#define configUNUSED_PRIO_BITS ( ( unsigned portCHAR ) ( 8 - configPRIO_BITS ) )\r
+\r
+#define configKERNEL_INTERRUPT_PRIORITY                ( ( unsigned portCHAR ) 7 << configUNUSED_PRIO_BITS )   /* Priority 7, or 255 as only the top three bits are implemented.  This is the lowest priority. */\r
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY   ( ( unsigned portCHAR ) 5 << configUNUSED_PRIO_BITS )  /* Priority 5, or 160 as only the top three bits are implemented. */\r
+\r
+#define pvPortMallocAligned( x, puxStackBuffer ) ( ( puxStackBuffer == NULL ) ? ( pvPortMalloc( x ) ) : ( puxStackBuffer ) )\r
+#define vPortFreeAligned( x ) ( void ) x\r
+\r
+#endif /* FREERTOS_CONFIG_H */\r
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/LM3S_Startup.s b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/LM3S_Startup.s
new file mode 100644 (file)
index 0000000..cbf6ecf
--- /dev/null
@@ -0,0 +1,196 @@
+/*****************************************************************************\r
+ * Copyright (c) 2006 Rowley Associates Limited.                             *\r
+ *                                                                           *\r
+ * This file may be distributed under the terms of the License Agreement     *\r
+ * provided with this software.                                              *\r
+ *                                                                           *\r
+ * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE   *\r
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *\r
+ *****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ *                           Preprocessor Definitions\r
+ *                           ------------------------\r
+ *\r
+ * STARTUP_FROM_RESET\r
+ *\r
+ *   If defined, the program will startup from power-on/reset. If not defined\r
+ *   the program will just loop endlessly from power-on/reset.\r
+ *\r
+ *   This definition is not defined by default on this target because the\r
+ *   debugger is unable to reset this target and maintain control of it over the\r
+ *   JTAG interface. The advantage of doing this is that it allows the debugger\r
+ *   to reset the CPU and run programs from a known reset CPU state on each run.\r
+ *   It also acts as a safety net if you accidently download a program in FLASH\r
+ *   that crashes and prevents the debugger from taking control over JTAG\r
+ *   rendering the target unusable over JTAG. The obvious disadvantage of doing\r
+ *   this is that your application will not startup without the debugger.\r
+ *\r
+ *   We advise that on this target you keep STARTUP_FROM_RESET undefined whilst\r
+ *   you are developing and only define STARTUP_FROM_RESET when development is\r
+ *   complete.\r
+ *\r
+ *****************************************************************************/\r
+\r
+.extern xPortPendSVHandler\r
+.extern xPortSysTickHandler\r
+.extern vPortSVCHandler\r
+\r
+.global reset_handler\r
+\r
+.macro DEFAULT_ISR_HANDLER name=\r
+  .thumb_func\r
+  .weak \name\r
+\name:\r
+1: b 1b /* endless loop */\r
+.endm\r
+\r
+  .section .vectors, "ax"\r
+  .code 16\r
+  .align 0\r
+  .global _vectors\r
+\r
+_vectors:\r
+  .word __stack_end__\r
+#ifdef STARTUP_FROM_RESET\r
+  .word reset_handler\r
+#else\r
+  .word reset_wait\r
+#endif /* STARTUP_FROM_RESET */\r
+  .word Nmi_ISR\r
+  .word Fault_ISR\r
+  .word MPU_Fault_ISR\r
+  .word 0  /* Populate if using Bus fault */\r
+  .word 0  /* Populate if using Usage fault */\r
+  .word 0  /* Reserved */\r
+  .word 0  /* Reserved */\r
+  .word 0  /* Reserved */\r
+  .word 0  /* Reserved */\r
+  .word vPortSVCHandler\r
+  .word 0  /* Populate if using a debug monitor */\r
+  .word 0  /* Reserved */\r
+  .word xPortPendSVHandler\r
+  .word xPortSysTickHandler\r
+  .word GPIO_Port_A_ISR\r
+  .word GPIO_Port_B_ISR\r
+  .word GPIO_Port_C_ISR\r
+  .word GPIO_Port_D_ISR\r
+  .word GPIO_Port_E_ISR\r
+  .word UART0_ISR\r
+  .word UART1_ISR\r
+  .word SSI_ISR\r
+  .word I2C_ISR\r
+  .word PWM_Fault_ISR\r
+  .word PWM_Generator_0_ISR\r
+  .word PWM_Generator_1_ISR\r
+  .word PWM_Generator_2_ISR\r
+  .word QEI_ISR\r
+  .word ADC_Sequence_0_ISR\r
+  .word ADC_Sequence_1_ISR\r
+  .word ADC_Sequence_2_ISR\r
+  .word ADC_Sequence_3_ISR\r
+  .word Watchdog_Timer_ISR\r
+  .word Timer0A_ISR\r
+  .word Timer0B_ISR\r
+  .word Timer1A_ISR\r
+  .word Timer1B_ISR\r
+  .word Timer2A_ISR\r
+  .word Timer2B_ISR\r
+  .word Analog_Comparator_0_ISR\r
+  .word Analog_Comparator_1_ISR\r
+  .word Analog_Comparator_2_ISR\r
+  .word System_Control_ISR\r
+  .word FLASH_Control_ISR\r
+  .word GPIO_Port_F_ISR\r
+  .word GPIO_Port_G_ISR\r
+  .word GPIO_Port_H_ISR\r
+  .word UART2_ISR\r
+  .word SSI1_ISR\r
+  .word Timer3A_ISR\r
+  .word Timer3B_ISR\r
+  .word I2C1_ISR\r
+  .word QEI1_ISR\r
+  .word CAN0_ISR\r
+  .word CAN1_ISR\r
+  .word CAN2_ISR\r
+  .word EMAC_ISR\r
+  .word HIBERNATE_ISR\r
+  .word USB0_ISR\r
+  .word PWM_Generator_3_ISR\r
+  .word uDMA_Software_Transfer_ISR\r
+  .word uDMA_Error_ISR\r
+_vectors_end:\r
+\r
+  .section .init, "ax"\r
+  .thumb_func\r
+\r
+reset_handler:\r
+#ifdef __RAM_BUILD\r
+  /* If this is a RAM build, configure vector table offset register to point\r
+     to the RAM vector table. */\r
+  ldr r0, =0xE000ED08\r
+  ldr r1, =_vectors\r
+  str r1, [r0]\r
+#endif\r
+  b _start\r
+\r
+DEFAULT_ISR_HANDLER Nmi_ISR\r
+/*DEFAULT_ISR_HANDLER Fault_ISR*/\r
+/*DEFAULT_ISR_HANDLER MPU_Fault_ISR*/\r
+DEFAULT_ISR_HANDLER SVCall_ISR\r
+DEFAULT_ISR_HANDLER SysTick_ISR\r
+DEFAULT_ISR_HANDLER PendSV_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_A_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_B_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_C_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_D_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_E_ISR\r
+DEFAULT_ISR_HANDLER UART0_ISR\r
+DEFAULT_ISR_HANDLER UART1_ISR\r
+DEFAULT_ISR_HANDLER SSI_ISR\r
+DEFAULT_ISR_HANDLER I2C_ISR\r
+DEFAULT_ISR_HANDLER PWM_Fault_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_0_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_1_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_2_ISR\r
+DEFAULT_ISR_HANDLER QEI_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_0_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_1_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_2_ISR\r
+DEFAULT_ISR_HANDLER ADC_Sequence_3_ISR\r
+DEFAULT_ISR_HANDLER Watchdog_Timer_ISR\r
+DEFAULT_ISR_HANDLER Timer0A_ISR\r
+DEFAULT_ISR_HANDLER Timer0B_ISR\r
+DEFAULT_ISR_HANDLER Timer1A_ISR\r
+DEFAULT_ISR_HANDLER Timer1B_ISR\r
+DEFAULT_ISR_HANDLER Timer2A_ISR\r
+DEFAULT_ISR_HANDLER Timer2B_ISR\r
+DEFAULT_ISR_HANDLER Analog_Comparator_0_ISR\r
+DEFAULT_ISR_HANDLER Analog_Comparator_1_ISR\r
+DEFAULT_ISR_HANDLER Analog_Comparator_2_ISR\r
+DEFAULT_ISR_HANDLER System_Control_ISR\r
+DEFAULT_ISR_HANDLER FLASH_Control_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_F_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_G_ISR\r
+DEFAULT_ISR_HANDLER GPIO_Port_H_ISR\r
+DEFAULT_ISR_HANDLER UART2_ISR\r
+DEFAULT_ISR_HANDLER SSI1_ISR\r
+DEFAULT_ISR_HANDLER Timer3A_ISR\r
+DEFAULT_ISR_HANDLER Timer3B_ISR\r
+DEFAULT_ISR_HANDLER I2C1_ISR\r
+DEFAULT_ISR_HANDLER QEI1_ISR\r
+DEFAULT_ISR_HANDLER CAN0_ISR\r
+DEFAULT_ISR_HANDLER CAN1_ISR\r
+DEFAULT_ISR_HANDLER CAN2_ISR\r
+DEFAULT_ISR_HANDLER ETHERNET_ISR\r
+DEFAULT_ISR_HANDLER HIBERNATE_ISR\r
+DEFAULT_ISR_HANDLER USB0_ISR\r
+DEFAULT_ISR_HANDLER PWM_Generator_3_ISR\r
+DEFAULT_ISR_HANDLER uDMA_Software_Transfer_ISR\r
+DEFAULT_ISR_HANDLER uDMA_Error_ISR\r
+DEFAULT_ISR_HANDLER EMAC_ISR\r
+\r
+#ifndef STARTUP_FROM_RESET\r
+DEFAULT_ISR_HANDLER reset_wait\r
+#endif /* STARTUP_FROM_RESET */\r
+\r
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/LM3S_Target.js b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/LM3S_Target.js
new file mode 100644 (file)
index 0000000..55a9c2c
--- /dev/null
@@ -0,0 +1,28 @@
+/******************************************************************************\r
+  Target Script for LM3S.\r
+\r
+  Copyright (c) 2006 Rowley Associates Limited.\r
+\r
+  This file may be distributed under the terms of the License Agreement\r
+  provided with this software.\r
+\r
+  THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE\r
+  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ ******************************************************************************/\r
+\r
+function Reset()\r
+{\r
+  TargetInterface.resetAndStop(1000);\r
+}\r
+\r
+function RAMReset()\r
+{\r
+  Reset();\r
+}\r
+\r
+function FLASHReset()\r
+{\r
+  Reset();\r
+}\r
+\r
+\r
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/RTOSDemo.hzp b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/RTOSDemo.hzp
new file mode 100644 (file)
index 0000000..0c93f88
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE CrossStudio_Project_File>
+<solution Name="RTOSDemo" version="2">
+  <project Name="RTOSDemo">
+    <configuration Name="Common" Target="LM3S8962" arm_architecture="v7M" arm_core_type="Cortex-M3" arm_linker_fiq_stack_size="0" arm_linker_heap_size="0" arm_linker_irq_stack_size="0" arm_linker_process_stack_size="0" arm_linker_stack_size="400" arm_simulator_memory_simulation_filename="$(PackagesDir)/targets/Luminary_LM3S/LM3SSimulatorMemory.dll" arm_simulator_memory_simulation_parameter="0x40000;0x10000" arm_target_debug_interface_type="ADIv5" arm_target_flash_loader_type="LIBMEM RPC Loader" build_remove_unused_symbols="No" c_only_additional_options="-Wall;-Wextra" c_preprocessor_definitions="sprintf=usprintf;snprintf=usnprintf;printf=uipprintf" c_user_include_directories="..\\..\\Source\\include;..\\..\\Source\\portable\\GCC\\ARM_CM3_MPU;..\\Common\\include;..\\Common\\drivers\\LuminaryMicro;.;$(SamplesDir)/Luminary_Stellaris_Driver_Library" gcc_optimization_level="None" linker_additional_files="" linker_memory_map_file="$(PackagesDir)/targets/Luminary_LM3S/LM3S8962_MemoryMap.xml" linker_output_format="None" linker_printf_fmt_level="int" linker_printf_width_precision_supported="No" linker_scanf_fmt_level="int" project_directory="" project_type="Executable" property_groups_file_path="$(PackagesDir)/targets/Luminary_LM3S/propertyGroups.xml"/>
+    <configuration Name="Flash" Placement="Flash" arm_target_flash_loader_file_path="$(PackagesDir)/targets/Luminary_LM3S/Release/Loader.elf" linker_section_placement_file="$(ProjectDir)/flash_placement.xml" target_reset_script="FLASHReset()"/>
+    <configuration Name="RAM" Placement="RAM" linker_section_placement_file="$(PackagesDir)/targets/Luminary_LM3S/ram_placement.xml" target_reset_script="RAMReset()"/>
+    <folder Name="Source Files">
+      <configuration Name="Common" filter="c;cpp;cxx;cc;h;s;asm;inc"/>
+      <folder Name="FreeRTOS MPU">
+        <folder Name="include" file_name="">
+          <file file_name="../../Source/portable/GCC/ARM_CM3/portmacro.h"/>
+          <file file_name="../../Source/include/task.h"/>
+          <file file_name="../../Source/include/FreeRTOS.h"/>
+          <file file_name="../../Source/include/list.h"/>
+          <file file_name="../../Source/include/portable.h"/>
+          <file file_name="../../Source/include/projdefs.h"/>
+          <file file_name="../../Source/include/queue.h"/>
+          <file file_name="../../Source/include/semphr.h"/>
+          <file file_name="../../Source/include/StackMacros.h"/>
+          <file file_name="../../Source/include/mpu_wrappers.h"/>
+        </folder>
+        <file file_name="../../Source/tasks.c"/>
+        <file file_name="../../Source/list.c"/>
+        <file file_name="../../Source/queue.c"/>
+        <file file_name="../../Source/portable/MemMang/heap_2.c"/>
+        <file file_name="../../Source/portable/GCC/ARM_CM3_MPU/port.c"/>
+      </folder>
+      <file file_name="main.c"/>
+      <folder Name="include">
+        <file file_name="FreeRTOSConfig.h"/>
+      </folder>
+      <folder Name="Libraries">
+        <file file_name="../Common/drivers/LuminaryMicro/Rowley/libdriver.a"/>
+      </folder>
+      <file file_name="../Common/drivers/LuminaryMicro/ustdlib.c"/>
+    </folder>
+    <folder Name="System Files">
+      <file file_name="thumb_crt0.s"/>
+      <file file_name="LM3S_Startup.s"/>
+      <file file_name="LM3S_Target.js">
+        <configuration Name="Common" build_exclude_from_build="Yes" file_type="Reset Script"/>
+        <configuration Name="THUMB Flash Debug" build_exclude_from_build="No"/>
+      </file>
+    </folder>
+  </project>
+  <configuration Name="THUMB Flash Debug" inherited_configurations="THUMB;Flash;Debug"/>
+  <configuration Name="THUMB" Platform="ARM" arm_instruction_set="THUMB" arm_library_instruction_set="THUMB" c_preprocessor_definitions="__THUMB" hidden="Yes"/>
+  <configuration Name="Flash" c_preprocessor_definitions="__FLASH_BUILD" hidden="Yes"/>
+  <configuration Name="Debug" build_debug_information="Yes" c_preprocessor_definitions="DEBUG" gcc_optimization_level="None" hidden="Yes" link_include_startup_code="No"/>
+  <configuration Name="THUMB Flash Release" inherited_configurations="THUMB;Flash;Release"/>
+  <configuration Name="Release" build_debug_information="No" c_additional_options="-g1" c_preprocessor_definitions="NDEBUG" gcc_optimization_level="Level 1" hidden="Yes" link_include_startup_code="No"/>
+</solution>
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/RTOSDemo.hzs b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/RTOSDemo.hzs
new file mode 100644 (file)
index 0000000..c8a7a40
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE CrossStudio_for_ARM_Session_File>
+<session>
+ <Bookmarks/>
+ <Breakpoints/>
+ <ExecutionCountWindow/>
+ <Memory1>
+  <MemoryWindow autoEvaluate="0" addressText="0x200002d0" numColumns="8" sizeText="120" dataSize="1" radix="16" addressSpace="" />
+ </Memory1>
+ <Memory2>
+  <MemoryWindow autoEvaluate="0" addressText="" numColumns="8" sizeText="" dataSize="1" radix="16" addressSpace="" />
+ </Memory2>
+ <Memory3>
+  <MemoryWindow autoEvaluate="0" addressText="" numColumns="8" sizeText="" dataSize="1" radix="16" addressSpace="" />
+ </Memory3>
+ <Memory4>
+  <MemoryWindow autoEvaluate="0" addressText="" numColumns="8" sizeText="" dataSize="1" radix="16" addressSpace="" />
+ </Memory4>
+ <Project>
+  <ProjectSessionItem path="RTOSDemo" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files" name="unnamed" />
+  <ProjectSessionItem path="RTOSDemo;RTOSDemo;Source Files;FreeRTOS MPU" name="unnamed" />
+ </Project>
+ <Register1>
+  <RegisterWindow openNodes="CPU;CPU/xPSR;CPU/CFBP;CPU/CFBP/CONTROL[0];CPU/CFBP/CONTROL[1];Interrupt_Type" binaryNodes="" unsignedNodes="" visibleGroups="CPU;Interrupt_Type" decimalNodes="" octalNodes="" asciiNodes="" />
+ </Register1>
+ <Register2>
+  <RegisterWindow openNodes="MPU;MPU/MPU_Control;MPU/MPU_Region_Base_Address;MPU/MPU_Attribute_and_Size" binaryNodes="MPU/MPU_Attribute_and_Size/SIZE" unsignedNodes="" visibleGroups="MPU" decimalNodes="" octalNodes="" asciiNodes="" />
+ </Register2>
+ <Register3>
+  <RegisterWindow openNodes="System_Control_Block;System_Control_Block/System_Handlers_8_11_Priority;System_Control_Block/System_Handler_Control_and_State" binaryNodes="" unsignedNodes="" visibleGroups="System_Control_Block" decimalNodes="" octalNodes="" asciiNodes="" />
+ </Register3>
+ <Register4>
+  <RegisterWindow openNodes="" binaryNodes="" unsignedNodes="" visibleGroups="" decimalNodes="" octalNodes="" asciiNodes="" />
+ </Register4>
+ <TargetWindow programAction="" uploadFileType="" programLoadAddress="" programSize="" uploadFileName="" uploadMemoryInterface="" programFileName="" uploadStartAddress="" programFileType="" uploadSize="" programMemoryInterface="" />
+ <TraceWindow>
+  <Trace enabled="Yes" />
+ </TraceWindow>
+ <Watch1>
+  <Watches active="1" update="Never" />
+ </Watch1>
+ <Watch2>
+  <Watches active="0" update="Never" />
+ </Watch2>
+ <Watch3>
+  <Watches active="0" update="Never" />
+ </Watch3>
+ <Watch4>
+  <Watches active="0" update="Never" />
+ </Watch4>
+ <Files>
+  <SessionOpenFile useTextEdit="1" useBinaryEdit="0" codecName="Latin1" x="0" debugPath="C:\E\Dev\FreeRTOS\Trial\FreeRTOS_MPU\FreeRTOS\Demo\CORTEX_MPU_LM3Sxxxx_Rowley\main.c" y="701" path="C:\E\Dev\FreeRTOS\Trial\FreeRTOS_MPU\FreeRTOS\Demo\CORTEX_MPU_LM3Sxxxx_Rowley\main.c" left="0" selected="1" name="unnamed" top="682" />
+ </Files>
+ <ARMCrossStudioWindow activeProject="RTOSDemo" autoConnectTarget="Luminary USB Debug" debugSearchFileMap="" fileDialogInitialDirectory="C:\E\Dev\FreeRTOS\WorkingCopy\Source\portable\GCC\ARM_CM3_MPU" fileDialogDefaultFilter="*.*" autoConnectCapabilities="388991" debugSearchPath="" buildConfiguration="THUMB Flash Debug" />
+</session>
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/flash_placement.xml b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/flash_placement.xml
new file mode 100644 (file)
index 0000000..800479d
--- /dev/null
@@ -0,0 +1,24 @@
+<!DOCTYPE Linker_Placement_File>
+<Root name="FLASH Section Placement">
+  <MemorySegment name="FLASH">
+    <ProgramSection load="Yes" inputsections="*(.vectors .vectors.*)" name=".vectors"/>
+       <ProgramSection alignment="4" size="16K - 0x100" load="Yes" inputsections="*(privileged_functions)" name="privileged_functions"/>
+    <ProgramSection alignment="4" load="Yes" inputsections="*(.init .init.*)" name=".init"/>
+    <ProgramSection alignment="4" load="Yes" inputsections="*(.text .text.* .glue_7t .glue_7 .gnu.linkonce.t.* .gcc_except_table)" name=".text"/>
+    <ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors))" name=".dtors"/>
+    <ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors))" name=".ctors"/>
+    <ProgramSection alignment="4" load="Yes" inputsections="*(.rodata .rodata.* .gnu.linkonce.r.*)" name=".rodata"/>
+    <ProgramSection alignment="4" load="Yes" runin=".data_run" inputsections="*(.data .data.* .gnu.linkonce.d.*)" name=".data"/>
+    <ProgramSection alignment="4" load="Yes" runin=".fast_run" inputsections="*(.fast .fast.*)" name=".fast"/>
+  </MemorySegment>
+  <MemorySegment name="SRAM">
+       <ProgramSection alignment="4" size="256" alignment="256" load="No" inputsections="*(privileged_data)" name="privileged_data"/>
+       <ProgramSection name=".vectors_ram" size="" alignment="0x100" load="No"/>    
+    <ProgramSection alignment="4" load="No" name=".data_run"/>
+    <ProgramSection alignment="4" load="No" inputsections="*(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)" name=".bss"/>
+    <ProgramSection alignment="4" load="No" inputsections="*(.non_init .non_init.*)" name=".non_init"/>
+    <ProgramSection alignment="4" size="__HEAPSIZE__" load="No" name=".heap"/>
+    <ProgramSection alignment="4" size="__STACKSIZE__" load="No" name=".stack"/>    
+    <ProgramSection alignment="4" load="No" name=".fast_run"/>
+  </MemorySegment>
+</Root>
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/main.c
new file mode 100644 (file)
index 0000000..67628e0
--- /dev/null
@@ -0,0 +1,742 @@
+/*\r
+       FreeRTOS V5.4.2 - Copyright (C) 2009 Real Time Engineers Ltd.\r
+\r
+       This file is part of the FreeRTOS distribution.\r
+\r
+       FreeRTOS is free software; you can redistribute it and/or modify it     under\r
+       the terms of the GNU General Public License (version 2) as published by the\r
+       Free Software Foundation and modified by the FreeRTOS exception.\r
+       **NOTE** The exception to the GPL is included to allow you to distribute a\r
+       combined work that includes FreeRTOS without being obliged to provide the\r
+       source code for proprietary components outside of the FreeRTOS kernel.\r
+       Alternative commercial license and support terms are also available upon\r
+       request.  See the licensing section of http://www.FreeRTOS.org for full\r
+       license details.\r
+\r
+       FreeRTOS is distributed in the hope that it will be useful,     but WITHOUT\r
+       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+       FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+       more details.\r
+\r
+       You should have received a copy of the GNU General Public License along\r
+       with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59\r
+       Temple Place, Suite 330, Boston, MA  02111-1307  USA.\r
+\r
+\r
+       ***************************************************************************\r
+       *                                                                                                                                                *\r
+       * Looking for a quick start?  Then check out the FreeRTOS eBook!                  *\r
+       * See http://www.FreeRTOS.org/Documentation for details                            *\r
+       *                                                                                                                                                *\r
+       ***************************************************************************\r
+\r
+       1 tab == 4 spaces!\r
+\r
+       Please ensure to read the configuration and relevant port sections of the\r
+       online documentation.\r
+\r
+       http://www.FreeRTOS.org - Documentation, latest information, license and\r
+       contact details.\r
+\r
+       http://www.SafeRTOS.com - A version that is certified for use in safety\r
+       critical systems.\r
+\r
+       http://www.OpenRTOS.com - Commercial support, development, porting,\r
+       licensing and training services.\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <string.h>\r
+#include <__cross_studio_io.h>\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Hardware library includes. */\r
+#include "hw_types.h"\r
+#include "hw_sysctl.h"\r
+#include "sysctl.h"\r
+\r
+/*\r
+ * This file demonstrates the use of MPU using just three tasks - two 'reg test'\r
+ * tasks and one 'check' task.  Read the comments above the\r
+ * function prototypes for more information.\r
+ */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Misc constants. */\r
+#define mainDONT_BLOCK                                 ( 0 )\r
+\r
+/* Definitions for the messages that can be sent to the check task. */\r
+#define mainREG_TEST_1_STILL_EXECUTING ( 0 )\r
+#define mainREG_TEST_2_STILL_EXECUTING ( 1 )\r
+#define mainPRINT_SYSTEM_STATUS                        ( 2 )\r
+\r
+/* GCC specifics. */\r
+#define mainALIGN_TO( x )                              __attribute__((aligned(x)))\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for functions that implement tasks. -----------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* \r
+ * Prototype for the reg test tasks.  Amongst other things, these fill the CPU\r
+ * registers with known values before checking that the registers still contain\r
+ * the expected values.  Each of the two tasks use different values so an error\r
+ * in the context switch mechanism can be caught.  Both reg test tasks execute\r
+ * at the idle priority so will get preempted regularly.\r
+ */\r
+static void prvRegTest1Task( void *pvParameters );\r
+static void prvRegTest2Task( void *pvParameters );\r
+\r
+/*\r
+ * Prototype for the check task.  The check task demonstrates various features\r
+ * of the MPU before entering a loop where it waits for commands to arrive on a\r
+ * queue.\r
+ *\r
+ * The check task will periodically be commanded to print out a status message.\r
+ * If both the reg tests tasks are executing as expected the check task will\r
+ * print "PASS" to the debug port, otherwise it will print 'FAIL'.  Debug port\r
+ * messages can be viewed within the CrossWorks IDE.\r
+ */\r
+static void prvCheckTask( void *pvParameters );\r
+\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Prototypes for other misc functions.  --------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Just configures any clocks and IO necessary.\r
+ */\r
+static void prvSetupHardware( void );\r
+\r
+/*\r
+ * Simply deletes the calling task.  The function is provided only because it\r
+ * is simpler to call from asm code than the normal vTaskDelete() API function.\r
+ * It has the noinline attribute because it is called from asm code.\r
+ */\r
+static void prvDeleteMe( void ) __attribute__((noinline));\r
+\r
+/*\r
+ * Used by both reg test tasks to send messages to the check task.  The message\r
+ * just lets the check task know that the sending is still functioning correctly.\r
+ * If a reg test task detects an error it will delete itself, and in so doing\r
+ * prevent itself from sending any more 'I'm Alive' messages to the check task.\r
+ */\r
+static void prvSendImAlive( xQueueHandle xHandle, unsigned long ulTaskNumber );\r
+\r
+/*\r
+ * The check task is created with access to three memory regions (plus its\r
+ * stack).  Each memory region is configured with different parameters and\r
+ * prvTestMemoryRegions() demonstrates what can and cannot be accessed for each\r
+ * region.  prvTestMemoryRegions() also demonstrates a task that was created\r
+ * as a privileged task settings its own privilege level down to that of a user\r
+ * task.\r
+ */\r
+static void prvTestMemoryRegions( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The handle of the queue used to communicate between tasks and between tasks\r
+and interrupts.  Note that this is a file scope variable that falls outside of\r
+any MPU region.  As such other techniques have to be used to allow the tasks\r
+to gain access to the queue.  See the comments in the tasks themselves for \r
+further information. */\r
+static xQueueHandle xFileScopeCheckQueue = NULL;\r
+\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Data used by the 'check' task. ---------------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Define the constants used to allocate the check task stack.  Note that the\r
+stack size is defined in words, not bytes. */\r
+#define mainCHECK_TASK_STACK_SIZE_WORDS        128\r
+#define mainCHECK_TASK_STACK_ALIGNMENT ( mainCHECK_TASK_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )\r
+\r
+/* Declare the stack that will be used by the check task.  The kernel will\r
+ automatically create an MPU region for the stack.  The stack alignment must \r
+ match its size, so if 128 words are reserved for the stack then it must be \r
+ aligned to ( 128 * 4 ) bytes. */\r
+static portSTACK_TYPE xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] mainALIGN_TO( mainCHECK_TASK_STACK_ALIGNMENT );\r
+\r
+/* Declare three arrays - an MPU region will be created for each array\r
+ using the xTaskParameters structure below.  Note that the arrays allocate \r
+slightly more RAM than is actually assigned to the MPU region.  This is to \r
+permit writes off the end of the array to be detected even when the arrays are \r
+placed in adjacent memory locations (with no gaps between them).  The align \r
+size must be a power of two. */\r
+#define mainREAD_WRITE_ARRAY_SIZE 130\r
+#define mainREAD_WRITE_ALIGN_SIZE 128\r
+char cReadWriteArray[ mainREAD_WRITE_ARRAY_SIZE ] mainALIGN_TO( mainREAD_WRITE_ALIGN_SIZE );\r
+\r
+#define mainREAD_ONLY_ARRAY_SIZE 260\r
+#define mainREAD_ONLY_ALIGN_SIZE 256\r
+char cReadOnlyArray[ mainREAD_ONLY_ARRAY_SIZE ] mainALIGN_TO( mainREAD_ONLY_ALIGN_SIZE );\r
+\r
+#define mainPRIVILEGED_ONLY_ACCESS_ARRAY_SIZE 130\r
+#define mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE 128\r
+char cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] mainALIGN_TO( mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE );\r
+\r
+/* Fill in a xTaskParameters structure to define the check task. */\r
+static const xTaskParameters xCheckTaskParameters =\r
+{\r
+       prvCheckTask,                                                           /* pvTaskCode - the function that implements the task. */\r
+       ( signed char * ) "Check",                                      /* pcName                       */\r
+       mainCHECK_TASK_STACK_SIZE_WORDS,                        /* usStackDepth - defined in words, not bytes. */\r
+       ( void * ) 0x12121212,                                          /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */\r
+       ( tskIDLE_PRIORITY + 1 ) | portPRIVILEGE_BIT,/* uxPriority - this is the highest priority task in the system.  The task is created in privileged mode to demonstrate accessing the privileged only data. */\r
+       xCheckTaskStack,                                                        /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+\r
+       /* xRegions - In this case the xRegions array is used to create MPU regions\r
+       for all three of the arrays declared directly above.  Each MPU region is\r
+       created with different parameters. */\r
+       {                                                                                       \r
+               /* Base address                                 Length                                                                  Parameters */\r
+        { cReadWriteArray,                             mainREAD_WRITE_ALIGN_SIZE,                              portMPU_REGION_READ_WRITE },\r
+        { cReadOnlyArray,                              mainREAD_ONLY_ALIGN_SIZE,                               portMPU_REGION_READ_ONLY },\r
+        { cPrivilegedOnlyAccessArray,  mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE,  portMPU_REGION_PRIVILEGED_READ_WRITE }\r
+       }\r
+};\r
+\r
+/* Three MPU regions are defined for use by the 'check' task when the task is \r
+created.  These are only used to demonstrate the MPU features and are not\r
+actually necessary for the check task to fulfill its primary purpose.  Instead\r
+the MPU regions are replaced with those defined by xAltRegions prior to the \r
+check task receiving any data on the queue or printing any messages to the\r
+debug console.  The region configured by xAltRegions just gives the check task\r
+access to the debug variables that form part of the Rowley library, and are\r
+accessed within the debug_printf() function. */\r
+extern unsigned long dbgCntrlWord_mempoll;\r
+static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =\r
+       {                                                                                       \r
+               /* Base address                                         Length          Parameters */\r
+        { ( void * ) &dbgCntrlWord_mempoll,    32,                     portMPU_REGION_READ_WRITE },\r
+        { 0,                                                           0,                      0 },\r
+        { 0,                                                           0,                      0 }\r
+       };\r
+\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Data used by the 'reg test' tasks. -----------------------*/\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Define the constants used to allocate the reg test task stacks.  Note that\r
+that stack size is defined in words, not bytes. */\r
+#define mainREG_TEST_STACK_SIZE_WORDS  128\r
+#define mainREG_TEST_STACK_ALIGNMENT   ( mainREG_TEST_STACK_SIZE_WORDS * sizeof( portSTACK_TYPE ) )\r
+\r
+/* Declare the stacks that will be used by the reg test tasks.  The kernel will\r
+automatically create an MPU region for the stack.  The stack alignment must \r
+match its size, so if 128 words are reserved for the stack then it must be \r
+aligned to ( 128 * 4 ) bytes. */\r
+static portSTACK_TYPE xRegTest1Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT );\r
+static portSTACK_TYPE xRegTest2Stack[ mainREG_TEST_STACK_SIZE_WORDS ] mainALIGN_TO( mainREG_TEST_STACK_ALIGNMENT );\r
+\r
+/* Fill in a xTaskParameters structure per reg test task to define the tasks. */\r
+static const xTaskParameters xRegTest1Parameters =\r
+{\r
+       prvRegTest1Task,                                                /* pvTaskCode - the function that implements the task. */\r
+       ( signed char * ) "RegTest1",                   /* pcName                       */\r
+       mainREG_TEST_STACK_SIZE_WORDS,                  /* usStackDepth         */\r
+       ( void * ) 0x12345678,                                  /* pvParameters - this value is just to test that the parameter is being passed into the task correctly. */\r
+       tskIDLE_PRIORITY | portPRIVILEGE_BIT,   /* uxPriority - note that this task is created with privileges to demonstrate one method of passing a queue handle into the task. */\r
+       xRegTest1Stack,                                                 /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+       {                                                                               /* xRegions - this task does not use any non-stack data. */\r
+               /* Base address         Length          Parameters */\r
+        { 0x00,                                0x00,                   0x00 },\r
+        { 0x00,                                0x00,                   0x00 },\r
+        { 0x00,                                0x00,                   0x00 }\r
+       }\r
+};\r
+/*-----------------------------------------------------------*/\r
+\r
+static xTaskParameters xRegTest2Parameters =\r
+{\r
+       prvRegTest2Task,                                /* pvTaskCode - the function that implements the task. */\r
+       ( signed char * ) "RegTest2",   /* pcName                       */\r
+       mainREG_TEST_STACK_SIZE_WORDS,  /* usStackDepth         */\r
+       ( void * ) NULL,                                /* pvParameters - this task uses the parameter to pass in a queue handle, but the queue is not created yet. */\r
+       tskIDLE_PRIORITY,                               /* uxPriority           */\r
+       xRegTest2Stack,                                 /* puxStackBuffer - the array to use as the task stack, as declared above. */\r
+       {                                                               /* xRegions - this task does not use any non-stack data. */\r
+               /* Base address         Length          Parameters */\r
+        { 0x00,                                0x00,                   0x00 },\r
+        { 0x00,                                0x00,                   0x00 },\r
+        { 0x00,                                0x00,                   0x00 }\r
+       }\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+int main( void )\r
+{\r
+       prvSetupHardware();\r
+\r
+       /* Create the queue used to pass "I'm alive" messages to the check task. */\r
+       xFileScopeCheckQueue = xQueueCreate( 1, sizeof( unsigned long ) );\r
+\r
+       /* One check task uses the task parameter to receive the queue handle.\r
+       This allows the file scope variable to be accessed from within the task.\r
+       The pvParameters member of xRegTest2Parameters can only be set after the\r
+       queue has been created. */\r
+       xRegTest2Parameters.pvParameters = xFileScopeCheckQueue;\r
+\r
+       /* Create the three test tasks.  Handles to the created tasks are not\r
+       required, hence the second parameter is NULL. */\r
+       xTaskCreateRestricted( &xRegTest1Parameters, NULL );\r
+    xTaskCreateRestricted( &xRegTest2Parameters, NULL );\r
+       xTaskCreateRestricted( &xCheckTaskParameters, NULL );\r
+\r
+       /* Start the scheduler. */\r
+       vTaskStartScheduler();\r
+\r
+       /* Will only get here if there was insufficient memory to create the idle\r
+       task. */\r
+       for( ;; );\r
+       return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckTask( void *pvParameters )\r
+{\r
+/* This task is created in privileged mode so can access the file scope\r
+queue variable.  Take a stack copy of this before the task is set into user\r
+mode.  Once that task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+xQueueHandle xQueue = xFileScopeCheckQueue;\r
+long lMessage;\r
+unsigned long ulStillAliveCounts[ 2 ] = { 0 };\r
+const char *pcStatusMessage = "PASS\r\n";\r
+\r
+       /* Just to remove compiler warning. */\r
+       ( void ) pvParameters;\r
+\r
+       /* Demonstrate how the various memory regions can and can't be accessed. \r
+       The task privilege is set down to user mode within this function. */\r
+       prvTestMemoryRegions();\r
+\r
+       /* Change the memory regions allocated to this task to those initially\r
+       set up for demonstration purposes to those actually required by the task. */\r
+       vTaskAllocateMPURegions( NULL, xAltRegions );\r
+\r
+       /* This loop performs the main function of the task, which is blocking\r
+       on a message queue then processing each message as it arrives. */\r
+       for( ;; )\r
+       {\r
+               /* Wait for the next message to arrive. */\r
+               xQueueReceive( xQueue, &lMessage, portMAX_DELAY );\r
+               \r
+               switch( lMessage )\r
+               {\r
+                       case mainREG_TEST_1_STILL_EXECUTING     :       \r
+                                       /* Message from task 1, so task 1 must still be executing. */\r
+                                       ( ulStillAliveCounts[ 0 ] )++;\r
+                                       break;\r
+\r
+                       case mainREG_TEST_2_STILL_EXECUTING     :                                               \r
+                                       /* Message from task 2, so task 2 must still be executing. */\r
+                                       ( ulStillAliveCounts[ 1 ] )++;\r
+                                       break;\r
+\r
+                       case mainPRINT_SYSTEM_STATUS            :       \r
+                                       /* Message from tick hook, time to print out the system\r
+                                       status.  If messages has stopped arriving from either reg\r
+                                       test task then the status must be set to fail. */\r
+                                       if( ( ulStillAliveCounts[ 0 ] == 0 ) || ( ulStillAliveCounts[ 1 ] == 0 )  )\r
+                                       {\r
+                                               /* One or both of the test tasks are no longer sending \r
+                                               'still alive' messages. */\r
+                                               pcStatusMessage = "FAIL\r\n";\r
+                                       }\r
+\r
+                                       /* Print a pass/fail message to the terminal.  This will be\r
+                                       visible in the CrossWorks IDE. */\r
+                                       debug_printf( pcStatusMessage );\r
+\r
+                                       /* Reset the count of 'still alive' messages. */\r
+                                       memset( ulStillAliveCounts, 0x00, sizeof( ulStillAliveCounts ) );\r
+                                       break;\r
+\r
+               default :\r
+                                       /* Something unexpected happened.  Delete this task so the \r
+                                       error is apparent (no output will be displayed). */\r
+                                       prvDeleteMe();\r
+                                       break;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTestMemoryRegions( void )\r
+{\r
+long l;\r
+char cTemp;\r
+\r
+       /* The check task is created in the privileged mode.  The privileged array \r
+       can be both read from and written to while this task is privileged. */\r
+       cPrivilegedOnlyAccessArray[ 0 ] = 'a';\r
+       if( cPrivilegedOnlyAccessArray[ 0 ] != 'a' )\r
+       {\r
+               /* Something unexpected happened.  Delete this task so the error is\r
+               apparent (no output will be displayed). */\r
+               prvDeleteMe();\r
+       }\r
+\r
+       /* Writing off the end of the RAM allocated to this task will *NOT* cause a\r
+       protection fault because the task is still executing in a privileged mode.  \r
+       Uncomment the following to test. */\r
+       /*cPrivilegedOnlyAccessArray[ mainPRIVILEGED_ONLY_ACCESS_ALIGN_SIZE ] = 'a';*/\r
+\r
+       /* Now set the task into user mode. */\r
+       portSWITCH_TO_USER_MODE();\r
+        \r
+       /* Accessing the privileged only array will now cause a fault.  Uncomment \r
+       the following line to test. */    \r
+       /*cPrivilegedOnlyAccessArray[ 0 ] = 'a';*/\r
+\r
+       /* The read/write array can still be successfully read and written. */\r
+       for( l = 0; l < mainREAD_WRITE_ALIGN_SIZE; l++ )\r
+       {\r
+               cReadWriteArray[ l ] = 'a';\r
+               if( cReadWriteArray[ l ] != 'a' )\r
+               {\r
+                       /* Something unexpected happened.  Delete this task so the error is\r
+                       apparent (no output will be displayed). */\r
+                       prvDeleteMe();\r
+               }\r
+       }\r
+\r
+       /* But attempting to read or write off the end of the RAM allocated to this\r
+       task will cause a fault.  Uncomment either of the following two lines to \r
+       test. */\r
+       /* cReadWriteArray[ 0 ] = cReadWriteArray[ -1 ]; */\r
+       /* cReadWriteArray[ mainREAD_WRITE_ALIGN_SIZE ] = 0x00; */\r
+\r
+       /* The read only array can be successfully read... */\r
+       for( l = 0; l < mainREAD_ONLY_ALIGN_SIZE; l++ )\r
+       {\r
+               cTemp = cReadOnlyArray[ l ];\r
+       }\r
+\r
+       /* ...but cannot be written.  Uncomment the following line to test. */\r
+       /* cReadOnlyArray[ 0 ] = 'a'; */\r
+\r
+       /* Writing to the first and last locations in the stack array should not \r
+       cause a protection fault.  Note that doing this will cause the kernel to\r
+       detect a stack overflow if configCHECK_FOR_STACK_OVERFLOW is greater than \r
+       1. */\r
+    xCheckTaskStack[ 0 ] = 0;\r
+    xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS - 1 ] = 0;\r
+\r
+       /* Writing off either end of the stack array should cause a protection \r
+       fault, uncomment either of the following two lines to test. */\r
+       /* xCheckTaskStack[ -1 ] = 0; */\r
+    /* xCheckTaskStack[ mainCHECK_TASK_STACK_SIZE_WORDS ] = 0; */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTest1Task( void *pvParameters )\r
+{\r
+/* This task is created in privileged mode so can access the file scope\r
+queue variable.  Take a stack copy of this before the task is set into user\r
+mode.  Once that task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+xQueueHandle xQueue = xFileScopeCheckQueue;\r
+\r
+       /* Now the queue handle has been obtained the task can switch to user \r
+       mode.  This is just one method of passing a handle into a protected\r
+       task, the other reg test task uses the task parameter instead. */\r
+    portSWITCH_TO_USER_MODE();\r
+\r
+       /* First check that the parameter value is as expected. */\r
+       if( pvParameters != ( void * ) 0x12345678 )\r
+       {\r
+               /* Error detected.  Delete the task so it stops communicating with\r
+               the check task. */\r
+               prvDeleteMe();\r
+       }\r
+\r
+\r
+       for( ;; )\r
+       {               \r
+               /* This task tests the kernel context switch mechanism by reading and\r
+               writing directly to registers - which requires the test to be written\r
+               in assembly code. */\r
+               __asm volatile \r
+               (       \r
+                       "               MOV     R4, #104                        \n" /* Set registers to a known value.  R0 to R1 are done in the loop below. */\r
+                       "               MOV     R5, #105                        \n"\r
+                       "               MOV     R6, #106                        \n"\r
+                       "               MOV     R8, #108                        \n"\r
+                       "               MOV     R9, #109                        \n"\r
+                       "               MOV     R10, #110                       \n"\r
+                       "               MOV     R11, #111                       \n"\r
+                       "reg1loop:                                              \n"\r
+                       "               MOV     R0, #100                        \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */\r
+                       "               MOV     R1, #101                        \n"\r
+                       "               MOV     R2, #102                        \n"\r
+                       "               MOV R3, #103                    \n"\r
+                       "               MOV     R12, #112                       \n"\r
+                       "               SVC #1                                  \n" /* Yield just to increase test coverage. */\r
+                       "               CMP     R0, #100                        \n" /* Check all the registers still contain their expected values. */\r
+                       "               BNE     prvDeleteMe                     \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */\r
+                       "               CMP     R1, #101                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R2, #102                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP R3, #103                    \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R4, #104                        \n" \r
+                       "               BNE     prvDeleteMe                     \n" \r
+                       "               CMP     R5, #105                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R6, #106                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R8, #108                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R9, #109                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R10, #110                       \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R11, #111                       \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R12, #112                       \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+               );\r
+\r
+               /* Send mainREG_TEST_1_STILL_EXECUTING to the check task to indicate that this \r
+               task is still functioning. */\r
+               prvSendImAlive( xQueue, mainREG_TEST_1_STILL_EXECUTING );\r
+\r
+               /* Go back to check all the register values again. */\r
+               __asm volatile( "               B reg1loop      " );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTest2Task( void *pvParameters )\r
+{\r
+/* The queue handle is passed in as the task parameter.  This is one method of\r
+passing data into a protected task, the other check task uses a different \r
+method. */\r
+xQueueHandle xQueue = ( xQueueHandle ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               /* This task tests the kernel context switch mechanism by reading and\r
+               writing directly to registers - which requires the test to be written\r
+               in assembly code. */\r
+               __asm volatile \r
+               (       \r
+                       "               MOV     R4, #4                          \n" /* Set registers to a known value.  R0 to R1 are done in the loop below. */\r
+                       "               MOV     R5, #5                          \n"\r
+                       "               MOV     R6, #6                          \n"\r
+                       "               MOV     R8, #8                          \n" /* Frame pointer is omitted as it must not be changed. */\r
+                       "               MOV     R9, #9                          \n"\r
+                       "               MOV     R10, 10                         \n"\r
+                       "               MOV     R11, #11                        \n"                                             \r
+                       "reg2loop:                                              \n"\r
+                       "               MOV     R0, #13                         \n" /* Set the scratch registers to known values - done inside the loop as they get clobbered. */\r
+                       "               MOV     R1, #1                          \n"\r
+                       "               MOV     R2, #2                          \n"\r
+                       "               MOV R3, #3                              \n"\r
+                       "               MOV     R12, #12                        \n"\r
+                       "               CMP     R0, #13                         \n" /* Check all the registers still contain their expected values. */\r
+                       "               BNE     prvDeleteMe                     \n" /* Value was not as expected, delete the task so it stops communicating with the check task */\r
+                       "               CMP     R1, #1                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R2, #2                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP R3, #3                              \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R4, #4                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R5, #5                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R6, #6                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R8, #8                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R9, #9                          \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R10, #10                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R11, #11                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+                       "               CMP     R12, #12                        \n"\r
+                       "               BNE     prvDeleteMe                     \n"\r
+               );\r
+\r
+               /* Send mainREG_TEST_2_STILL_EXECUTING to the check task to indicate that this \r
+               task is still functioning. */\r
+               prvSendImAlive( xQueue, mainREG_TEST_2_STILL_EXECUTING );\r
+\r
+               /* Go back to check all the register values again. */\r
+               __asm volatile( "               B reg2loop      " );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDeleteMe( void )\r
+{\r
+       vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendImAlive( xQueueHandle xHandle, unsigned long ulTaskNumber )\r
+{\r
+       if( xHandle != NULL )\r
+       {\r
+               xQueueSend( xHandle, &ulTaskNumber, mainDONT_BLOCK );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupHardware( void )\r
+{\r
+       /* If running on Rev A2 silicon, turn the LDO voltage up to 2.75V.  This is\r
+       a workaround to allow the PLL to operate reliably. */\r
+       if( DEVICE_IS_REVA2 )\r
+       {\r
+               SysCtlLDOSet( SYSCTL_LDO_2_75V );\r
+       }\r
+\r
+       /* Set the clocking to run from the PLL at 50 MHz */\r
+       SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+static unsigned long ulCallCount;\r
+const unsigned long ulCallsBetweenSends = 5000 / portTICK_RATE_MS;\r
+const unsigned long ulMessage = mainPRINT_SYSTEM_STATUS;\r
+portBASE_TYPE xDummy;\r
+\r
+       /* If configUSE_TICK_HOOK is set to 1 then this function will get called\r
+       from each RTOS tick.  It is called from the tick interrupt and therefore\r
+       will be executing in the privileged state. */\r
+\r
+       ulCallCount++;\r
+\r
+       /* Is it time to print out the pass/fail message again? */\r
+       if( ulCallCount >= ulCallsBetweenSends )\r
+       {\r
+               ulCallCount = 0;\r
+\r
+               /* Send a message to the check task to command it to check that all\r
+               the tasks are still running then print out the status. \r
+               \r
+               This is running in an ISR so has to use the "FromISR" version of\r
+               xQueueSend().  Because it is in an ISR it is running with privileges\r
+               so can access xFileScopeCheckQueue directly. */\r
+               xQueueSendFromISR( xFileScopeCheckQueue, &ulMessage, &xDummy );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )\r
+{\r
+       /* If configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2 then this \r
+       function will automatically get called if a task overflows its stack. */\r
+       ( void ) pxTask;\r
+       ( void ) pcTaskName;\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationMallocFailedHook( void )\r
+{\r
+       /* If configUSE_MALLOC_FAILED_HOOK is set to 1 then this function will\r
+       be called automatically if a call to pvPortMalloc() fails.  pvPortMalloc()\r
+       is called automatically when a task, queue or semaphore is created. */\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Just to keep the linker happy. */\r
+void __error__( char *pcFilename, unsigned long ulLine )\r
+{\r
+       ( void ) pcFilename;\r
+       ( void ) ulLine;\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Just to keep the linker happy. */\r
+int uipprintf( const char *fmt, ... )\r
+{\r
+       ( void ) fmt;\r
+       return( 0 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void hard_fault_handler(unsigned int * hardfault_args)\r
+{\r
+unsigned int stacked_r0;\r
+unsigned int stacked_r1;\r
+unsigned int stacked_r2;\r
+unsigned int stacked_r3;\r
+unsigned int stacked_r12;\r
+unsigned int stacked_lr;\r
+unsigned int stacked_pc;\r
+unsigned int stacked_psr;\r
+\r
+       stacked_r0 = ((unsigned long) hardfault_args[0]);\r
+       stacked_r1 = ((unsigned long) hardfault_args[1]);\r
+       stacked_r2 = ((unsigned long) hardfault_args[2]);\r
+       stacked_r3 = ((unsigned long) hardfault_args[3]);\r
+\r
+       stacked_r12 = ((unsigned long) hardfault_args[4]);\r
+       stacked_lr = ((unsigned long) hardfault_args[5]);\r
+       stacked_pc = ((unsigned long) hardfault_args[6]);\r
+       stacked_psr = ((unsigned long) hardfault_args[7]);\r
+\r
+       /* Inspect stacked_pc to locate the offending instruction. */\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void Fault_ISR( void ) __attribute__((naked));\r
+void Fault_ISR( void )\r
+{\r
+       __asm volatile\r
+       (\r
+               " tst lr, #4                                                                            \n"\r
+               " ite eq                                                                                        \n"\r
+               " mrseq r0, msp                                                                         \n"\r
+               " mrsne r0, psp                                                                         \n"\r
+               " ldr r1, [r0, #24]                                                                     \n"\r
+               " ldr r2, handler_address_const                                         \n"\r
+               " bx r2                                                                                         \n"\r
+               " handler_address_const: .word hard_fault_handler       \n"\r
+       );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void MPU_Fault_ISR( void ) __attribute__((naked));\r
+void MPU_Fault_ISR( void )\r
+{\r
+       __asm volatile\r
+       (\r
+               " tst lr, #4                                                                            \n"\r
+               " ite eq                                                                                        \n"\r
+               " mrseq r0, msp                                                                         \n"\r
+               " mrsne r0, psp                                                                         \n"\r
+               " ldr r1, [r0, #24]                                                                     \n"\r
+               " ldr r2, handler_address_const                                         \n"\r
+               " bx r2                                                                                         \n"\r
+               " handler2_address_const: .word hard_fault_handler      \n"\r
+       );\r
+}\r
+/*-----------------------------------------------------------*/
\ No newline at end of file
diff --git a/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/thumb_crt0.s b/Demo/CORTEX_MPU_LM3Sxxxx_Rowley/thumb_crt0.s
new file mode 100644 (file)
index 0000000..ec6d509
--- /dev/null
@@ -0,0 +1,233 @@
+/*****************************************************************************\r
+ * Copyright (c) 2009 Rowley Associates Limited.                             *\r
+ *                                                                           *\r
+ * This file may be distributed under the terms of the License Agreement     *\r
+ * provided with this software.                                              *\r
+ *                                                                           *\r
+ * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE   *\r
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *\r
+ *****************************************************************************/\r
+\r
+/*****************************************************************************\r
+ *                           Preprocessor Definitions\r
+ *                           ------------------------\r
+ * APP_ENTRY_POINT\r
+ *\r
+ *   Defines the application entry point function, if undefined this setting\r
+ *   defaults to "main".\r
+ *\r
+ * USE_PROCESS_STACK\r
+ *\r
+ *   If defined, thread mode will be configured to use the process stack if\r
+ *   the size of the process stack is greater than zero bytes in length.\r
+ *\r
+ * INITIALIZE_STACK\r
+ *\r
+ *   If defined, the contents of the stack will be initialized to a the\r
+ *   value 0xCC.\r
+ *\r
+ * FULL_LIBRARY\r
+ *\r
+ *  If defined then\r
+ *    - argc, argv are setup by the debug_getargs.\r
+ *    - the exit symbol is defined and executes on return from main.\r
+ *    - the exit symbol calls destructors, atexit functions and then debug_exit.\r
+ *\r
+ *  If not defined then\r
+ *    - argc and argv are zero.\r
+ *    - no exit symbol, code loops on return from main.\r
+ *****************************************************************************/\r
+\r
+#ifndef APP_ENTRY_POINT\r
+#define APP_ENTRY_POINT main\r
+#endif\r
+\r
+#ifndef ARGSSPACE\r
+#define ARGSSPACE 128\r
+#endif\r
+\r
+  .global _start\r
+  .syntax unified\r
+  .extern APP_ENTRY_POINT\r
+#ifdef FULL_LIBRARY\r
+  .global exit\r
+#endif\r
+\r
+  .section .init, "ax"\r
+  .code 16\r
+  .align 2\r
+  .thumb_func\r
+\r
+_start:\r
+#ifdef __RAM_BUILD\r
+  ldr r1, =__stack_end__\r
+  mov sp, r1\r
+#endif\r
+#ifdef INITIALIZE_STACK\r
+  mov r2, #0xCC\r
+  ldr r0, =__stack_start__\r
+#ifndef __RAM_BUILD\r
+  mov r1, sp\r
+#endif\r
+  bl memory_set\r
+#endif\r
+\r
+#ifdef USE_PROCESS_STACK\r
+  /* Set up process stack if size > 0 */\r
+  ldr r1, =__stack_process_end__\r
+  ldr r0, =__stack_process_start__\r
+  subs r2, r1, r0\r
+  beq 1f\r
+  msr psp, r1\r
+  mov r2, #2\r
+  msr control, r2\r
+#ifdef INITIALIZE_STACK\r
+  mov r2, #0xCC\r
+  bl memory_set\r
+#endif\r
+1:\r
+#endif\r
+  /* Copy initialised memory sections into RAM (if necessary). */\r
+  ldr r0, =__data_load_start__\r
+  ldr r1, =__data_start__\r
+  ldr r2, =__data_end__\r
+  bl memory_copy\r
+  ldr r0, =__text_load_start__\r
+  ldr r1, =__text_start__\r
+  ldr r2, =__text_end__\r
+  bl memory_copy\r
+  ldr r0, =__fast_load_start__\r
+  ldr r1, =__fast_start__\r
+  ldr r2, =__fast_end__\r
+  bl memory_copy\r
+  ldr r0, =__ctors_load_start__\r
+  ldr r1, =__ctors_start__\r
+  ldr r2, =__ctors_end__\r
+  bl memory_copy\r
+  ldr r0, =__dtors_load_start__\r
+  ldr r1, =__dtors_start__\r
+  ldr r2, =__dtors_end__\r
+  bl memory_copy\r
+  ldr r0, =__rodata_load_start__\r
+  ldr r1, =__rodata_start__\r
+  ldr r2, =__rodata_end__\r
+  bl memory_copy\r
+\r
+  /* Zero the bss. */\r
+  ldr r0, =__bss_start__\r
+  ldr r1, =__bss_end__\r
+  mov r2, #0\r
+  bl memory_set\r
+\r
+  /* Zereo the privileged data. */\r
+  ldr r0, =__privileged_data_start__\r
+  ldr r1, =__privileged_data_end__\r
+  mov r2, #0\r
+  bl memory_set\r
+\r
+  /* Initialise the heap */\r
+  ldr r0, = __heap_start__\r
+  ldr r1, = __heap_end__\r
+  sub r1, r1, r0\r
+  mov r2, #0\r
+  str r2, [r0]\r
+  add r0, r0, #4\r
+  str r1, [r0]\r
+\r
+  /* Call constructors */\r
+  ldr r0, =__ctors_start__\r
+  ldr r1, =__ctors_end__\r
+ctor_loop:\r
+  cmp r0, r1\r
+  beq ctor_end\r
+  ldr r2, [r0]\r
+  add r0, #4\r
+  push {r0-r1}\r
+  blx r2\r
+  pop {r0-r1}\r
+  b ctor_loop\r
+ctor_end:\r
+\r
+  /* Setup initial call frame */\r
+  mov r0, #0\r
+  mov lr, r0\r
+  mov r12, sp\r
+\r
+start:\r
+  /* Jump to application entry point */\r
+#ifdef FULL_LIBRARY\r
+  mov r0, #ARGSSPACE\r
+  ldr r1, =args\r
+  ldr r2, =debug_getargs\r
+  blx r2\r
+  ldr r1, =args\r
+#else\r
+  mov r0, #0\r
+  mov r1, #0\r
+#endif\r
+  ldr r2, =APP_ENTRY_POINT\r
+  blx r2\r
+\r
+#ifdef FULL_LIBRARY\r
+  .thumb_func\r
+exit:\r
+  mov r5, r0 // save the exit parameter/return result\r
+\r
+  /* Call destructors */\r
+  ldr r0, =__dtors_start__\r
+  ldr r1, =__dtors_end__\r
+dtor_loop:\r
+  cmp r0, r1\r
+  beq dtor_end\r
+  ldr r2, [r0]\r
+  add r0, #4\r
+  push {r0-r1}\r
+  blx r2\r
+  pop {r0-r1}\r
+  b dtor_loop\r
+dtor_end:\r
+\r
+  /* Call atexit functions */\r
+  ldr r2, =_execute_at_exit_fns\r
+  blx r2\r
+\r
+  /* Call debug_exit with return result/exit parameter */\r
+  mov r0, r5\r
+  ldr r2, =debug_exit\r
+  blx r2\r
+#endif\r
+\r
+  /* Returned from application entry point, loop forever. */\r
+exit_loop:\r
+  b exit_loop\r
+\r
+memory_copy:\r
+  cmp r0, r1\r
+  beq 2f\r
+  subs r2, r2, r1\r
+  beq 2f\r
+1:\r
+  ldrb r3, [r0]\r
+  add r0, r0, #1\r
+  strb r3, [r1]\r
+  add r1, r1, #1\r
+  subs r2, r2, #1\r
+  bne 1b\r
+2:\r
+  bx lr\r
+\r
+memory_set:\r
+  cmp r0, r1\r
+  beq 1f\r
+  strb r2, [r0]\r
+  add r0, r0, #1\r
+  b memory_set\r
+1:\r
+  bx lr\r
+\r
+#ifdef FULL_LIBRARY\r
+  .bss\r
+args:\r
+  .space ARGSSPACE\r
+#endif\r
+\r