]> git.sur5r.net Git - freertos/blobdiff - Demo/Cortex_STM32L152_IAR/main.c
Comment and spell check the STM32L152 demo project.
[freertos] / Demo / Cortex_STM32L152_IAR / main.c
index 8dbf6daba66c9e62f020cc1182c2b7177bfa65d4..a47d0ce284336534ff8c6096bc4f21322ba7a1f7 100644 (file)
     licensing and training services.\r
 */\r
 \r
+/*\r
+ * The documentation page for this demo available on http://www.FreeRTOS.org\r
+ * documents the hardware configuration required to run this demo.  It also\r
+ * provides more information on the expected demo application behaviour.\r
+ *\r
+ * main() creates all the demo application tasks, then starts the scheduler.\r
+ * A lot of the created tasks are from the pool of "standard demo" tasks.  The\r
+ * web documentation provides more details of the standard demo application\r
+ * tasks, which provide no particular functionality but do provide a good\r
+ * example of how to use the FreeRTOS API.\r
+ *\r
+ * In addition to the standard demo tasks, the following tasks, interrupts and\r
+ * tests are defined and/or created within this file:\r
+ *\r
+ * "LCD" task - The LCD task is a 'gatekeeper' task.  It is the only task that\r
+ * is permitted to access the LCD and therefore ensures access to the LCD is\r
+ * always serialised and there are no mutual exclusion issues.  When a task or\r
+ * an interrupt wants to write to the LCD, it does not access the LCD directly\r
+ * but instead sends the message to the LCD task.  The LCD task then performs\r
+ * the actual LCD output.  This mechanism also allows interrupts to, in effect,\r
+ * write to the LCD by sending messages to the LCD task.\r
+ *\r
+ * The LCD task is also a demonstration of a controller task design pattern.\r
+ * Some tasks do not actually send a string to the LCD task directly, but\r
+ * instead send a command that is interpreted by the LCD task.  In a normal\r
+ * application these commands can be control values or set points, in this\r
+ * simple example the commands just result in messages being displayed on the\r
+ * LCD.\r
+ *\r
+ * "Button Poll" task - This task polls the state of the 'up' key on the\r
+ * joystick input device.  It uses the vTaskDelay() API function to control\r
+ * the poll rate to ensure debouncing is not necessary and that the task does\r
+ * not use all the available CPU processing time.\r
+ *\r
+ * Button Interrupt and run time stats display - The select button on the\r
+ * joystick input device is configured to generate an external interrupt.  The\r
+ * handler for this interrupt sends a message to LCD task, which interprets the\r
+ * message to mean, firstly write a message to the LCD, and secondly, generate\r
+ * a table of run time statistics.  The run time statistics are displayed as a\r
+ * table that contains information on how much processing time each task has\r
+ * been allocated since the application started to execute.  This information\r
+ * is provided both as an absolute time, and as a percentage of the total run\r
+ * time.  The information is displayed in the terminal IO window of the IAR\r
+ * embedded workbench.  The online documentation for this demo shows a screen\r
+ * shot demonstrating where the run time stats can be viewed.\r
+ *\r
+ * Idle Hook - The idle hook is a function that is called on each iteration of\r
+ * the idle task.  In this case it is used to place the processor into a low\r
+ * power mode.  Note however that this application is implemented using standard\r
+ * components, and is therefore not optimised for low power operation.  Lower\r
+ * power consumption would be achieved by converting polling tasks into event\r
+ * driven tasks, and slowing the tick interrupt frequency.\r
+ *\r
+ * "Check" function called from the tick hook - The tick hook is called during\r
+ * each tick interrupt.  It is called from an interrupt context so must execute\r
+ * quickly, not attempt to block, and not call any FreeRTOS API functions that\r
+ * do not end in "FromISR".  In this case the tick hook executes a 'check'\r
+ * function.  This only executes every five seconds.  Its main function is to\r
+ * check that all the standard demo tasks are still operational.  Each time it\r
+ * executes it sends a status code to the LCD task.  The LCD task interprets the\r
+ * code and displays an appropriate message - which will be PASS if no tasks\r
+ * have reported any errors, or a message stating which task has reported an\r
+ * error.\r
+*/\r
+\r
 /* Standard includes. */\r
 #include <stdio.h>\r
 \r
 #include "comtest2.h"\r
 #include "GenQTest.h"\r
 \r
