]> git.sur5r.net Git - freertos/blobdiff - Demo/CORTEX_MB9B500_IAR_Keil/main-full.c
New MicroBlaze port: Added a FreeRTOS exception handler, and installed it in each...
[freertos] / Demo / CORTEX_MB9B500_IAR_Keil / main-full.c
index 29361610baebf8608cee2101559c0189a52a492c..7f71a2108173022d8a6be581094fb095315c84fd 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+    FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.\r
 \r
 \r
        FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by:\r
  *\r
  * main-full.c (this file) defines a comprehensive demo that creates many\r
  * tasks, queues, semaphores and timers.  It also demonstrates how Cortex-M3\r
- * interrupts can interact with FreeRTOS tasks/timers, and implements a simple\r
- * and small interactive web server.\r
+ * interrupts can interact with FreeRTOS tasks/timers.\r
  *\r
- * This project runs on the SmartFusion A2F-EVAL-KIT evaluation board, which\r
- * is populated with an A2F200M3F SmartFusion mixed signal FPGA.  The A2F200M3F\r
- * incorporates a Cortex-M3 microcontroller.\r
+ * This project runs on the SK-FM3-100PMC evaluation board, which is populated\r
+ * with an MB9BF5006N Cortex-M3 based microcontroller.\r
  *\r
  * The main() Function:\r
- * main() creates two demo specific software timers, one demo specific queue,\r
- * and three demo specific tasks.  It then creates a whole host of 'standard\r
+ * main() creates three demo specific software timers, one demo specific queue,\r
+ * and two demo specific tasks.  It then creates a whole host of 'standard\r
  * demo' tasks/queues/semaphores, before starting the scheduler.  The demo\r
  * specific tasks and timers are described in the comments here.  The standard\r
  * demo tasks are described on the FreeRTOS.org web site.\r
@@ -81,6 +79,9 @@
  * included to both test the FreeRTOS port, and provide examples of how the\r
  * various FreeRTOS API functions can be used.\r
  *\r
+ * This demo creates 43 tasks in total.  If you want a simpler demo, use the\r
+ * Blinky build configuration.\r
+ *\r
  * The Demo Specific Queue Send Task:\r
  * The queue send task is implemented by the prvQueueSendTask() function in\r
  * this file.  prvQueueSendTask() sits in a loop that causes it to repeatedly\r
  * in this file.  prvQueueReceiveTask() sits in a loop that causes it to\r
  * repeatedly attempt to read data from the queue that was created within\r
  * main().  When data is received, the task checks the value of the data, and\r
- * if the value equals the expected 100, toggles the green LED.  The 'block\r
- * time' parameter passed to the queue receive function specifies that the task\r
- * should be held in the Blocked state indefinitely to wait for data to be\r
- * available on the queue.  The queue receive task will only leave the Blocked\r
- * state when the queue send task writes to the queue.  As the queue send task\r
- * writes to the queue every 200 milliseconds, the queue receive task leaves\r
- * the Blocked state every 200 milliseconds, and therefore toggles the LED\r
- * every 200 milliseconds.\r
+ * if the value equals the expected 100, toggles an LED in the 7 segment display\r
+ * (see the documentation page for this demo on the FreeRTOS.org site to see\r
+ * which LED is used).  The 'block time' parameter passed to the queue receive\r
+ * function specifies that the task should be held in the Blocked state\r
+ * indefinitely to wait for data to be available on the queue.  The queue\r
+ * receive task will only leave the Blocked state when the queue send task\r
+ * writes to the queue.  As the queue send task writes to the queue every 200\r
+ * milliseconds, the queue receive task leaves the Blocked state every 200\r
+ * milliseconds, and therefore toggles the LED every 200 milliseconds.\r
  *\r
  * The Demo Specific LED Software Timer and the Button Interrupt:\r
- * The user button SW1 is configured to generate an interrupt each time it is\r
+ * The user button SW2 is configured to generate an interrupt each time it is\r
  * pressed.  The interrupt service routine switches an LED on, and resets the\r
  * LED software timer.  The LED timer has a 5000 millisecond (5 second) period,\r
  * and uses a callback function that is defined to just turn the LED off again.\r
  * Therefore, pressing the user button will turn the LED on, and the LED will\r
  * remain on until a full five seconds pass without the button being pressed.\r
