static void vErrorChecks( void *pvParameters ) { TickType_t xDelayPeriod = mainCHECK_PERIOD; TickType_t xLastWakeTime; /* Initialise xLastWakeTime to ensure the first call to vTaskDelayUntil() functions correctly. */ xLastWakeTime = xTaskGetTickCount(); for( ;; ) { /* Delay until it is time to execute again. The delay period is shorter following an error. */ vTaskDelayUntil( &xLastWakeTime, xDelayPeriod ); /* Check all the demo application tasks are executing without error. If an error is found the delay period is shortened - this has the effect of increasing the flash rate of the 'check' task LED. */ if( prvCheckOtherTasksAreStillRunning() == pdFAIL ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_CHECK_PERIOD; } /* Toggle the LED each cycle round. */ vParTestToggleLED( mainCHECK_TASK_LED ); } }
static void prvErrorChecks( void *pvParameters ) { portTickType xDelayPeriod = mainNO_ERROR_CHECK_DELAY, xLastExecutionTime; /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil() works correctly. */ xLastExecutionTime = xTaskGetTickCount(); /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { /* Wait until it is time to check again. The time we wait here depends on whether an error has been detected or not. When an error is detected the time is shortened resulting in a faster LED flash rate. */ /* Perform this check every mainCHECK_DELAY milliseconds. */ vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod ); /* See if the other tasks are all ok. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error occurred in one of the tasks so shorten the delay period - which has the effect of increasing the frequency of the LED toggle. */ xDelayPeriod = mainERROR_CHECK_DELAY; } /* Flash! */ vParTestToggleLED( mainCHECK_TEST_LED ); } }
static void vErrorChecks( void *pvParameters ) { TickType_t xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; /* The parameters are not used in this task. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so the on board LED flash rate will increase. */ for( ;; ) { /* Delay until it is time to execute again. */ vTaskDelay( xDelayPeriod ); /* Check all the standard demo application tasks are executing without error. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } vParTestToggleLED( mainCHECK_TASK_LED ); } }
static portTASK_FUNCTION( vErrorChecks, pvParameters ) { TickType_t xLastCheckTime; TickType_t xDelayTime = mainNO_ERROR_CHECK_PERIOD; char cErrorOccurred; /* We need to initialise xLastCheckTime prior to the first call to vTaskDelayUntil(). */ xLastCheckTime = xTaskGetTickCount(); /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { /* Wait until it is time to check the other tasks again. */ vTaskDelayUntil( &xLastCheckTime, xDelayTime ); /* Check all the other tasks are running, and running without ever having an error. */ cErrorOccurred = prvCheckOtherTasksAreStillRunning(); /* If an error was detected increase the frequency of the LED flash. */ if( cErrorOccurred == pdTRUE ) { xDelayTime = mainERROR_CHECK_PERIOD; } /* Flash the LED for visual feedback. */ vParTestToggleLED( mainCHECK_TASK_LED ); } }
static void vErrorChecks( void *pvParameters ) { static volatile unsigned long ulDummyVariable = 3UL; TickType_t xDelayPeriod = mainNO_ERROR_CHECK_DELAY; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { /* Wait until it is time to check again. The time we wait here depends on whether an error has been detected or not. When an error is detected the time is shortened resulting in a faster LED flash rate. */ vTaskDelay( xDelayPeriod ); /* Perform a bit of 32bit maths to ensure the registers used by the integer tasks get some exercise outside of the integer tasks themselves. The result here is not important we are just deliberately changing registers used by other tasks to ensure that their context switch is operating as required. - see the demo application documentation for more info. */ ulDummyVariable *= 3UL; /* See if the other tasks are all ok. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error occurred in one of the tasks so shorten the delay period - which has the effect of increasing the frequency of the LED toggle. */ xDelayPeriod = mainERROR_CHECK_DELAY; } /* Flash! */ vParTestToggleLED( mainCHECK_LED ); } }
static void vErrorChecks( void *pvParameters ) { portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; /* Just to stop compiler warnings. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so the on board LED flash rate will increase. */ for( ;; ) { /* Delay until it is time to execute again. */ vTaskDelay( xDelayPeriod ); /* Check all the standard demo application tasks are executing without error. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } /* The toggle rate of the LED depends on how long this task delays for. An error reduces the delay period and so increases the toggle rate. */ vParTestToggleLED( mainON_BOARD_LED_BIT ); } }
static void vErrorChecks( void *pvParameters ) { TickType_t xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; /* Parameters are not used. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so the on board LED flash rate will increase. This task runs at the highest priority. */ for( ;; ) { /* The period of the delay depends on whether an error has been detected or not. If an error has been detected then the period is reduced to increase the LED flash rate. */ vTaskDelay( xDelayPeriod ); if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } /* Toggle the LED before going back to wait for the next cycle. */ vParTestToggleLED( mainCHECK_LED ); } }
static portTASK_FUNCTION( vErrorChecks, pvParameters ) { TickType_t xDelayPeriod = mainNO_ERROR_CHECK_DELAY; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { /* Wait until it is time to check again. The time we wait here depends on whether an error has been detected or not. When an error is detected the time is shortened resulting in a faster LED flash rate. */ vTaskDelay( xDelayPeriod ); /* See if the other tasks are all ok. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error occurred in one of the tasks so shorten the delay period - which has the effect of increasing the frequency of the LED toggle. */ xDelayPeriod = mainERROR_CHECK_DELAY; } /* Flash! */ vParTestToggleLED( mainCHECK_LED ); } }
static void vErrorChecks( void *pvParameters ) { portTickType xDelayTime = mainNO_ERROR_CHECK_PERIOD; portBASE_TYPE xErrorOccurred; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { /* Wait until it is time to check the other tasks. */ vTaskDelay( xDelayTime ); /* Check all the other tasks are running, and running without ever having an error. */ xErrorOccurred = prvCheckOtherTasksAreStillRunning(); /* If an error was detected increase the frequency of the LED flash. */ if( xErrorOccurred == pdTRUE ) { xDelayTime = mainERROR_CHECK_PERIOD; } /* Flash the LED for visual feedback. */ vParTestToggleLED( mainCHECK_TASK_LED ); } }
static void vErrorChecks( void *pvParameters ) { TickType_t xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; TickType_t xLastWakeTime; /* The parameters are not used. */ ( void ) pvParameters; /* Initialise xLastWakeTime to ensure the first call to vTaskDelayUntil() functions correctly. */ xLastWakeTime = xTaskGetTickCount(); /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so the Check LED flash rate will increase. */ for( ;; ) { /* Delay until it is time to execute again. The delay period is shorter following an error. */ vTaskDelayUntil( &xLastWakeTime, xDelayPeriod ); /* Check all the standard demo application tasks are executing without error. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } vParTestToggleLED( mainCHECK_LED ); } }
static void vErrorChecks( void *pvParameters ) { portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; unsigned long ulMemCheckTaskRunningCount; xTaskHandle xCreatedTask; /* Just to stop compiler warnings. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so the on board LED flash rate will increase. In addition to the standard tests the memory allocator is tested through the dynamic creation and deletion of a task each cycle. Each time the task is created memory must be allocated for its stack. When the task is deleted this memory is returned to the heap. If the task cannot be created then it is likely that the memory allocation failed. */ for( ;; ) { /* Reset xCreatedTask. This is modified by the task about to be created so we can tell if it is executing correctly or not. */ xCreatedTask = mainNO_TASK; /* Dynamically create a task - passing ulMemCheckTaskRunningCount as a parameter. */ ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; if( xTaskCreate( vMemCheckTask, ( signed char * ) "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS ) { /* Could not create the task - we have probably run out of heap. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } /* Delay until it is time to execute again. */ vTaskDelay( xDelayPeriod ); /* Delete the dynamically created task. */ if( xCreatedTask != mainNO_TASK ) { vTaskDelete( xCreatedTask ); } /* Check all the standard demo application tasks are executing without error. ulMemCheckTaskRunningCount is checked to ensure it was modified by the task just deleted. */ if( prvCheckOtherTasksAreStillRunning( ulMemCheckTaskRunningCount ) != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } /* The toggle rate of the LED depends on how long this task delays for. An error reduces the delay period and so increases the toggle rate. */ vParTestToggleLED( mainON_BOARD_LED_BIT ); } }
static void vErrorChecks( void *pvParameters ) { TickType_t xDelayPeriod = mainNO_ERROR_FLASH_PERIOD; unsigned long ulMemCheckTaskRunningCount; TaskHandle_t xCreatedTask; /* The parameters are not used in this function. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD to mainERROR_FLASH_PERIOD so the on board LED flash rate will increase. In addition to the standard tests the memory allocator is tested through the dynamic creation and deletion of a task each cycle. Each time the task is created memory must be allocated for its stack. When the task is deleted this memory is returned to the heap. If the task cannot be created then it is likely that the memory allocation failed. */ for( ;; ) { /* Dynamically create a task - passing ulMemCheckTaskRunningCount as a parameter. */ ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; xCreatedTask = mainNO_TASK; if( xTaskCreate( vMemCheckTask, "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS ) { /* Could not create the task - we have probably run out of heap. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } /* Delay until it is time to execute again. */ vTaskDelay( xDelayPeriod ); /* Delete the dynamically created task. */ if( xCreatedTask != mainNO_TASK ) { vTaskDelete( xCreatedTask ); } /* Check all the standard demo application tasks are executing without error. ulMemCheckTaskRunningCount is checked to ensure it was modified by the task just deleted. */ if( prvCheckOtherTasksAreStillRunning( ulMemCheckTaskRunningCount ) != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_FLASH_PERIOD; } prvToggleOnBoardLED(); } }
/* * Cycle for ever, delaying then checking all the other tasks are still * operating without error. If an error is detected then the delay period * is decreased from mainCHECK_PERIOD to mainERROR_CHECK_PERIOD so * the on board LED flash rate will increase. * * In addition to the standard tests the memory allocator is tested through * the dynamic creation and deletion of a task each cycle. Each time the * task is created memory must be allocated for its stack. When the task is * deleted this memory is returned to the heap. If the task cannot be created * then it is likely that the memory allocation failed. In addition the * dynamically created task allocates and frees memory while it runs. */ static void vErrorChecks( void *pvParameters ) { portTickType xDelayPeriod = mainCHECK_PERIOD; volatile unsigned long ulMemCheckTaskRunningCount; xTaskHandle xCreatedTask; portTickType xLastWakeTime; /* Initialise xLastWakeTime to ensure the first call to vTaskDelayUntil() functions correctly. */ xLastWakeTime = xTaskGetTickCount(); for( ;; ) { /* Set ulMemCheckTaskRunningCount to a known value so we can check later that it has changed. */ ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; /* Dynamically create a task - passing ulMemCheckTaskRunningCount as a parameter. */ xCreatedTask = mainNO_TASK; if( xTaskCreate( vMemCheckTask, ( signed char * ) "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS ) { /* Could not create the task - we have probably run out of heap. */ xDelayPeriod = mainERROR_CHECK_PERIOD; } /* Delay until it is time to execute again. The delay period is shorter following an error. */ vTaskDelayUntil( &xLastWakeTime, xDelayPeriod ); /* Delete the dynamically created task. */ if( xCreatedTask != mainNO_TASK ) { vTaskDelete( xCreatedTask ); } /* Check all the standard demo application tasks are executing without error. ulMemCheckTaskRunningCount is checked to ensure it was modified by the task just deleted. */ if( prvCheckOtherTasksAreStillRunning( ulMemCheckTaskRunningCount ) != pdPASS ) { /* An error has been detected in one of the tasks - flash faster. */ xDelayPeriod = mainERROR_CHECK_PERIOD; } vParTestToggleLED( mainCHECK_TASK_LED ); } }
static portTASK_FUNCTION( vErrorChecks, pvParameters ) { unsigned long ulMemCheckTaskRunningCount; TaskHandle_t xCreatedTask; /* The parameters are not used in this function. */ ( void )pvParameters; xSerialPortInitMinimal( mainCOM_TEST_BAUD_RATE, 8 ); for( ;; ) { ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; xCreatedTask = mainNO_TASK; if( xTaskCreate ( vMemCheckTask, "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * )&ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS ) { xSerialPutChar( xSTDComPort, 'E', portMAX_DELAY ); } /* Delay until it is time to execute again. */ vTaskDelay( mainCHECK_PERIOD ); /* Delete the dynamically created task. */ if( xCreatedTask != mainNO_TASK ) { vTaskDelete( xCreatedTask ); } if( prvCheckOtherTasksAreStillRunning( ulMemCheckTaskRunningCount ) != pdPASS ) { xSerialPutChar( xSTDComPort, 'E', portMAX_DELAY ); } else { xSerialPutChar( xSTDComPort, '.', portMAX_DELAY ); } } }
static void vErrorChecks( void *pvParameters ) { static portCHAR cCheckVal[ mainMAX_FLAG_STRING_LEN ]; portCHAR *pcFlagString; xLCDMessage xMessageToSend; portTickType xLastWakeTime; portCHAR *pcStringsToDisplay[] = { "Check status flag" }; /* The parameters are not used in this task. */ ( void ) pvParameters; pcFlagString = &cCheckVal[ 0 ]; /* Initialise xLastWakeTime to ensure the first call to vTaskDelayUntil() functions correctly. */ xLastWakeTime = xTaskGetTickCount(); /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { /* Delay until it is time to execute again. */ vTaskDelayUntil( &xLastWakeTime, mainCHECK_PERIOD ); /* Check all the other tasks to see if the error flag needs updating. */ prvCheckOtherTasksAreStillRunning(); /* Create a string indicating the error flag status. */ sprintf( cCheckVal, "equals 0x%x ", ulErrorFlags ); xMessageToSend.xRow = Line2; /* Send the first part of the message to the LCD task. */ xMessageToSend.ppcMessageToDisplay = &pcStringsToDisplay[ 0 ]; xQueueSend( xLCDQueue, ( void * ) &xMessageToSend, 0 ); vTaskDelay( mainSTRING_WRITE_DELAY ); /* Send the second part of the message to the LCD task. */ xMessageToSend.ppcMessageToDisplay = &pcFlagString; xQueueSend( xLCDQueue, ( void * ) &xMessageToSend, 0 ); } }
static void vErrorChecks( void *pvParameters ) { static volatile unsigned long ulDummyVariable = 3UL; /* The parameters are not used. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. */ for( ;; ) { vTaskDelay( mainCHECK_PERIOD ); /* Perform a bit of 32bit maths to ensure the registers used by the integer tasks get some exercise. The result here is not important - see the demo application documentation for more info. */ ulDummyVariable *= 3; prvCheckOtherTasksAreStillRunning(); } }
static void prvCheckTask( void *pvParameters ) { portTickType xDelayPeriod = mainNO_ERROR_FLASH_PERIOD_MS; portTickType xLastExecutionTime; /* Just to stop compiler warnings. */ ( void ) pvParameters; /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil() works correctly. */ xLastExecutionTime = xTaskGetTickCount(); /* Cycle for ever, delaying then checking all the other tasks are still operating without error. If an error is detected then the delay period is decreased from mainNO_ERROR_FLASH_PERIOD_MS to mainERROR_FLASH_PERIOD_MS so the on board LED flash rate will increase. NOTE: This task could easily be replaced by a software timer callback to remove the overhead of having an extra task. */ for( ;; ) { /* Delay until it is time to execute again. */ vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod ); /* Check all the standard demo application tasks are executing without error. */ if( prvCheckOtherTasksAreStillRunning() != pdPASS ) { /* An error has been detected in one of the tasks - flash the LED at a higher frequency to give visible feedback that something has gone wrong (it might just be that the loop back connector required by the comtest tasks has not been fitted). */ xDelayPeriod = mainERROR_FLASH_PERIOD_MS; } /* The toggle rate of the LED depends on how long this task delays for. An error reduces the delay period and so increases the toggle rate. */ vParTestToggleLED( mainON_BOARD_LED_BIT ); } }
static portTASK_FUNCTION( executeSensorTask, pvParameters ) { uint32_t xLastWakeUpTime; uint16_t ledCycleCounter = 0; //Initialize the wake up time with the current time xLastWakeUpTime = xTaskGetTickCount(); for(;;) { //Execute this task each 50ms vTaskDelayUntil( &xLastWakeUpTime, SENSOR_TASK_CYCLE ); ledCycleCounter += 50; if( prvCheckOtherTasksAreStillRunning() ) { //signal that everything is ok } else { //signal error condition } //toogle the green led each 500ms if( ledCycleCounter % GREEN_LED_TOGGLE_CYCLE == 0 ) { PORTA ^= (1<<PA7); } if( ledCycleCounter > 65000 ) { ledCycleCounter = 0; } } }
static void vErrorChecks( void *pvParameters ) { portTickType xExpectedWakeTime; const portTickType xPrintRate = ( portTickType ) 5000 / portTICK_RATE_MS; const long lMaxAllowableTimeDifference = ( long ) 0; portTickType xWakeTime; long lTimeDifference; const char *pcReceivedMessage; const char * const pcTaskBlockedTooLongMsg = "Print task blocked too long!\r\n"; const char * const pcUnexpectedHookValueMsg = "Task hook has unexpected value!\r\n"; ( void ) pvParameters; /* Register our callback function. */ vTaskSetApplicationTaskTag( NULL, prvExampleTaskHook ); /* Just for test purposes. */ if( xTaskGetApplicationTaskTag( NULL ) != prvExampleTaskHook ) { vPrintDisplayMessage( &pcUnexpectedHookValueMsg ); } /* Loop continuously, blocking, then checking all the other tasks are still running, before blocking once again. This task blocks on the queue of messages that require displaying so will wake either by its time out expiring, or a message becoming available. */ for( ;; ) { /* Calculate the time we will unblock if no messages are received on the queue. This is used to check that we have not blocked for too long. */ xExpectedWakeTime = xTaskGetTickCount(); xExpectedWakeTime += xPrintRate; /* Block waiting for either a time out or a message to be posted that required displaying. */ pcReceivedMessage = pcPrintGetNextMessage( xPrintRate ); /* Was a message received? */ if( pcReceivedMessage == NULL ) { /* A message was not received so we timed out, did we unblock at the expected time? */ xWakeTime = xTaskGetTickCount(); /* Calculate the difference between the time we unblocked and the time we should have unblocked. */ if( xWakeTime > xExpectedWakeTime ) { lTimeDifference = ( long ) ( xWakeTime - xExpectedWakeTime ); } else { lTimeDifference = ( long ) ( xExpectedWakeTime - xWakeTime ); } if( lTimeDifference > lMaxAllowableTimeDifference ) { /* We blocked too long - create a message that will get printed out the next time around. If we are not using preemption then we won't expect the timing to be so accurate. */ if( sUsingPreemption == pdTRUE ) { vPrintDisplayMessage( &pcTaskBlockedTooLongMsg ); } } /* Check the other tasks are still running, just in case. */ prvCheckOtherTasksAreStillRunning(); } else { /* We unblocked due to a message becoming available. Send the message for printing. */ vDisplayMessage( pcReceivedMessage ); } /* Key presses are used to invoke the trace visualisation utility, or end the program. */ prvCheckForKeyPresses(); } }
static void vErrorChecks( void *pvParameters ) { portTickType xExpectedWakeTime; const portTickType xPrintRate = ( portTickType ) 5000 / portTICK_RATE_MS; const long lMaxAllowableTimeDifference = ( long ) 0; portTickType xWakeTime; long lTimeDifference; const char *pcReceivedMessage; const char * const pcTaskBlockedTooLongMsg = "Print task blocked too long!\r\n"; /* Stop warnings. */ ( void ) pvParameters; /* Loop continuously, blocking, then checking all the other tasks are still running, before blocking once again. This task blocks on the queue of messages that require displaying so will wake either by its time out expiring, or a message becoming available. */ for( ;; ) { /* Calculate the time we will unblock if no messages are received on the queue. This is used to check that we have not blocked for too long. */ xExpectedWakeTime = xTaskGetTickCount(); xExpectedWakeTime += xPrintRate; /* Block waiting for either a time out or a message to be posted that required displaying. */ pcReceivedMessage = pcPrintGetNextMessage( xPrintRate ); /* Was a message received? */ if( pcReceivedMessage == NULL ) { /* A message was not received so we timed out, did we unblock at the expected time? */ xWakeTime = xTaskGetTickCount(); /* Calculate the difference between the time we unblocked and the time we should have unblocked. */ if( xWakeTime > xExpectedWakeTime ) { lTimeDifference = ( long ) ( xWakeTime - xExpectedWakeTime ); } else { lTimeDifference = ( long ) ( xExpectedWakeTime - xWakeTime ); } if( lTimeDifference > lMaxAllowableTimeDifference ) { /* We blocked too long - create a message that will get printed out the next time around. */ vPrintDisplayMessage( &pcTaskBlockedTooLongMsg ); } /* Check the other tasks are still running, just in case. */ prvCheckOtherTasksAreStillRunning(); } else { /* We unblocked due to a message becoming available. Send the message for printing. */ vDisplayMessage( pcReceivedMessage ); } /* Key presses are used to invoke the trace visualisation utility, or end the program. */ prvCheckForKeyPresses(); } } /*lint !e715 !e818 pvParameters is not used but all task functions must take this form. */
/*! * \brief The task function for the "Check" task. */ static void vErrorChecks( void *pvParameters ) { static volatile unsigned portLONG ulDummyVariable = 3UL; unsigned portLONG ulMemCheckTaskRunningCount; xTaskHandle xCreatedTask; portBASE_TYPE bSuicidalTask = 0; /* The parameters are not used. Prevent compiler warnings. */ ( void ) pvParameters; /* Cycle for ever, delaying then checking all the other tasks are still operating without error. In addition to the standard tests the memory allocator is tested through the dynamic creation and deletion of a task each cycle. Each time the task is created memory must be allocated for its stack. When the task is deleted this memory is returned to the heap. If the task cannot be created then it is likely that the memory allocation failed. */ for( ;; ) { /* Do this only once. */ if( bSuicidalTask == 0 ) { bSuicidalTask++; /* This task has to be created last as it keeps account of the number of tasks it expects to see running. However its implementation expects to be called before vTaskStartScheduler(). We're in the case here where vTaskStartScheduler() has already been called (thus the hidden IDLE task has already been spawned). Since vCreateSuicidalTask() supposes that the IDLE task isn't included in the response from uxTaskGetNumberOfTasks(), let the MEM_CHECK task play that role. => this is why vCreateSuicidalTasks() is not called as the last task. */ vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); } /* Reset xCreatedTask. This is modified by the task about to be created so we can tell if it is executing correctly or not. */ xCreatedTask = mainNO_TASK; /* Dynamically create a task - passing ulMemCheckTaskRunningCount as a parameter. */ ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; if( xTaskCreate( vMemCheckTask, ( signed portCHAR * ) "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS ) { /* Could not create the task - we have probably run out of heap. Don't go any further and flash the LED faster to provide visual feedback of the error. */ prvIndicateError(); } /* Delay until it is time to execute again. */ vTaskDelay( mainCHECK_PERIOD ); /* Delete the dynamically created task. */ if( xCreatedTask != mainNO_TASK ) { vTaskDelete( xCreatedTask ); } /* Perform a bit of 32bit maths to ensure the registers used by the integer tasks get some exercise. The result here is not important - see the demo application documentation for more info. */ ulDummyVariable *= 3; /* Check all other tasks are still operating without error. Check that vMemCheckTask did increment the counter. */ if( ( prvCheckOtherTasksAreStillRunning() != pdFALSE ) || ( ulMemCheckTaskRunningCount == mainCOUNT_INITIAL_VALUE ) ) { /* An error has occurred in one of the tasks. Don't go any further and flash the LED faster to give visual feedback of the error. */ prvIndicateError(); } else { /* Toggle the LED if everything is okay. */ vParTestToggleLED( mainCHECK_TASK_LED ); } } }