]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Common/Minimal/GenQTest.c
Update version number to 8.1.1 for patch release that re-enables mutexes to be given...
[freertos] / FreeRTOS / Demo / Common / Minimal / GenQTest.c
index 59e176b1695ef4d330a2ba41e46046acea1ecdee..84ec6f8042ee237ea93479a65c3a58e71e0cc8ef 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V8.1.0 - Copyright (C) 2014 Real Time Engineers Ltd.\r
+    FreeRTOS V8.1.1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
     All rights reserved\r
 \r
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
@@ -93,6 +93,7 @@
 #define genqMUTEX_MEDIUM_PRIORITY      ( tskIDLE_PRIORITY + 2 )\r
 #define genqMUTEX_HIGH_PRIORITY                ( tskIDLE_PRIORITY + 3 )\r
 \r
+#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -121,6 +122,28 @@ static void prvLowPriorityMutexTask( void *pvParameters );
 static void prvMediumPriorityMutexTask( void *pvParameters );\r
 static void prvHighPriorityMutexTask( void *pvParameters );\r
 \r
+/*\r
+ * Exercises the priority inheritance when a task takes two mutexes, returning\r
+ * them in a different order to which they were taken.\r
+ */\r
+static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
+\r
+/*\r
+ * Exercises the priority inheritance when a task takes two mutexes, returning\r
+ * them in the same order in which they were taken.\r
+ */\r
+static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );\r
+\r
+/*\r
+ * Task that receives an a mutex that is given from an interrupt - although\r
+ * generally mutexes should not be used given in interrupts (and definitely\r
+ * never taken in an interrupt) there are some circumstances when it may be\r
+ * desirable.  NOTE:  This function is not declared static to prevent compiler\r
+ * warnings being generated in demos where the function is declared but not\r
+ * used.\r
+ */\r
+void vInterruptMutexTask( void *pvParameters );\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /* Flag that will be latched to pdTRUE should any unexpected behaviour be\r
@@ -139,6 +162,11 @@ static volatile uint32_t ulGuardedVariable = 0;
 priority mutex test tasks. */\r
 static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;\r
 \r
+/* A mutex which is given from an interrupt - although generally mutexes should\r
+not be used given in interrupts (and definitely never taken in an interrupt)\r
+there are some circumstances when it may be desirable. */\r
+static SemaphoreHandle_t xISRMutex = NULL;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 void vStartGenericQueueTasks( UBaseType_t uxPriority )\r
@@ -146,6 +174,9 @@ void vStartGenericQueueTasks( UBaseType_t uxPriority )
 QueueHandle_t xQueue;\r
 SemaphoreHandle_t xMutex;\r
 \r
+       xISRMutex = xSemaphoreCreateMutex();\r
+       configASSERT( xISRMutex );\r
+\r
        /* Create the queue that we are going to use for the\r
        prvSendFrontAndBackTest demo. */\r
        xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );\r
@@ -180,6 +211,14 @@ SemaphoreHandle_t xMutex;
        xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );\r
        xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );\r
        xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );\r
+\r
+       /* Only when the windows simulator is being used - create the task that\r
+       receives a mutex from an interrupt. */\r
+       #ifdef _WINDOWS_\r
+       {\r
+               xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL );\r
+       }\r
+       #endif /* __WINDOWS__ */\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -411,150 +450,286 @@ QueueHandle_t xQueue;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvLowPriorityMutexTask( void *pvParameters )\r
+static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )\r
 {\r
-SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;\r
+       /* Take the mutex.  It should be available now. */\r
+       if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-       #ifdef USE_STDIO\r
-       void vPrintDisplayMessage( const char * const * ppcMessageToSend );\r
+       /* Set the guarded variable to a known start value. */\r
+       ulGuardedVariable = 0;\r
 \r
-               const char * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";\r
+       /* This task's priority should be as per that assigned when the task was\r
+       created. */\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* Queue a message for printing to say the task has started. */\r
-               vPrintDisplayMessage( &pcTaskStartMsg );\r
+       /* Now unsuspend the high priority task.  This will attempt to take the\r
+       mutex, and block when it finds it cannot obtain it. */\r
+       vTaskResume( xHighPriorityMutexTask );\r
+\r
+       #if configUSE_PREEMPTION == 0\r
+               taskYIELD();\r
        #endif\r
 \r
-       /* The local mutex is used to check the 'mutexs held' count. */\r
-       xLocalMutex = xSemaphoreCreateMutex();\r
-       configASSERT( xLocalMutex );\r
+       /* Ensure the task is reporting its priority as blocked and not\r
+       suspended (as it would have done in versions up to V7.5.3). */\r
+       #if( INCLUDE_eTaskGetState == 1 )\r
+       {\r
+               configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );\r
+       }\r
+       #endif /* INCLUDE_eTaskGetState */\r
 \r