+ * See the documentation page for this demo on the FreeRTOS.org web site to see\r
+ * which LED is used.\r
  *\r
  * The Demo Specific "Check" Callback Function:\r
  * This is called each time the 'check' timer expires.  The check timer\r
  * the mainCHECK_LED definition each time it executes.  Therefore, if LED\r
  * mainCHECK_LED is toggling every three seconds, then no error have been found.\r
  * If LED mainCHECK_LED is toggling every 500ms, then at least one errors has\r
- * been found.  The task in which the error was discovered is displayed at the\r
- * bottom of the "task stats" page that is served by the embedded web server.\r
+ * been found.  The variable pcStatusMessage is set to a string that indicates\r
+ * which task reported an error.  See the documentation page for this demo on\r
+ * the FreeRTOS.org web site to see which LED in the 7 segment display is used.\r
+ *\r
+ * The Demo Specific "Digit Counter" Callback Function:\r
+ * This is called each time the 'digit counter' timer expires.  It causes the\r
+ * digits 0 to 9 to be displayed in turn as the first character of the two\r
+ * character display.  The LEDs in the other digit of the two character\r
+ * display are used as general purpose LEDs, as described in this comment block.\r
  *\r
  * The Demo Specific Idle Hook Function:\r
  * The idle hook function demonstrates how to query the amount of FreeRTOS heap\r
  * space that is remaining (see vApplicationIdleHook() defined in this file).\r
  *\r
- * The Web Server Task:\r
- * The IP address used by the SmartFusion target is configured by the\r
- * definitions configIP_ADDR0 to configIP_ADDR3, which are located in the\r
- * FreeRTOSConfig.h header file.  See the documentation page for this example\r
- * on the http://www.FreeRTOS.org web site for further connection information.\r
+ * The Demo Specific Tick Hook Function:\r
+ * The tick hook function is used to test the interrupt safe software timer\r
+ * functionality.\r
  */\r
 \r
 /* Kernel includes. */\r
 #include "QPeek.h"\r
 #include "recmutex.h"\r
 #include "TimerDemo.h"\r
-\r
-/* Priorities at which the tasks are created. */\r
-#define mainQUEUE_RECEIVE_TASK_PRIORITY                ( tskIDLE_PRIORITY + 2 )\r
-#define        mainQUEUE_SEND_TASK_PRIORITY            ( tskIDLE_PRIORITY + 1 )\r
+#include "comtest2.h"\r
+#include "PollQ.h"\r
+#include "countsem.h"\r
+#include "dynamic.h"\r
 \r
 /* The rate at which data is sent to the queue, specified in milliseconds, and\r
 converted to ticks using the portTICK_RATE_MS constant. */\r
-#define mainQUEUE_SEND_FREQUENCY_MS                    ( 200 / portTICK_RATE_MS )\r
+#define mainQUEUE_SEND_FREQUENCY_MS    ( 200 / portTICK_RATE_MS )\r
 \r
 /* The number of items the queue can hold.  This is 1 as the receive task\r
 will remove items as they are added, meaning the send task should always find\r
 the queue empty. */\r
 #define mainQUEUE_LENGTH                       ( 1 )\r
 \r
-/* The LED toggled by the check timer callback function. */\r
+/* The LED toggled by the check timer callback function.  This is an LED in the\r
+second digit of the two digit 7 segment display.  See the documentation page\r
+for this demo on the FreeRTOS.org web site to see which LED this relates to. */\r
 #define mainCHECK_LED                          0x07UL\r
 \r
-/* The LED toggle by the queue receive task. */\r
-#define mainTASK_CONTROLLED_LED                0x8000UL\r
+/* The LED toggle by the queue receive task.  This is an LED in the second digit\r
+of the two digit 7 segment display.  See the documentation page for this demo on\r
+the FreeRTOS.org web site to see which LED this relates to. */\r
+#define mainTASK_CONTROLLED_LED                0x06UL\r
 \r
 /* The LED turned on by the button interrupt, and turned off by the LED timer.\r
-Although it looks like this value is the same as that defined for\r
-mainTASK_CONTROLLED_LED, the two LEDs are on different ports. */\r
-#define mainTIMER_CONTROLLED_LED       0x8000UL\r
+This is an LED in the second digit of the two digit 7 segment display.  See the\r
+documentation page for this demo on the FreeRTOS.org web site to see which LED\r
+this relates to. */\r
+#define mainTIMER_CONTROLLED_LED       0x05UL\r
+\r
+/* The LED used by the comtest tasks. See the comtest.c file for more\r
+information.  The LEDs used by the comtest task are in the second digit of the\r
+two digit 7 segment display.  See the documentation page for this demo on the\r
+FreeRTOS.org web site to see which LEDs this relates to. */\r
+#define mainCOM_TEST_LED                       ( 3 )\r
 \r
 /* Constant used by the standard timer test functions. */\r
 #define mainTIMER_TEST_PERIOD          ( 50 )\r
 \r