-/* ST driver includes. */\r
-#include "stm32l1xx_usart.h"\r
-\r
 /* Eval board includes. */\r
 #include "stm32_eval.h"\r
 #include "stm32l152_eval_lcd.h"\r
 \r
+/* The priorities assigned to the tasks. */\r
 #define mainFLASH_TASK_PRIORITY                        ( tskIDLE_PRIORITY + 1 )\r
 #define mainLCD_TASK_PRIORITY                  ( tskIDLE_PRIORITY + 1 )\r
 #define mainCOM_TEST_PRIORITY                  ( tskIDLE_PRIORITY + 2 )\r
 #define mainGENERIC_QUEUE_TEST_PRIORITY        ( tskIDLE_PRIORITY )\r
 \r
-#define mainLCD_TASK_STACK_SIZE                        ( configMINIMAL_STACK_SIZE * 2 )\r
-\r
+/* The length of the queue (the number of items the queue can hold) that is used\r
+to send messages from tasks and interrupts the the LCD task. */\r
 #define mainQUEUE_LENGTH                               ( 5 )\r
 \r
+/* Codes sent within message to the LCD task so the LCD task can interrupt\r
+exactly what the message it just received was.  These are sent in the\r
+cMessageID member of the message structure (defined below). */\r
 #define mainMESSAGE_BUTTON_UP                  ( 1 )\r
-#define mainMESSAGE_BUTTON_DOWN                        ( 2 )\r
-#define mainMESSAGE_BUTTON_LEFT                        ( 3 )\r
-#define mainMESSAGE_BUTTON_RIGHT               ( 4 )\r
-#define mainMESSAGE_BUTTON_SEL                 ( 5 )\r
-#define mainMESSAGE_STATUS                             ( 6 )\r
-\r
-#define mainERROR_DYNAMIC_TASKS                        ( 2 )\r
-#define mainERROR_COM_TEST                             ( 3 )\r
-#define mainERROR_GEN_QUEUE_TEST               ( 4 )\r
+#define mainMESSAGE_BUTTON_SEL                 ( 2 )\r
+#define mainMESSAGE_STATUS                             ( 3 )\r
+\r
+/* When cMessageID member of the message sent to the LCD task is\r
+mainMESSAGE_STATUS then these definitions are sent in the lMessageValue member\r
+of the same message to indicate what the status actually is.  The value 1 is not\r
+used as this is globally defined as pdPASS, and indicates that no errors have\r
+been reported (the system is running as expected). */\r
+#define mainERROR_DYNAMIC_TASKS                        ( pdPASS + 1 )\r
+#define mainERROR_COM_TEST                             ( pdPASS + 2 )\r
+#define mainERROR_GEN_QUEUE_TEST               ( pdPASS + 3 )\r
 \r
 /* Baud rate used by the comtest tasks. */\r
-#define mainCOM_TEST_BAUD_RATE         ( 9600 )\r
+#define mainCOM_TEST_BAUD_RATE         ( 115200 )\r
 \r
 /* The LED used by the comtest tasks. See the comtest.c file for more\r
 information. */\r
 #define mainCOM_TEST_LED                       ( 3 )\r
 \r
+/*-----------------------------------------------------------*/\r
 \r
 /*\r
  * System configuration is performed prior to main() being called, this function\r
  * configures the peripherals used by the demo application.\r
  */\r
 static void prvSetupHardware( void );\r
