#include "QueueSet.h"\r
#include "recmutex.h"\r
#include "EventGroupsDemo.h"\r
+#include "TaskNotify.h"\r
+#include "IntSemTest.h"\r
+#include "TimerDemo.h"\r
+#include "IntQueue.h"\r
\r
/* The period after which the check timer will expire, in ms, provided no errors\r
have been reported by any of the standard demo tasks. ms are converted to the\r
/* UDP command server and echo task parameters. */\r
#define mainUDP_CLI_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
#define mainUDP_CLI_PORT_NUMBER ( 5001UL )\r
-#define mainUDP_CLI_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2U )\r
+#define mainUDP_CLI_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE + 90 )\r
#define mainECHO_CLIENT_STACK_SIZE ( configMINIMAL_STACK_SIZE + 30 )\r
\r
/* Set to 1 to include the UDP echo client tasks in the build. The echo clients\r
FreeRTOSConfig.h. */\r
#define mainINCLUDE_ECHO_CLIENT_TASKS 1\r
\r
+/* Used by the standard demo timer tasks. */\r
+#define mainTIMER_TEST_PERIOD ( 50 )\r
+\r
/*-----------------------------------------------------------*/\r
\r
/*\r
*/\r
extern void vInitialiseLCD( void );\r
\r
+/*\r
+ * Register check tasks, and the tasks used to write over and check the contents\r
+ * of the FPU registers, as described at the top of this file. The nature of\r
+ * these files necessitates that they are written in an assembly file.\r
+ */\r
+static void prvRegTest1Task( void *pvParameters ) __attribute__((naked));\r
+static void prvRegTest2Task( void *pvParameters ) __attribute__((naked));\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* The default IP and MAC address used by the demo. The address configuration\r
Note each node on a network must have a unique MAC address. */\r
const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };\r
\r
+/* The following two variables are used to communicate the status of the\r
+register check tasks to the check software timer. If the variables keep\r
+incrementing, then the register check tasks has not discovered any errors. If\r
+a variable stops incrementing, then an error has been found. */\r
+volatile unsigned long ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;\r
+\r
/*-----------------------------------------------------------*/\r
\r
int main_full( void )\r
{\r
-TimerHandle_t xTimer = NULL;\r
-\r
/* Usage instructions on http://www.FreeRTOS.org/Atmel_SAM4E_RTOS_Demo.html */\r
\r
/* Initialise the LCD and output a bitmap. The IP address will also be\r
has completed if DHCP is used). */\r
FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );\r
\r
- /* Create all the other standard demo tasks. */\r
- vStartLEDFlashTimers( mainNUM_FLASH_TIMER_LEDS );\r
+ /* Create all the other standard demo tasks. */ \r
vCreateBlockTimeTasks();\r
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
vStartQueueSetTasks();\r
vStartRecursiveMutexTasks();\r
vStartEventGroupTasks();\r
+ vStartTaskNotifyTask();\r
+ vStartInterruptSemaphoreTasks();\r
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
+ vStartInterruptQueueTasks();\r
\r
- /* Create the software timer that performs the 'check' functionality, as\r
- described at the top of this file. */\r
- xTimer = xTimerCreate( "CheckTimer", /* A text name, purely to help debugging. */\r
- ( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */\r
- pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */\r
- ( void * ) 0, /* The ID is not used, so can be set to anything. */\r
- prvCheckTimerCallback ); /* The callback function that inspects the status of all the other tasks. */\r
-\r
- if( xTimer != NULL )\r
- {\r
- xTimerStart( xTimer, mainDONT_BLOCK );\r
- }\r
+ /* Create the register check tasks, as described at the top of this\r
+ file */\r
+ xTaskCreate( prvRegTest1Task, "Reg1", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( prvRegTest2Task, "Reg2", configMINIMAL_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, NULL );\r
\r
/* Start the scheduler itself. */\r
vTaskStartScheduler();\r
static void prvCheckTimerCallback( TimerHandle_t xTimer )\r
{\r
static long lChangedTimerPeriodAlready = pdFALSE;\r
+static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;\r
unsigned long ulErrorOccurred = pdFALSE;\r
\r
/* Avoid compiler warnings. */\r
{\r
ulErrorOccurred |= ( 0x01UL << 13UL );\r
}\r
+ else if( xAreTaskNotificationTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorOccurred |= ( 0x01UL << 14UL );\r
+ }\r
+ else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorOccurred |= ( 0x01UL << 15UL );\r
+ }\r
+ else if( xAreTimerDemoTasksStillRunning( mainCHECK_TIMER_PERIOD_MS ) != pdTRUE )\r
+ {\r
+ ulErrorOccurred |= 1UL << 16UL;\r
+ } \r
+ else if( xAreIntQueueTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorOccurred |= 1UL << 17UL;\r
+ }\r
+\r
+ \r
+ /* Check that the register test 1 task is still running. */\r
+ if( ulLastRegTest1Value == ulRegTest1LoopCounter )\r
+ {\r
+ ulErrorOccurred |= 1UL << 18UL;\r
+ }\r
+ ulLastRegTest1Value = ulRegTest1LoopCounter;\r
+\r
+ /* Check that the register test 2 task is still running. */\r
+ if( ulLastRegTest2Value == ulRegTest2LoopCounter )\r
+ {\r
+ ulErrorOccurred |= 1UL << 19UL;\r
+ }\r
+ ulLastRegTest2Value = ulRegTest2LoopCounter;\r
\r
if( ulErrorOccurred != pdFALSE )\r
{\r
\r
void vFullDemoIdleHook( void )\r
{\r
+static TimerHandle_t xCheckTimer = NULL;\r
+ \r
+ if( xCheckTimer == NULL )\r
+ {\r
+ /* Create the software timer that performs the 'check' \r
+ functionality, in the full demo. This is not done before the\r
+ scheduler is started as to do so would prevent the standard demo\r
+ timer tasks from passing their tests (they expect the timer\r
+ command queue to be empty. */\r
+ xCheckTimer = xTimerCreate( "CheckTimer", /* A text name, purely to help debugging. */\r
+ ( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */\r
+ pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */\r
+ ( void * ) 0, /* The ID is not used, so can be set to anything. */\r
+ prvCheckTimerCallback ); /* The callback function that inspects the status of all the other tasks. */\r
+\r
+ if( xCheckTimer != NULL )\r
+ {\r
+ xTimerStart( xCheckTimer, mainDONT_BLOCK );\r
+ }\r
+ \r
+ /* Also start some timers that just flash LEDs. */\r
+ vStartLEDFlashTimers( mainNUM_FLASH_TIMER_LEDS );\r
+ }\r
+ \r
/* If the file system is only going to be accessed from one task then\r
F_FS_THREAD_AWARE can be set to 0 and the set of example files is created\r
before the RTOS scheduler is started. If the file system is going to be\r
\r
/* Call the event group ISR tests. */\r
vPeriodicEventGroupsProcessing();\r
+ \r
+ /* Exercise task notifications from interrupts. */\r
+ xNotifyTaskFromISR();\r
+ \r
+ /* Use mutexes from interrupts. */\r
+ vInterruptSemaphorePeriodicTest();\r
+ \r
+ /* Use timers from an interrupt. */\r
+ vTimerPeriodicISRTests();\r
}\r
/*-----------------------------------------------------------*/\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
+/* This is a naked function. */\r
+static void prvRegTest1Task( void *pvParameters )\r
+{\r
+ __asm volatile\r
+ (\r
+ " /* Fill the core registers with known values. */ \n"\r
+ " mov r0, #100 \n"\r
+ " mov r1, #101 \n"\r
+ " mov r2, #102 \n"\r
+ " mov r3, #103 \n"\r
+ " mov r4, #104 \n"\r
+ " mov r5, #105 \n"\r
+ " mov r6, #106 \n"\r
+ " mov r7, #107 \n"\r
+ " mov r8, #108 \n"\r
+ " mov r9, #109 \n"\r
+ " mov r10, #110 \n"\r
+ " mov r11, #111 \n"\r
+ " mov r12, #112 \n"\r
+ " \n"\r
+ " /* Fill the VFP registers with known values. */ \n"\r
+ " vmov d0, r0, r1 \n"\r
+ " vmov d1, r2, r3 \n"\r
+ " vmov d2, r4, r5 \n"\r
+ " vmov d3, r6, r7 \n"\r
+ " vmov d4, r8, r9 \n"\r
+ " vmov d5, r10, r11 \n"\r
+ " vmov d6, r0, r1 \n"\r
+ " vmov d7, r2, r3 \n"\r
+ " vmov d8, r4, r5 \n"\r
+ " vmov d9, r6, r7 \n"\r
+ " vmov d10, r8, r9 \n"\r
+ " vmov d11, r10, r11 \n"\r
+ " vmov d12, r0, r1 \n"\r
+ " vmov d13, r2, r3 \n"\r
+ " vmov d14, r4, r5 \n"\r
+ " vmov d15, r6, r7 \n"\r
+ " \n"\r
+ "reg1_loop: \n"\r
+ " /* Check all the VFP registers still contain the values set above.\n"\r
+ " First save registers that are clobbered by the test. */ \n"\r
+ " push { r0-r1 } \n"\r
+ " \n"\r
+ " vmov r0, r1, d0 \n"\r
+ " cmp r0, #100 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #101 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d1 \n"\r
+ " cmp r0, #102 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #103 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d2 \n"\r
+ " cmp r0, #104 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #105 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d3 \n"\r
+ " cmp r0, #106 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #107 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d4 \n"\r
+ " cmp r0, #108 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #109 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d5 \n"\r
+ " cmp r0, #110 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #111 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d6 \n"\r
+ " cmp r0, #100 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #101 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d7 \n"\r
+ " cmp r0, #102 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #103 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d8 \n"\r
+ " cmp r0, #104 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #105 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d9 \n"\r
+ " cmp r0, #106 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #107 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d10 \n"\r
+ " cmp r0, #108 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #109 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d11 \n"\r
+ " cmp r0, #110 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #111 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d12 \n"\r
+ " cmp r0, #100 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #101 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d13 \n"\r
+ " cmp r0, #102 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #103 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d14 \n"\r
+ " cmp r0, #104 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #105 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " vmov r0, r1, d15 \n"\r
+ " cmp r0, #106 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " cmp r1, #107 \n"\r
+ " bne reg1_error_loopf \n"\r
+ " \n"\r
+ " /* Restore the registers that were clobbered by the test. */\n"\r
+ " pop {r0-r1} \n"\r
+ " \n"\r
+ " /* VFP register test passed. Jump to the core register test. */\n"\r
+ " b reg1_loopf_pass \n"\r
+ " \n"\r
+ "reg1_error_loopf: \n"\r
+ " /* If this line is hit then a VFP register value was found to be\n"\r
+ " incorrect. */ \n"\r
+ " b reg1_error_loopf \n"\r
+ " \n"\r
+ "reg1_loopf_pass: \n"\r
+ " \n"\r
+ " cmp r0, #100 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r1, #101 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r2, #102 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r3, #103 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r4, #104 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r5, #105 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r6, #106 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r7, #107 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r8, #108 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r9, #109 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r10, #110 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r11, #111 \n"\r
+ " bne reg1_error_loop \n"\r
+ " cmp r12, #112 \n"\r
+ " bne reg1_error_loop \n"\r
+ " \n"\r
+ " /* Everything passed, increment the loop counter. */ \n"\r
+ " push { r0-r1 } \n"\r
+ " ldr r0, =ulRegTest1LoopCounter \n"\r
+ " ldr r1, [r0] \n"\r
+ " adds r1, r1, #1 \n"\r
+ " str r1, [r0] \n"\r
+ " pop { r0-r1 } \n"\r
+ " \n"\r
+ " /* Start again. */ \n"\r
+ " b reg1_loop \n"\r
+ " \n"\r
+ "reg1_error_loop: \n"\r
+ " /* If this line is hit then there was an error in a core register value.\n"\r
+ " The loop ensures the loop counter stops incrementing. */\n"\r
+ " b reg1_error_loop \n"\r
+ " nop "\r
+ );\r
+ \r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This is a naked function. */\r
+static void prvRegTest2Task( void *pvParameters )\r
+{\r
+ __asm volatile\r
+ (\r
+ " /* Set all the core registers to known values. */ \n"\r
+ " mov r0, #-1 \n"\r
+ " mov r1, #1 \n"\r
+ " mov r2, #2 \n"\r
+ " mov r3, #3 \n"\r
+ " mov r4, #4 \n"\r
+ " mov r5, #5 \n"\r
+ " mov r6, #6 \n"\r
+ " mov r7, #7 \n"\r
+ " mov r8, #8 \n"\r
+ " mov r9, #9 \n"\r
+ " mov r10, #10 \n"\r
+ " mov r11, #11 \n"\r
+ " mov r12, #12 \n"\r
+ " \n"\r
+ " /* Set all the VFP to known values. */ \n"\r
+ " vmov d0, r0, r1 \n"\r
+ " vmov d1, r2, r3 \n"\r
+ " vmov d2, r4, r5 \n"\r
+ " vmov d3, r6, r7 \n"\r
+ " vmov d4, r8, r9 \n"\r
+ " vmov d5, r10, r11 \n"\r
+ " vmov d6, r0, r1 \n"\r
+ " vmov d7, r2, r3 \n"\r
+ " vmov d8, r4, r5 \n"\r
+ " vmov d9, r6, r7 \n"\r
+ " vmov d10, r8, r9 \n"\r
+ " vmov d11, r10, r11 \n"\r
+ " vmov d12, r0, r1 \n"\r
+ " vmov d13, r2, r3 \n"\r
+ " vmov d14, r4, r5 \n"\r
+ " vmov d15, r6, r7 \n"\r
+ " \n"\r
+ "reg2_loop: \n"\r
+ " \n"\r
+ " /* Check all the VFP registers still contain the values set above.\n"\r
+ " First save registers that are clobbered by the test. */ \n"\r
+ " push { r0-r1 } \n"\r
+ " \n"\r
+ " vmov r0, r1, d0 \n"\r
+ " cmp r0, #-1 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #1 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d1 \n"\r
+ " cmp r0, #2 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #3 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d2 \n"\r
+ " cmp r0, #4 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #5 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d3 \n"\r
+ " cmp r0, #6 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #7 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d4 \n"\r
+ " cmp r0, #8 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #9 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d5 \n"\r
+ " cmp r0, #10 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #11 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d6 \n"\r
+ " cmp r0, #-1 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #1 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d7 \n"\r
+ " cmp r0, #2 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #3 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d8 \n"\r
+ " cmp r0, #4 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #5 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d9 \n"\r
+ " cmp r0, #6 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #7 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d10 \n"\r
+ " cmp r0, #8 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #9 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d11 \n"\r
+ " cmp r0, #10 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #11 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d12 \n"\r
+ " cmp r0, #-1 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #1 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d13 \n"\r
+ " cmp r0, #2 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #3 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d14 \n"\r
+ " cmp r0, #4 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #5 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " vmov r0, r1, d15 \n"\r
+ " cmp r0, #6 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " cmp r1, #7 \n"\r
+ " bne reg2_error_loopf \n"\r
+ " \n"\r
+ " /* Restore the registers that were clobbered by the test. */\n"\r
+ " pop {r0-r1} \n"\r
+ " \n"\r
+ " /* VFP register test passed. Jump to the core register test. */\n"\r
+ " b reg2_loopf_pass \n"\r
+ " \n"\r
+ "reg2_error_loopf: \n"\r
+ " /* If this line is hit then a VFP register value was found to be\n"\r
+ " incorrect. */ \n"\r
+ " b reg2_error_loopf \n"\r
+ " \n"\r
+ "reg2_loopf_pass: \n"\r
+ " \n"\r
+ " cmp r0, #-1 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r1, #1 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r2, #2 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r3, #3 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r4, #4 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r5, #5 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r6, #6 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r7, #7 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r8, #8 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r9, #9 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r10, #10 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r11, #11 \n"\r
+ " bne reg2_error_loop \n"\r
+ " cmp r12, #12 \n"\r
+ " bne reg2_error_loop \n"\r
+ " \n"\r
+ " /* Increment the loop counter to indicate this test is still functioning\n"\r
+ " correctly. */ \n"\r
+ " push { r0-r1 } \n"\r
+ " ldr r0, =ulRegTest2LoopCounter \n"\r
+ " ldr r1, [r0] \n"\r
+ " adds r1, r1, #1 \n"\r
+ " str r1, [r0] \n"\r
+ " \n"\r
+ " /* Yield to increase test coverage. */ \n"\r
+ " movs r0, #0x01 \n"\r
+ " ldr r1, =0xe000ed04 \n" /* NVIC_INT_CTRL */\r
+ " lsl r0, #28 \n" /* Shift to PendSV bit */\r
+ " str r0, [r1] \n"\r
+ " dsb \n"\r
+ " pop { r0-r1 } \n"\r
+ " \n"\r
+ " /* Start again. */ \n"\r
+ " b reg2_loop \n"\r
+ " \n"\r
+ "reg2_error_loop: \n"\r
+ " /* If this line is hit then there was an error in a core register value.\n"\r
+ " This loop ensures the loop counter variable stops incrementing. */\n"\r
+ " b reg2_error_loop \n"\r
+ " nop \n"\r
+ );\r
+\r
+ /* Remove compiler warnings about unused parameters. */\r
+ ( void ) pvParameters;\r
+}\r