-/* Priorities used by the various different tasks. */\r
+/* Priorities used by the various different standard demo tasks. */\r
 #define mainCHECK_TASK_PRIORITY                ( configMAX_PRIORITIES - 1 )\r
 #define mainQUEUE_POLL_PRIORITY                ( tskIDLE_PRIORITY + 1 )\r
 #define mainSEM_TEST_PRIORITY          ( tskIDLE_PRIORITY + 1 )\r
@@ -191,21 +211,36 @@ mainTASK_CONTROLLED_LED, the two LEDs are on different ports. */
 #define mainFLASH_TASK_PRIORITY                ( tskIDLE_PRIORITY + 1 )\r
 #define mainINTEGER_TASK_PRIORITY   ( tskIDLE_PRIORITY )\r
 #define mainGEN_QUEUE_TASK_PRIORITY    ( tskIDLE_PRIORITY )\r
+#define mainCOM_TEST_PRIORITY          ( tskIDLE_PRIORITY + 2 )\r
+\r
+/* Priorities defined in this main-full.c file. */\r
+#define mainQUEUE_RECEIVE_TASK_PRIORITY                ( tskIDLE_PRIORITY + 2 )\r
+#define        mainQUEUE_SEND_TASK_PRIORITY            ( tskIDLE_PRIORITY + 1 )\r
 \r
 /* The period at which the check timer will expire, in ms, provided no errors\r
-have been reported by any of the standard demo tasks. */\r
-#define mainCHECK_TIMER_PERIOD_MS      ( 3000UL / portTICK_RATE_MS )\r
+have been reported by any of the standard demo tasks.  ms are converted to the\r
+equivalent in ticks using the portTICK_RATE_MS constant. */\r
+#define mainCHECK_TIMER_PERIOD_MS                      ( 3000UL / portTICK_RATE_MS )\r
 \r
 /* The period at which the check timer will expire, in ms, if an error has been\r
-reported in one of the standard demo tasks. */\r
-#define mainERROR_CHECK_TIMER_PERIOD_MS ( 500UL / portTICK_RATE_MS )\r
+reported in one of the standard demo tasks.  ms are converted to the equivalent\r
+in ticks using the portTICK_RATE_MS constant. */\r
+#define mainERROR_CHECK_TIMER_PERIOD_MS        ( 500UL / portTICK_RATE_MS )\r
+\r
+/* The period at which the digit counter timer will expire, in ms, and converted\r
+to ticks using the portTICK_RATE_MS constant. */\r
+#define mainDIGIT_COUNTER_TIMER_PERIOD_MS      ( 250UL / portTICK_RATE_MS )\r
 \r
 /* The LED will remain on until the button has not been pushed for a full\r
 5000ms. */\r
-#define mainLED_TIMER_PERIOD_MS                ( 5000UL / portTICK_RATE_MS )\r
+#define mainLED_TIMER_PERIOD_MS                                ( 5000UL / portTICK_RATE_MS )\r
 \r
 /* A zero block time. */\r
-#define mainDONT_BLOCK                         ( 0UL )\r
+#define mainDONT_BLOCK                                         ( 0UL )\r
+\r
+/* Baud rate used by the comtest tasks. */\r
+#define mainCOM_TEST_BAUD_RATE                         ( 115200UL )\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -214,14 +249,14 @@ reported in one of the standard demo tasks. */
 static void prvSetupHardware( void );\r
 \r
 /*\r
- * The tasks as described in the comments at the top of this file.\r
+ * The application specific (not common demo) tasks as described in the comments\r
+ * at the top of this file.\r
  */\r
 static void prvQueueReceiveTask( void *pvParameters );\r
 static void prvQueueSendTask( void *pvParameters );\r
 \r
 /*\r
- * The LED timer callback function.  This does nothing but switch the red LED\r
- * off.\r
+ * The LED timer callback function.  This does nothing but switch an LED off.\r
  */\r
 static void prvLEDTimerCallback( xTimerHandle xTimer );\r
 \r