+\r
+/*\r
+ * Definition of the LCD/controller task described in the comments at the top\r
+ * of this file.\r
+ */\r
 static void prvLCDTask( void *pvParameters );\r
-static void vTempTask( void *pv );\r
+\r
+/*\r
+ * Definition of the button poll task described in the comments at the top of\r
+ * this file.\r
+ */\r
+static void vButtonPollTask( void *pvParameters );\r
+\r
+/*\r
+ * Converts a status message value into an appropriate string for display on\r
+ * the LCD.  The string is written to pcBuffer.\r
+ */\r
 static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue );\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
+/* The time base for the run time stats is generated by the 16 bit timer 6.\r
+Each time the timer overflows ulTIM6_OverflowCount is incremented.  Therefore,\r
+when converting the total run time to a 32 bit number, the most significant two\r
+bytes are given by ulTIM6_OverflowCount and the least significant two bytes are\r
+given by the current TIM6 counter value.  Care must be taken with data\r
+consistency when combining the two in case a timer overflow occurs as the\r
+value is being read. */\r
 unsigned long ulTIM6_OverflowCount = 0UL;\r
 \r
+/* The handle of the queue used to send messages from tasks and interrupts to\r
+the LCD task. */\r
 static xQueueHandle xLCDQueue = NULL;\r
 \r
+/* The definition of each message sent from tasks and interrupts to the LCD\r
+task. */\r
 typedef struct\r
 {\r
-       char cMessageID;\r
-       long lMessageValue;\r
+       char cMessageID;        /* << States what the message is. */\r
+       long lMessageValue; /* << States the message value (can be an integer, string pointer, etc. depending on the value of cMessageID. */\r
 } xQueueMessage;\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
 void main( void )\r
 {\r
+       /* Configure the peripherals used by this demo application.  This includes\r
+       configuring the joystick input select button to generate interrupts. */\r
        prvSetupHardware();\r
        \r
        /* Create the queue used by tasks and interrupts to send strings to the LCD\r
        task. */\r
        xLCDQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( xQueueMessage ) );\r
        \r
+       /* If the queue could not be created then don't create any tasks that might\r
+       attempt to use the queue. */\r
        if( xLCDQueue != NULL )\r
        {\r
+               /* Add the created queue to the queue registry so it can be viewed in\r
+               the IAR FreeRTOS state viewer plug-in. */\r
                vQueueAddToRegistry( xLCDQueue, "LCDQueue" );\r
-               xTaskCreate( prvLCDTask, ( signed char * ) "LCD", mainLCD_TASK_STACK_SIZE, NULL, mainLCD_TASK_PRIORITY, NULL );\r
-               xTaskCreate( vTempTask, ( signed char * ) "Temp", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
+               \r
+               /* Create the LCD and button poll tasks, as described at the top of this\r
+               file. */\r
+               xTaskCreate( prvLCDTask, ( signed char * ) "LCD", configMINIMAL_STACK_SIZE, NULL, mainLCD_TASK_PRIORITY, NULL );\r
+               xTaskCreate( vButtonPollTask, ( signed char * ) "Temp", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );\r
+               \r
+               /* Create a subset of the standard demo tasks. */\r
                vStartDynamicPriorityTasks();\r
                vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY );\r
                vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
                vStartGenericQueueTasks( mainGENERIC_QUEUE_TEST_PRIORITY );\r
                \r
+               /* Start the scheduler. */\r
                vTaskStartScheduler();\r
        }\r
        \r
+       /* If all is well then this line will never be reached.  If it is reached\r
+       then it is likely that there was insufficient (FreeRTOS) heap memory space\r
+       to create the idle task.  This may have been trapped by the malloc() failed\r
+       hook function, if one is configured. */\r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -150,49 +265,88 @@ static void prvLCDTask( void *pvParameters )
 xQueueMessage xReceivedMessage;\r
 long lLine = Line1;\r
 const long lFontHeight = (((sFONT *)LCD_GetFont())->Height);\r
