]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_MPU_Simulator_Keil_GCC/Keil_Specific/RegTest.c
Increase the test coverage of the GCC MPU demo that runs in the Keil simulator.
[freertos] / FreeRTOS / Demo / CORTEX_MPU_Simulator_Keil_GCC / Keil_Specific / RegTest.c
diff --git a/FreeRTOS/Demo/CORTEX_MPU_Simulator_Keil_GCC/Keil_Specific/RegTest.c b/FreeRTOS/Demo/CORTEX_MPU_Simulator_Keil_GCC/Keil_Specific/RegTest.c
new file mode 100644 (file)
index 0000000..e2b8cfa
--- /dev/null
@@ -0,0 +1,703 @@
+/*\r
+    FreeRTOS V9.0.0rc2 - Copyright (C) 2015 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\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
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "queue.h"\r
+#include "task.h"\r
+\r
+/*\r
+ * "Reg test" tasks - These fill the registers with known values, then check\r
+ * that each register maintains its expected value for the lifetime of the\r
+ * task.  Each task uses a different set of values.  The reg test tasks execute\r
+ * with a very low priority, so get preempted very frequently.  A register\r
+ * containing an unexpected value is indicative of an error in the context\r
+ * switching mechanism.\r
+ */\r
+\r
+void vRegTest1Implementation( void *pvParameters );\r
+void vRegTest2Implementation( void *pvParameters );\r
+void vRegTest3Implementation( void );\r
+void vRegTest4Implementation( void );\r
+\r
+/*\r
+ * Used as an easy way of deleting a task from inline assembly.\r
+ */\r
+extern void vMainDeleteMe( void ) __attribute__((noinline));\r
+\r
+/*\r
+ * Used by the first two reg test tasks and a software timer callback function\r
+ * to send messages to the check task.  The message just lets the check task\r
+ * know that the tasks and timer are still functioning correctly.  If a reg test\r
+ * task detects an error it will delete itself, and in so doing prevent itself\r
+ * from sending any more 'I'm Alive' messages to the check task.\r
+ */\r
+extern void vMainSendImAlive( QueueHandle_t xHandle, uint32_t ulTaskNumber );\r
+\r
+/* The queue used to send a message to the check task. */\r
+extern QueueHandle_t xGlobalScopeCheckQueue;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vRegTest1Implementation( 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 this task is in user mode the file scope queue variable will no\r
+longer be accessible but the stack copy will. */\r
+QueueHandle_t xQueue = xGlobalScopeCheckQueue;\r
+const TickType_t xDelayTime = pdMS_TO_TICKS( 100UL );\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 * ) configREG_TEST_TASK_1_PARAMETER )\r
+       {\r
+               /* Error detected.  Delete the task so it stops communicating with\r
+               the check task. */\r
+               vMainDeleteMe();\r
+       }\r
+\r
+       for( ;; )\r
+       {\r
+               #if defined ( __GNUC__ )\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     vMainDeleteMe           \n" /* Value was not as expected, delete the task so it stops communicating with the check task. */\r
+                               "               CMP     R1, #101                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R2, #102                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP R3, #103                    \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R4, #104                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R5, #105                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R6, #106                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R8, #108                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R9, #109                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R10, #110                       \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R11, #111                       \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R12, #112                       \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"\r
+                       );\r
+               }\r
+               #endif /* __GNUC__ */\r
+\r
+               /* Send configREG_TEST_1_STILL_EXECUTING to the check task to indicate that this\r
+               task is still functioning. */\r
+               vMainSendImAlive( xQueue, configREG_TEST_1_STILL_EXECUTING );\r
+               vTaskDelay( xDelayTime );\r
+\r
+               #if defined ( __GNUC__ )\r
+               {\r
+                       /* Go back to check all the register values again. */\r
+                       __asm volatile( "               B reg1loop      " );\r
+               }\r
+               #endif /* __GNUC__ */\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vRegTest2Implementation( 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 reg test task uses a different\r
+method. */\r
+QueueHandle_t xQueue = ( QueueHandle_t ) pvParameters;\r
+const TickType_t xDelayTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       for( ;; )\r
+       {\r
+               #if defined ( __GNUC__ )\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     vMainDeleteMe           \n" /* Value was not as expected, delete the task so it stops communicating with the check task */\r
+                               "               CMP     R1, #1                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R2, #2                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP R3, #3                              \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R4, #4                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R5, #5                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R6, #6                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R8, #8                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R9, #9                          \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R10, #10                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R11, #11                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               "               CMP     R12, #12                        \n"\r
+                               "               BNE     vMainDeleteMe           \n"\r
+                               :::"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r8", "r9", "r10", "r11", "r12"\r
+                       );\r
+               }\r
+               #endif /* __GNUC__ */\r
+\r
+               /* Send configREG_TEST_2_STILL_EXECUTING to the check task to indicate\r
+               that this task is still functioning. */\r
+               vMainSendImAlive( xQueue, configREG_TEST_2_STILL_EXECUTING );\r
+               vTaskDelay( xDelayTime );\r
+\r
+               #if defined ( __GNUC__ )\r
+               {\r
+                       /* Go back to check all the register values again. */\r
+                       __asm volatile( "               B reg2loop      " );\r
+               }\r
+               #endif /* __GNUC__ */\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+__asm void vRegTest3Implementation( void )\r
+{\r
+       extern pulRegTest3LoopCounter\r
+\r
+       PRESERVE8\r
+\r
+       /* Fill the core registers with known values. */\r
+       mov     r0, #100\r
+       mov     r1, #101\r
+       mov     r2, #102\r
+       mov     r3, #103\r
+       mov     r4, #104\r
+       mov     r5, #105\r
+       mov     r6, #106\r
+       mov     r7, #107\r
+       mov     r8, #108\r
+       mov     r9, #109\r
+       mov     r10, #110\r
+       mov     r11, #111\r
+       mov     r12, #112\r
+\r
+       /* Fill the VFP registers with known values. */\r
+       vmov    d0, r0, r1\r
+       vmov    d1, r2, r3\r
+       vmov    d2, r4, r5\r
+       vmov    d3, r6, r7\r
+       vmov    d4, r8, r9\r
+       vmov    d5, r10, r11\r
+       vmov    d6, r0, r1\r
+       vmov    d7, r2, r3\r
+       vmov    d8, r4, r5\r
+       vmov    d9, r6, r7\r
+       vmov    d10, r8, r9\r
+       vmov    d11, r10, r11\r
+       vmov    d12, r0, r1\r
+       vmov    d13, r2, r3\r
+       vmov    d14, r4, r5\r
+       vmov    d15, r6, r7\r
+\r
+reg1_loop\r
+\r
+       /* Check all the VFP registers still contain the values set above.\r
+       First save registers that are clobbered by the test. */\r
+       push { r0-r1 }\r
+\r
+       vmov    r0, r1, d0\r
+       cmp     r0, #100\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #101\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d1\r
+       cmp     r0, #102\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #103\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d2\r
+       cmp     r0, #104\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #105\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d3\r
+       cmp     r0, #106\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #107\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d4\r
+       cmp     r0, #108\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #109\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d5\r
+       cmp     r0, #110\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #111\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d6\r
+       cmp     r0, #100\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #101\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d7\r
+       cmp     r0, #102\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #103\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d8\r
+       cmp     r0, #104\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #105\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d9\r
+       cmp     r0, #106\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #107\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d10\r
+       cmp     r0, #108\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #109\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d11\r
+       cmp     r0, #110\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #111\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d12\r
+       cmp     r0, #100\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #101\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d13\r
+       cmp     r0, #102\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #103\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d14\r
+       cmp     r0, #104\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #105\r
+       bne     reg1_error_loopf\r
+       vmov    r0, r1, d15\r
+       cmp     r0, #106\r
+       bne     reg1_error_loopf\r
+       cmp     r1, #107\r
+       bne     reg1_error_loopf\r
+\r
+       /* Restore the registers that were clobbered by the test. */\r
+       pop     {r0-r1}\r
+\r
+       /* VFP register test passed.  Jump to the core register test. */\r
+       b               reg1_loopf_pass\r
+\r
+reg1_error_loopf\r
+       /* If this line is hit then a VFP register value was found to be incorrect. */\r
+       b reg1_error_loopf\r
+\r
+reg1_loopf_pass\r
+\r
+       cmp     r0, #100\r
+       bne     reg1_error_loop\r
+       cmp     r1, #101\r
+       bne     reg1_error_loop\r
+       cmp     r2, #102\r
+       bne     reg1_error_loop\r
+       cmp     r3, #103\r
+       bne     reg1_error_loop\r
+       cmp     r4, #104\r
+       bne     reg1_error_loop\r
+       cmp     r5, #105\r
+       bne     reg1_error_loop\r
+       cmp     r6, #106\r
+       bne     reg1_error_loop\r
+       cmp     r7, #107\r
+       bne     reg1_error_loop\r
+       cmp     r8, #108\r
+       bne     reg1_error_loop\r
+       cmp     r9, #109\r
+       bne     reg1_error_loop\r
+       cmp     r10, #110\r
+       bne     reg1_error_loop\r
+       cmp     r11, #111\r
+       bne     reg1_error_loop\r
+       cmp     r12, #112\r
+       bne     reg1_error_loop\r
+\r
+       /* Everything passed, increment the loop counter. */\r
+       push    { r0-r1 }\r
+       ldr     r0, =pulRegTest3LoopCounter\r
+       ldr     r0, [r0]\r
+       ldr     r1, [r0]\r
+       adds    r1, r1, #1\r
+       str     r1, [r0]\r
+       pop     { r0-r1 }\r
+\r
+       /* Start again. */\r
+       b               reg1_loop\r
+\r
+reg1_error_loop\r
+       /* If this line is hit then there was an error in a core register value.\r
+       The loop ensures the loop counter stops incrementing. */\r
+       b       reg1_error_loop\r
+       nop\r
+       nop\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+__asm void vRegTest4Implementation( void )\r
+{\r
+       extern pulRegTest4LoopCounter;\r
+\r
+       PRESERVE8\r
+\r
+       /* Set all the core registers to known values. */\r
+       mov     r0, #-1\r
+       mov     r1, #1\r
+       mov     r2, #2\r
+       mov     r3, #3\r
+       mov     r4, #4\r
+       mov     r5, #5\r
+       mov     r6, #6\r
+       mov     r7, #7\r
+       mov     r8, #8\r
+       mov     r9, #9\r
+       mov     r10, #10\r
+       mov     r11, #11\r
+       mov     r12, #12\r
+\r
+       /* Set all the VFP to known values. */\r
+       vmov    d0, r0, r1\r
+       vmov    d1, r2, r3\r
+       vmov    d2, r4, r5\r
+       vmov    d3, r6, r7\r
+       vmov    d4, r8, r9\r
+       vmov    d5, r10, r11\r
+       vmov    d6, r0, r1\r
+       vmov    d7, r2, r3\r
+       vmov    d8, r4, r5\r
+       vmov    d9, r6, r7\r
+       vmov    d10, r8, r9\r
+       vmov    d11, r10, r11\r
+       vmov    d12, r0, r1\r
+       vmov    d13, r2, r3\r
+       vmov    d14, r4, r5\r
+       vmov    d15, r6, r7\r
+\r
+reg2_loop\r
+\r
+       /* Check all the VFP registers still contain the values set above.\r
+       First save registers that are clobbered by the test. */\r
+       push { r0-r1 }\r
+\r
+       vmov    r0, r1, d0\r
+       cmp     r0, #-1\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #1\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d1\r
+       cmp     r0, #2\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #3\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d2\r
+       cmp     r0, #4\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #5\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d3\r
+       cmp     r0, #6\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #7\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d4\r
+       cmp     r0, #8\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #9\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d5\r
+       cmp     r0, #10\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #11\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d6\r
+       cmp     r0, #-1\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #1\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d7\r
+       cmp     r0, #2\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #3\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d8\r
+       cmp     r0, #4\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #5\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d9\r
+       cmp     r0, #6\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #7\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d10\r
+       cmp     r0, #8\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #9\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d11\r
+       cmp     r0, #10\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #11\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d12\r
+       cmp     r0, #-1\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #1\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d13\r
+       cmp     r0, #2\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #3\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d14\r
+       cmp     r0, #4\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #5\r
+       bne     reg2_error_loopf\r
+       vmov    r0, r1, d15\r
+       cmp     r0, #6\r
+       bne     reg2_error_loopf\r
+       cmp     r1, #7\r
+       bne     reg2_error_loopf\r
+\r
+       /* Restore the registers that were clobbered by the test. */\r
+       pop     {r0-r1}\r
+\r
+       /* VFP register test passed.  Jump to the core register test. */\r
+       b               reg2_loopf_pass\r
+\r
+reg2_error_loopf\r
+       /* If this line is hit then a VFP register value was found to be\r
+       incorrect. */\r
+       b reg2_error_loopf\r
+\r
+reg2_loopf_pass\r
+\r
+       cmp     r0, #-1\r
+       bne     reg2_error_loop\r
+       cmp     r1, #1\r
+       bne     reg2_error_loop\r
+       cmp     r2, #2\r
+       bne     reg2_error_loop\r
+       cmp     r3, #3\r
+       bne     reg2_error_loop\r
+       cmp     r4, #4\r
+       bne     reg2_error_loop\r
+       cmp     r5, #5\r
+       bne     reg2_error_loop\r
+       cmp     r6, #6\r
+       bne     reg2_error_loop\r
+       cmp     r7, #7\r
+       bne     reg2_error_loop\r
+       cmp     r8, #8\r
+       bne     reg2_error_loop\r
+       cmp     r9, #9\r
+       bne     reg2_error_loop\r
+       cmp     r10, #10\r
+       bne     reg2_error_loop\r
+       cmp     r11, #11\r
+       bne     reg2_error_loop\r
+       cmp     r12, #12\r
+       bne     reg2_error_loop\r
+\r
+       /* Increment the loop counter so the check task knows this task is\r
+       still running. */\r
+       push    { r0-r1 }\r
+       ldr     r0, =pulRegTest4LoopCounter\r
+       ldr     r0, [r0]\r
+       ldr     r1, [r0]\r
+       adds    r1, r1, #1\r
+       str     r1, [r0]\r
+       pop { r0-r1 }\r
+\r
+       /* Yield to increase test coverage. */\r
+       SVC #1\r
+\r
+       /* Start again. */\r
+       b reg2_loop\r
+\r
+reg2_error_loop\r
+       /* If this line is hit then there was an error in a core register value.\r
+       This loop ensures the loop counter variable stops incrementing. */\r
+       b reg2_error_loop\r
+       nop\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Fault handlers are here for convenience as they use compiler specific syntax\r
+and this file is specific to the Keil compiler. */\r
+void hard_fault_handler( uint32_t * hardfault_args )\r
+{\r
+volatile uint32_t stacked_r0;\r
+volatile uint32_t stacked_r1;\r
+volatile uint32_t stacked_r2;\r
+volatile uint32_t stacked_r3;\r
+volatile uint32_t stacked_r12;\r
+volatile uint32_t stacked_lr;\r
+volatile uint32_t stacked_pc;\r
+volatile uint32_t stacked_psr;\r
+\r
+       stacked_r0 = ((uint32_t) hardfault_args[ 0 ]);\r
+       stacked_r1 = ((uint32_t) hardfault_args[ 1 ]);\r
+       stacked_r2 = ((uint32_t) hardfault_args[ 2 ]);\r
+       stacked_r3 = ((uint32_t) hardfault_args[ 3 ]);\r
+\r
+       stacked_r12 = ((uint32_t) hardfault_args[ 4 ]);\r
+       stacked_lr = ((uint32_t) hardfault_args[ 5 ]);\r
+       stacked_pc = ((uint32_t) hardfault_args[ 6 ]);\r
+       stacked_psr = ((uint32_t) hardfault_args[ 7 ]);\r
+\r
+       /* Inspect stacked_pc to locate the offending instruction. */\r
+       for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void HardFault_Handler( void );\r
+__asm void HardFault_Handler( void )\r
+{\r
+       extern hard_fault_handler\r
+\r
+       tst lr, #4\r
+       ite eq\r
+       mrseq r0, msp\r
+       mrsne r0, psp\r
+       ldr r1, [r0, #24]\r
+       ldr r2, hard_fault_handler\r
+       bx r2\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void MemManage_Handler( void );\r
+__asm void MemManage_Handler( void )\r
+{\r
+       extern hard_fault_handler\r
+\r
+       tst lr, #4\r
+       ite eq\r
+       mrseq r0, msp\r
+       mrsne r0, psp\r
+       ldr r1, [r0, #24]\r
+       ldr r2, hard_fault_handler\r
+       bx r2\r
+}\r
+/*-----------------------------------------------------------*/\r