@@ -230,6 +265,11 @@ static void prvLEDTimerCallback( xTimerHandle xTimer );
  */\r
 static void prvCheckTimerCallback( xTimerHandle xTimer );\r
 \r
+/*\r
+ * The digit counter callback function, as described at the top of this file.\r
+ */\r
+static void prvDigitCounterTimerCallback( xTimerHandle xTimer );\r
+\r
 /*\r
  * This is not a 'standard' partest function, so the prototype is not in\r
  * partest.h, and is instead included here.\r
@@ -245,7 +285,11 @@ static xQueueHandle xQueue = NULL;
 function. */\r
 static xTimerHandle xLEDTimer = NULL;\r
 \r
-/* The check timer.  This uses prvCheckTimerCallback() as it's callback\r
+/* The digit counter software timer.  This displays a counting digit on one half\r
+of the seven segment displays. */\r
+static xTimerHandle xDigitCounterTimer = NULL;\r
+\r
+/* The check timer.  This uses prvCheckTimerCallback() as its callback\r
 function. */\r
 static xTimerHandle xCheckTimer = NULL;\r
 \r
@@ -266,7 +310,7 @@ int main(void)
 \r
        if( xQueue != NULL )\r
        {\r
-               /* Start the three application specific demo tasks, as described in the\r
+               /* Start the two application specific demo tasks, as described in the\r
                comments at the top of this     file. */\r
                xTaskCreate( prvQueueReceiveTask, ( signed char * ) "Rx", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );\r
                xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );\r
@@ -290,7 +334,18 @@ int main(void)
                                                                        prvCheckTimerCallback                           /* The callback function that inspects the status of all the other tasks. */\r
                                                                  );\r
 \r
-               /* Create a lot of 'standard demo' tasks. */\r
+               /* Create the software timer that performs the 'digit counting'\r
+               functionality, as described at the top of this file. */\r
+               xDigitCounterTimer = xTimerCreate( ( const signed char * ) "DigitCounter",      /* A text name, purely to help debugging. */\r
+                                                                       ( mainDIGIT_COUNTER_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
+                                                                       prvDigitCounterTimerCallback                                    /* The callback function that inspects the status of all the other tasks. */\r
+                                                                 );            \r
+               \r
+               /* Create a lot of 'standard demo' tasks.  Over 40 tasks are created in\r
+               this demo.  For a much simpler demo, select the 'blinky' build\r
+               configuration. */\r
                vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
                vCreateBlockTimeTasks();\r
                vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
@@ -299,7 +354,11 @@ int main(void)
                vStartQueuePeekTasks();\r
                vStartRecursiveMutexTasks();\r
                vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
-\r
+               vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainCOM_TEST_BAUD_RATE, mainCOM_TEST_LED );\r
+               vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
+               vStartCountingSemaphoreTasks();\r
+               vStartDynamicPriorityTasks();\r
+               \r
                /* The suicide tasks must be created last, as they need to know how many\r
                tasks were running prior to their creation in order to ascertain whether\r
                or not the correct/expected number of tasks are running at any given\r
@@ -358,11 +417,31 @@ static void prvCheckTimerCallback( xTimerHandle xTimer )
                pcStatusMessage = "Error: RecMutex\r\n";\r
        }\r
 \r
+       if( xAreComTestTasksStillRunning() != pdPASS )\r
+       {\r
+               pcStatusMessage = "Error: ComTest\r\n";\r
+       }\r
+       \r
        if( xAreTimerDemoTasksStillRunning( ( mainCHECK_TIMER_PERIOD_MS ) ) != pdTRUE )\r
        {\r
                pcStatusMessage = "Error: TimerDemo";\r
        }\r
 \r
+       if( xArePollingQueuesStillRunning() != pdTRUE )\r
+       {\r
+               pcStatusMessage = "Error: PollQueue";\r
+       }\r
+\r
+       if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE )\r
+       {\r
+               pcStatusMessage = "Error: CountSem";\r
+       }\r
+       \r
+       if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )\r
+       {\r
+               pcStatusMessage = "Error: DynamicPriority";\r
+       }\r
+       \r
        /* Toggle the check LED to give an indication of the system status.  If\r
        the LED toggles every mainCHECK_TIMER_PERIOD_MS milliseconds then\r
        everything is ok.  A faster toggle indicates an error. */\r