-       for( ;; )\r
+       /* The priority of the high priority task should now have been inherited\r
+       as by now it will have attempted to get the mutex. */\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
        {\r
-               /* Take the mutex.  It should be available now. */\r
-               if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* Set the guarded variable to a known start value. */\r
-               ulGuardedVariable = 0;\r
+       /* Attempt to set the priority of this task to the test priority -\r
+       between the     idle priority and the medium/high test priorities, but the\r
+       actual priority should remain at the high priority. */\r
+       vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* This task's priority should be as per that assigned when the task was\r
-               created. */\r
-               if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       /* Now unsuspend the medium priority task.  This should not run as the\r
+       inherited priority of this task is above that of the medium priority\r
+       task. */\r
+       vTaskResume( xMediumPriorityMutexTask );\r
 \r
-               /* Now unsuspend the high priority task.  This will attempt to take the\r
-               mutex, and block when it finds it cannot obtain it. */\r
-               vTaskResume( xHighPriorityMutexTask );\r
+       /* If the medium priority task did run then it will have incremented the\r
+       guarded variable. */\r
+       if( ulGuardedVariable != 0 )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               #if configUSE_PREEMPTION == 0\r
-                       taskYIELD();\r
-               #endif\r
+       /* Take the local mutex too, so two mutexes are now held. */\r
+       if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* Ensure the task is reporting its priority as blocked and not\r
-               suspended (as it would have done in versions up to V7.5.3). */\r
-               #if( INCLUDE_eTaskGetState == 1 )\r
-               {\r
-                       configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );\r
-               }\r
-               #endif /* INCLUDE_eTaskGetState */\r
+       /* When the semaphore is given back the priority of this task should not\r
+       yet be disinherited because the local mutex is still held.  This is a\r
+       simplification to allow FreeRTOS to be integrated with middleware that\r
+       attempts to hold multiple mutexes without bloating the code with complex\r
+       algorithms.  It is possible that the high priority mutex task will\r
+       execute as it shares a priority with this task. */\r
+       if( xSemaphoreGive( xMutex ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* The priority of the high priority task should now have been inherited\r
-               as by now it will have attempted to get the mutex. */\r
-               if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       #if configUSE_PREEMPTION == 0\r
+               taskYIELD();\r
+       #endif\r
 \r
-               /* Attempt to set the priority of this task to the test priority -\r
-               between the     idle priority and the medium/high test priorities, but the\r
-               actual priority should remain at the high priority. */\r
-               vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );\r
-               if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       /* The guarded variable is only incremented by the medium priority task,\r
+       which still should not have executed as this task should remain at the\r
+       higher priority, ensure this is the case. */\r
+       if( ulGuardedVariable != 0 )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* Now unsuspend the medium priority task.  This should not run as the\r
-               inherited priority of this task is above that of the medium priority\r
-               task. */\r
-               vTaskResume( xMediumPriorityMutexTask );\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* If the medium priority task did run then it will have incremented the \r
-               guarded variable. */\r
-               if( ulGuardedVariable != 0 )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       /* Now also give back the local mutex, taking the held count back to 0.\r
+       This time the priority of this task should be disinherited back to the\r
+       priority to which it was set while the mutex was held.  This means\r
+       the medium priority task should execute and increment the guarded\r
+       variable.   When this task next runs both the high and medium priority\r
+       tasks will have been suspended again. */\r
+       if( xSemaphoreGive( xLocalMutex ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* Take the local mutex too, so two mutexes are now held. */\r
-               if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       #if configUSE_PREEMPTION == 0\r
+               taskYIELD();\r
+       #endif\r
 \r
-               /* When the semaphore is given back the priority of this task should not\r
-               yet be disinherited because the local mutex is still held.  This is a\r
-               simplification to allow FreeRTOS to be integrated with middleware that\r
-               attempts to hold multiple mutexes without bloating the code with complex\r
-               algorithms.  It is possible that the high priority mutex task will\r
-               execute as it shares a priority with this task. */\r
-               if( xSemaphoreGive( xMutex ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       /* Check the guarded variable did indeed increment... */\r
+       if( ulGuardedVariable != 1 )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               #if configUSE_PREEMPTION == 0\r
-                       taskYIELD();\r
-               #endif\r
+       /* ... and that the priority of this task has been disinherited to\r
+       genqMUTEX_TEST_PRIORITY. */\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* The guarded variable is only incremented by the medium priority task,\r
-               which still should not have executed as this task should remain at the\r
-               higher priority, ensure this is the case. */\r
-               if( ulGuardedVariable != 0 )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       /* Set the priority of this task back to its original value, ready for\r
+       the next loop around this test. */\r
+       vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-               if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )\r
+{\r
+       /* Take the mutex.  It should be available now. */\r
+       if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
 \r
-               /* Now also give back the local mutex, taking the held count back to 0.\r
-               This time the priority of this task should be disinherited back to the\r
-               priority to which it was set while the mutex was held.  This means\r
-               the medium priority task should execute and increment the guarded \r
-               variable.   When this task next runs both the high and medium priority \r
-               tasks will have been suspended again. */\r
-               if( xSemaphoreGive( xLocalMutex ) != pdPASS )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
+       /* Set the guarded variable to a known start value. */\r
+       ulGuardedVariable = 0;\r
+\r
+       /* This task's priority should be as per that assigned when the task was\r
+       created. */\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       /* Now unsuspend the high priority task.  This will attempt to take the\r
+       mutex, and block when it finds it cannot obtain it. */\r
+       vTaskResume( xHighPriorityMutexTask );\r
+\r
+       #if configUSE_PREEMPTION == 0\r
+               taskYIELD();\r
+       #endif\r
+\r
+       /* Ensure the task is reporting its priority as blocked and not\r
+       suspended (as it would have done in versions up to V7.5.3). */\r
+       #if( INCLUDE_eTaskGetState == 1 )\r
+       {\r
+               configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );\r
+       }\r
+       #endif /* INCLUDE_eTaskGetState */\r
+\r
+       /* The priority of the high priority task should now have been inherited\r
+       as by now it will have attempted to get the mutex. */\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       /* Now unsuspend the medium priority task.  This should not run as the\r
+       inherited priority of this task is above that of the medium priority\r
+       task. */\r
+       vTaskResume( xMediumPriorityMutexTask );\r
+\r
+       /* If the medium priority task did run then it will have incremented the\r
+       guarded variable. */\r
+       if( ulGuardedVariable != 0 )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       /* Take the local mutex too, so two mutexes are now held. */\r
+       if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       /* When the local semaphore is given back the priority of this task should\r
+       not     yet be disinherited because the shared mutex is still held.  This is a\r
+       simplification to allow FreeRTOS to be integrated with middleware that\r
+       attempts to hold multiple mutexes without bloating the code with complex\r
+       algorithms.  It is possible that the high priority mutex task will\r
+       execute as it shares a priority with this task. */\r
+       if( xSemaphoreGive( xLocalMutex ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       #if configUSE_PREEMPTION == 0\r
+               taskYIELD();\r
+       #endif\r
+\r
+       /* The guarded variable is only incremented by the medium priority task,\r
+       which still should not have executed as this task should remain at the\r
+       higher priority, ensure this is the case. */\r
+       if( ulGuardedVariable != 0 )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       /* Now also give back the shared mutex, taking the held count back to 0.\r
+       This time the priority of this task should be disinherited back to the\r
+       priority at which it was created.  This means the medium priority task\r
+       should execute and increment the guarded variable.  When this task next runs\r
+       both the high and medium priority tasks will have been suspended again. */\r
+       if( xSemaphoreGive( xMutex ) != pdPASS )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       #if configUSE_PREEMPTION == 0\r
+               taskYIELD();\r
+       #endif\r
+\r
+       /* Check the guarded variable did indeed increment... */\r
+       if( ulGuardedVariable != 1 )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+\r
+       /* ... and that the priority of this task has been disinherited to\r
+       genqMUTEX_LOW_PRIORITY. */\r
+       if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )\r
+       {\r
+               xErrorDetected = pdTRUE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLowPriorityMutexTask( void *pvParameters )\r
+{\r
+SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;\r
+\r
+       #ifdef USE_STDIO\r
+       void vPrintDisplayMessage( const char * const * ppcMessageToSend );\r
+\r
+               const char * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";\r
+\r
+               /* Queue a message for printing to say the task has started. */\r
+               vPrintDisplayMessage( &pcTaskStartMsg );\r
+       #endif\r
+\r
+       /* The local mutex is used to check the 'mutexs held' count. */\r
+       xLocalMutex = xSemaphoreCreateMutex();\r
+       configASSERT( xLocalMutex );\r
+\r
+       for( ;; )\r
+       {\r
+               /* The first tests exercise the priority inheritance when two mutexes\r
+               are taken then returned in a different order to which they were\r
+               taken. */\r
+               prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex );\r
+\r
+               /* Just to show this task is still running. */\r
+               ulLoopCounter2++;\r
 \r
                #if configUSE_PREEMPTION == 0\r
                        taskYIELD();\r
                #endif\r
 \r
-               /* Check the guarded variable did indeed increment... */\r
-               if( ulGuardedVariable != 1 )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* ... and that the priority of this task has been disinherited to\r
-               genqMUTEX_TEST_PRIORITY. */\r
-               if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )\r
-               {\r
-                       xErrorDetected = pdTRUE;\r
-               }\r
-\r
-               /* Set the priority of this task back to its original value, ready for\r
-               the next loop around this test. */\r
-               vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );\r
+               /* The second tests exercise the priority inheritance when two mutexes\r
+               are taken then returned in the same order in which they were taken. */\r
+               prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex );\r
 \r
                /* Just to show this task is still running. */\r
                ulLoopCounter2++;\r
@@ -612,12 +787,53 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+/* NOTE: This function is not declared static to prevent compiler warnings in\r
+demos where the function is declared but not used. */\r
+void vInterruptMutexTask( void *pvParameters )\r
+{\r
+const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS );\r
+volatile uint32_t ulLoops = 0;\r
+\r
+       /* Just to avoid compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Has to wait longer than the time between gives to make sure it\r
+               should definitely have received the mutex. */\r
+               if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )\r
+               {\r
+                       xErrorDetected = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       ulLoops++;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vMutexISRInteractionTest( void )\r
+{\r
+static TickType_t xLastGiveTime = 0;\r
+TickType_t xTimeNow;\r
+\r
+       xTimeNow = xTaskGetTickCountFromISR();\r
+       if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )\r
+       {\r
+               configASSERT( xISRMutex );\r
+               xSemaphoreGiveFromISR( xISRMutex, NULL );\r
+               xLastGiveTime = xTimeNow;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 /* This is called to check that all the created tasks are still running. */\r
 BaseType_t xAreGenericQueueTasksStillRunning( void )\r
 {\r
 static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;\r
 \r
-       /* If the demo task is still running then we expect the loopcounters to\r
+       /* If the demo task is still running then we expect the loop counters to\r
        have incremented since this function was last called. */\r
        if( ulLastLoopCounter == ulLoopCounter )\r
        {\r