+\r
+/* Buffer into which strings are formatted and placed ready for display on the\r
+LCD.  Note this is a static variable to prevent it being allocated on the task\r
+stack, which is too small to hold such a variable.  The stack size is configured\r
+when the task is created. */\r
 static char cBuffer[ 512 ];\r
 \r
        /* This function is the only function that uses printf().  If printf() is\r
        used from any other function then some sort of mutual exclusion on stdout\r
-       will be necessary. */\r
-\r
+       will be necessary.\r
+       \r
+       This is also the only function that is permitted to access the LCD.\r
+       \r
+       First print out the number of bytes that remain in the FreeRTOS heap.  This\r
+       can be viewed in the terminal IO window within the IAR Embedded Workbench. */\r
        printf( "%d bytes of heap space remain unallocated\n", xPortGetFreeHeapSize() );\r
 \r
        for( ;; )\r
        {\r
+               /* Wait for a message to be received.  This will wait indefinitely if\r
+               INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h, therefore there\r
+               is no need to check the function return value. */\r
                xQueueReceive( xLCDQueue, &xReceivedMessage, portMAX_DELAY );\r
 \r
+               /* Clear the LCD if the last LCD message was output to the last\r
+               available line on the LCD. */\r
                if( lLine > Line9 )\r
                {\r
                        LCD_Clear( Blue );\r
                        lLine = 0;\r
                }\r
                                \r
+               /* What is this message?  What does it contain? */\r
                switch( xReceivedMessage.cMessageID )\r
                {\r
-                       case mainMESSAGE_BUTTON_UP              :       sprintf( cBuffer, "Button up = %d", xReceivedMessage.lMessageValue );\r
-                                                                                               break;\r
-                       case mainMESSAGE_BUTTON_DOWN    :       sprintf( cBuffer, "Button down = %d", xReceivedMessage.lMessageValue );\r
-                                                                                               break;\r
-                       case mainMESSAGE_BUTTON_LEFT    :       sprintf( cBuffer, "Button left = %d", xReceivedMessage.lMessageValue );\r
-                                                                                               break;\r
-                       case mainMESSAGE_BUTTON_RIGHT   :       sprintf( cBuffer, "Button right = %d", xReceivedMessage.lMessageValue );\r
+                       case mainMESSAGE_BUTTON_UP              :       /* The button poll task has just\r
+                                                                                               informed this task that the up\r
+                                                                                               button on the joystick input has\r
+                                                                                               been pressed or released. */\r
+                                                                                               sprintf( cBuffer, "Button up = %d", xReceivedMessage.lMessageValue );\r
                                                                                                break;\r
-                       case mainMESSAGE_BUTTON_SEL             :       printf( "\nTask\t     Abs Time\t     %%Time\n*****************************************" );\r
+\r
+                       case mainMESSAGE_BUTTON_SEL             :       /* The select button interrupt\r
+                                                                                               just informed this task that the\r
+                                                                                               select button was pressed.\r
+                                                                                               Generate a table of task run time\r
+                                                                                               statistics and output this to\r
+                                                                                               the terminal IO window in the IAR\r
+                                                                                               embedded workbench. */\r
+                                                                                               printf( "\nTask\t     Abs Time\t     %%Time\n*****************************************" );\r
                                                                                                vTaskGetRunTimeStats( ( signed char * ) cBuffer );\r
                                                                                                printf( cBuffer );\r
                                                                                                \r
-                                                                                               /* The select button passes its\r
-                                                                                               own string to print out. */\r
+                                                                                               /* Also print out a message to\r
+                                                                                               the LCD - in this case the\r
+                                                                                               pointer to the string to print\r
+                                                                                               is sent directly in the\r
+                                                                                               lMessageValue member of the\r
+                                                                                               message.  This just demonstrates\r
+                                                                                               a different communication\r
+                                                                                               technique. */\r
                                                                                                sprintf( cBuffer, "%s", ( char * ) xReceivedMessage.lMessageValue );\r
                                                                                                break;\r
-                       case mainMESSAGE_STATUS                 :       prvGenerateStatusMessage( cBuffer, xReceivedMessage.lMessageValue );\r
+                                                                                               \r
+                       case mainMESSAGE_STATUS                 :       /* The tick interrupt hook\r
+                                                                                               function has just informed this\r
+                                                                                               task of the system status.\r
+                                                                                               Generate a string in accordance\r
+                                                                                               with the status value. */\r
+                                                                                               prvGenerateStatusMessage( cBuffer, xReceivedMessage.lMessageValue );\r
                                                                                                break;\r
+                                                                                               \r
                        default                                                 :       sprintf( cBuffer, "Unknown message" );\r
                                                                                                break;\r
                }\r
                \r
+               /* Output the message that was placed into the cBuffer array within the\r
+               switch statement above. */\r
                LCD_DisplayStringLine( lLine, ( uint8_t * ) cBuffer );\r
+               \r
+               /* Move onto the next LCD line, ready for the next iteration of this\r
+               loop. */\r
                lLine += lFontHeight;\r
        }\r
 }\r