@@ -385,14 +464,29 @@ static void prvCheckTimerCallback( xTimerHandle xTimer )
 static void prvLEDTimerCallback( xTimerHandle xTimer )\r
 {\r
        /* The timer has expired - so no button pushes have occurred in the last\r
-       five seconds - turn the LED off.  NOTE - accessing the LED port should use\r
-       a critical section because it is accessed from multiple tasks, and the\r
-       button interrupt - in this trivial case, for simplicity, the critical\r
-       section is omitted.\r
+       five seconds - turn the LED off. */\r
+       vParTestSetLED( mainTIMER_CONTROLLED_LED, pdFALSE );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDigitCounterTimerCallback( xTimerHandle xTimer )\r
+{\r
+/* Define the bit patterns that display numbers on the seven segment display. */\r
+static const unsigned short usNumbersPatterns[] = { 0xC000U, 0xF900U, 0xA400U, 0xB000U, 0x9900U, 0x9200U, 0x8200U, 0xF800U, 0x8000U, 0x9000U };\r
+static long lCounter = 0L;\r
+const long lNumberOfDigits = 10L;\r
+\r
+       /* Display the next number, counting up. */\r
+       FM3_GPIO->PDOR1 = usNumbersPatterns[ lCounter ];\r
+\r
+       /* Move onto the next digit. */ \r
+       lCounter++;\r
        \r
-       A ParTest function is not used to set the LED as the LED is not on the seven\r
-       segment display that the ParTest functions control. */\r
-       FM3_GPIO->PDOR1 |= mainTIMER_CONTROLLED_LED;\r
+       /* Ensure the counter does not go off the end of the array. */\r
+       if( lCounter >= lNumberOfDigits )\r
+       {\r
+               lCounter = 0L;\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -404,7 +498,7 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        /* The button was pushed, so ensure the LED is on before resetting the\r
        LED timer.  The LED timer will turn the LED off if the button is not\r
        pushed within 5000ms. */\r
-       FM3_GPIO->PDOR1 &= ~mainTIMER_CONTROLLED_LED;\r
+       vParTestSetLEDFromISR( mainTIMER_CONTROLLED_LED, pdTRUE );\r
 \r
        /* This interrupt safe FreeRTOS function can be called from this interrupt\r
        because the interrupt priority is below the\r
@@ -431,11 +525,12 @@ const unsigned long ulValueToSend = 100UL;
 \r
        /* The timer command queue will have been filled when the timer test tasks\r
        were created in main() (this is part of the test they perform).  Therefore,\r
-       while the check and count timers can be created in main(), they cannot be\r
-       started from main().  Once the scheduler has started, the timer service\r
-       task will drain the command queue, and now the check and OLED timers can be\r
-       started successfully. */\r
+       while the check and digit counter timers can be created in main(), they\r
+       cannot be started from main().  Once the scheduler has started, the timer\r
+       service task will drain the command queue, and now the check and digit\r
+       counter timers can be started successfully. */\r
        xTimerStart( xCheckTimer, portMAX_DELAY );\r
+       xTimerStart( xDigitCounterTimer, portMAX_DELAY );\r
 \r
        /* Initialise xNextWakeTime - this only needs to be done once. */\r
        xNextWakeTime = xTaskGetTickCount();\r
@@ -553,19 +648,11 @@ volatile size_t xFreeStackSpace;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-char *pcGetTaskStatusMessage( void )\r
+void vApplicationTickHook( void )\r
 {\r
-       /* Not bothered about a critical section here although technically because\r
-       of the task priorities the pointer could change it will be atomic if not\r
-       near atomic and its not critical. */\r
-       if( pcStatusMessage == NULL )\r
-       {\r
-               return "All tasks running without error";\r
-       }\r
-       else\r
-       {\r
-               return ( char * ) pcStatusMessage;\r
-       }\r
-}\r
+       /* Call the periodic timer test, which tests the timer API functions that\r
+       can be called from an ISR. */\r
+       vTimerPeriodicISRTests();\r
+}      \r
 /*-----------------------------------------------------------*/\r
 \r