@@ -200,13 +354,15 @@ static char cBuffer[ 512 ];
 \r
 static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue )\r
 {\r
+       /* Just a utility function to convert a status value into a meaningful\r
+       string for output onto the LCD. */\r
        switch( lStatusValue )\r
        {\r
                case pdPASS                                             :       sprintf( pcBuffer, "Task status = PASS" );\r
                                                                                        break;\r
                case mainERROR_DYNAMIC_TASKS    :       sprintf( pcBuffer, "Error: Dynamic tasks" );\r
                                                                                        break;\r
-               case mainERROR_COM_TEST                 :       sprintf( pcBuffer, "Error: COM test" );\r
+               case mainERROR_COM_TEST                 :       sprintf( pcBuffer, "Err: loop connected?" ); /* Error in COM test - is the Loopback connector connected? */                                                                                                             \r
                                                                                        break;\r
                case mainERROR_GEN_QUEUE_TEST   :       sprintf( pcBuffer, "Error: Gen Q test" );\r
                                                                                        break;\r
@@ -218,11 +374,21 @@ static void prvGenerateStatusMessage( char *pcBuffer, long lStatusValue )
 \r
 void EXTI9_5_IRQHandler( void )\r
 {\r
+/* Define the message sent to the LCD task from this interrupt. */\r
 const xQueueMessage xMessage = { mainMESSAGE_BUTTON_SEL, ( unsigned long ) "Select Interrupt!" };\r
 long lHigherPriorityTaskWoken = pdFALSE;\r
 \r
+       /* This is the interrupt handler for the joystick select button input.\r
+       The button has been pushed, write a message to the LCD via the LCD task. */\r
        xQueueSendFromISR( xLCDQueue, &xMessage, &lHigherPriorityTaskWoken );\r
+       \r
        EXTI_ClearITPendingBit( SEL_BUTTON_EXTI_LINE );\r
+       \r
+       /* If writing to xLCDQueue caused a task to unblock, and the unblocked task\r
+       has a priority equal to or above the task that this interrupt interrupted,\r
+       then lHigherPriorityTaskWoken will have been set to pdTRUE internally within\r
+       xQueuesendFromISR(), and portEND_SWITCHING_ISR() will ensure that this\r
+       interrupt returns directly to the higher priority unblocked task. */\r
        portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -231,12 +397,22 @@ void vApplicationTickHook( void )
 {\r
 static unsigned long ulCounter = 0;\r
 static const unsigned long ulCheckFrequency = 5000UL / portTICK_RATE_MS;\r
+long lHigherPriorityTaskWoken = pdFALSE;\r
+\r
+/* Define the status message that is sent to the LCD task.  By default the\r
+status is PASS. */\r
 static xQueueMessage xStatusMessage = { mainMESSAGE_STATUS, pdPASS };\r
-long lHigherPriorityTaskWoken = pdFALSE; /* Not used in this case as this is the tick hook. */\r
 \r
+       /* This is called from within the tick interrupt and performs the 'check'\r
+       functionality as described in the comments at the top of this file.\r
+\r
+       Is it time to perform the 'check' functionality again? */\r
        ulCounter++;\r
        if( ulCounter >= ulCheckFrequency )\r
        {\r
+               /* See if the standard demo tasks are executing as expected, changing\r
+               the message that is sent to the LCD task from PASS to an error code if\r
+               any tasks set reports an error. */\r
                if( xAreDynamicPriorityTasksStillRunning() != pdPASS )\r
                {\r
                        xStatusMessage.lMessageValue = mainERROR_DYNAMIC_TASKS;\r
@@ -252,35 +428,47 @@ long lHigherPriorityTaskWoken = pdFALSE; /* Not used in this case as this is the
                        xStatusMessage.lMessageValue = mainERROR_GEN_QUEUE_TEST;\r
                }\r
                \r
+               /* As this is the tick hook the lHigherPriorityTaskWoken parameter is not\r
+               needed (a context switch is going to be performed anyway), but it must\r
+               still be provided. */\r
                xQueueSendFromISR( xLCDQueue, &xStatusMessage, &lHigherPriorityTaskWoken );\r
                ulCounter = 0;\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void vTempTask( void *pv )\r
+static void vButtonPollTask( void *pvParameters )\r
 {\r
 long lLastState = pdTRUE;\r
 long lState;\r
 xQueueMessage xMessage;\r
 \r
+       /* This tasks performs the button polling functionality as described at the\r
+       top of this file. */\r
        for( ;; )\r
        {\r
+               /* Check the button state. */\r
                lState = STM_EVAL_PBGetState( BUTTON_UP );\r
                if( lState != lLastState )\r
                {\r
+                       /* The state has changed, send a message to the LCD task. */\r
                        xMessage.cMessageID = mainMESSAGE_BUTTON_UP;\r
                        xMessage.lMessageValue = lState;\r
                        lLastState = lState;\r
                        xQueueSend( xLCDQueue, &xMessage, portMAX_DELAY );\r
-                       vTaskDelay( 10 );\r
                }\r
+               \r
+               /* Block for 10 milliseconds so this task does not utilise all the CPU\r
+               time and debouncing of the button is not necessary. */\r
+               vTaskDelay( 10 / portTICK_RATE_MS );\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 static void prvSetupHardware( void )\r
 {\r
+       /* Ensure that all 4 interrupt priority bits are used as the pre-emption\r
+       priority. */\r
        NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );\r
        \r
        /* Initialise the LEDs. */\r
@@ -294,19 +482,18 @@ static void prvSetupHardware( void )
        \r
        /* The select button in the middle of the joystick is configured to generate\r
        an interrupt.  The Eval board library will configure the interrupt\r
-       priority to be the lowest priority available - this is important as the\r
-       interrupt service routine makes use of a FreeRTOS API function so must\r
-       therefore use a priority equal to or below that set by the\r
-       configMAX_SYSCALL_INTERRUPT_PRIORITY() value set in FreeRTOSConfig.h. */\r
+       priority to be the lowest priority available so the priority need not be\r
+       set here explicitly.  It is important that the priority is equal to or\r
+       below that set by the configMAX_SYSCALL_INTERRUPT_PRIORITY value set in\r
+       FreeRTOSConfig.h. */\r
        STM_EVAL_PBInit( BUTTON_SEL, BUTTON_MODE_EXTI );\r
 \r
        /* Initialize the LCD */\r
-       STM32L152_LCD_Init();\r
-       \r
-       LCD_Clear(Blue);\r
-       LCD_SetBackColor(Blue);\r
-       LCD_SetTextColor(White);\r
-       LCD_DisplayStringLine(Line0, "  www.FreeRTOS.org");\r
+       STM32L152_LCD_Init();   \r
+       LCD_Clear( Blue );\r
+       LCD_SetBackColor( Blue );\r
+       LCD_SetTextColor( White );\r
+       LCD_DisplayStringLine( Line0, "  www.FreeRTOS.org" );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -315,6 +502,18 @@ void vConfigureTimerForRunTimeStats( void )
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;\r
 NVIC_InitTypeDef NVIC_InitStructure;\r
 \r
+       /* The time base for the run time stats is generated by the 16 bit timer 6.\r
+       Each time the timer overflows ulTIM6_OverflowCount is incremented.\r
+       Therefore, when converting the total run time to a 32 bit number, the most\r
+       significant two bytes are given by ulTIM6_OverflowCount and the least\r
+       significant two bytes are given by the current TIM6 counter value.  Care\r
+       must be taken with data consistency when combining the two in case a timer\r
+       overflow occurs as the value is being read.\r
+       \r
+       The portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro (in FreeRTOSConfig.h) is\r
+       defined to call this function, so the kernel will call this function\r
+       automatically at the appropriate time. */\r
+\r
        /* TIM6 clock enable */\r
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);\r
 \r
@@ -330,22 +529,32 @@ NVIC_InitTypeDef NVIC_InitStructure;
        /* Only interrupt on overflow events. */\r
        TIM6->CR1 |= TIM_CR1_URS;\r
        \r
+       /* Enable the interrupt. */\r
        TIM_ITConfig( TIM6, TIM_IT_Update, ENABLE );\r
        \r
-       /* Enable the TIM6 gloabal Interrupt */\r
+       /* Enable the TIM6 global Interrupt */\r
        NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;\r
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_LOWEST_INTERRUPT_PRIORITY;\r
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; /* Not used as 4 bits are used for the pre-emption priority. */\r
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\r
+       NVIC_Init(&NVIC_InitStructure);\r
        \r
        TIM_ClearITPendingBit( TIM6, TIM_IT_Update );\r
-       NVIC_Init(&NVIC_InitStructure);\r
        TIM_Cmd( TIM6, ENABLE );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void TIM6_IRQHandler( void )\r
 {\r
+       /* Interrupt handler for TIM 6\r
+       \r
+       The time base for the run time stats is generated by the 16 bit timer 6.\r
+       Each time the timer overflows ulTIM6_OverflowCount is incremented.\r
+       Therefore, when converting the total run time to a 32 bit number, the most\r
+       significant two bytes are given by ulTIM6_OverflowCount and the least\r
+       significant two bytes are given by the current TIM6 counter value.  Care\r
+       must be taken with data consistency when combining the two in case a timer\r
+       overflow occurs as the value is being read. */\r
        if( TIM_GetITStatus( TIM6, TIM_IT_Update) != RESET)\r
        {\r
                ulTIM6_OverflowCount++;\r
@@ -359,18 +568,27 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName
        ( void ) pcTaskName;\r
        ( void ) pxTask;\r
        \r
+       /* Run time stack overflow checking is performed if\r
+       configconfigCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook\r
+       function is called if a stack overflow is detected. */\r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void vApplicationMallocFailedHook( void )\r
 {\r
+       /* Called if a call to pvPortMalloc() fails because there is insufficient\r
+       free memory available in the FreeRTOS heap.  pvPortMalloc() is called\r
+       internally by FreeRTOS API functions that create tasks, queues or\r
+       semaphores. */\r
        for( ;; );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void vApplicationIdleHook( void )\r
 {\r
+       /* Called on each itteration of the idle task.  In this case the idle task\r
+       just enters a low(ish) power mode. */\r
        PWR_EnterSleepMode( PWR_Regulator_ON, PWR_SLEEPEntry_WFI );\r
 }\r
 \r