]> git.sur5r.net Git - freertos/blobdiff - Demo/MB96350_Softune_Dice_Kit/DiceTask.c
Add STM32F0 demo.
[freertos] / Demo / MB96350_Softune_Dice_Kit / DiceTask.c
index 33deebf10a4022043a104a67fa4b1d84d0938462..4fcc0efecc7ebf12bf059b58e37a972f7eb82872 100644 (file)
 /*\r
-       FreeRTOS.org V5.1.1 - Copyright (C) 2003-2008 Richard Barry.\r
+    FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
+       \r
 \r
-       This file is part of the FreeRTOS.org distribution.\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
+     *    Complete, revised, and edited pdf reference manuals are also       *\r
+     *    available.                                                         *\r
+     *                                                                       *\r
+     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
+     *    ensuring you get running as quickly as possible and with an        *\r
+     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
+     *    the FreeRTOS project to continue with its mission of providing     *\r
+     *    professional grade, cross platform, de facto standard solutions    *\r
+     *    for microcontrollers - completely free of charge!                  *\r
+     *                                                                       *\r
+     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
+     *                                                                       *\r
+     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+     *                                                                       *\r
+    ***************************************************************************\r
 \r
-       FreeRTOS.org is free software; you can redistribute it and/or modify\r
-       it under the terms of the GNU General Public License as published by\r
-       the Free Software Foundation; either version 2 of the License, or\r
-       (at your option) any later version.\r
 \r
-       FreeRTOS.org is distributed in the hope that it will be useful,\r
-       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-       GNU General Public License for more details.\r
+    This file is part of the FreeRTOS distribution.\r
 \r
-       You should have received a copy of the GNU General Public License\r
-       along with FreeRTOS.org; if not, write to the Free Software\r
-       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+    >>>NOTE<<< The modification to the GPL is included to allow you to\r
+    distribute a combined work that includes FreeRTOS without being obliged to\r
+    provide the source code for proprietary components outside of the FreeRTOS\r
+    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
+    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+    more details. You should have received a copy of the GNU General Public\r
+    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+    by writing to Richard Barry, contact details for whom are available on the\r
+    FreeRTOS WEB site.\r
 \r
-       A special exception to the GPL can be applied should you wish to distribute\r
-       a combined work that includes FreeRTOS.org, without being obliged to provide\r
-       the source code for any proprietary components.  See the licensing section \r
-       of http://www.FreeRTOS.org for full details of how and when the exception\r
-       can be applied.\r
+    1 tab == 4 spaces!\r
 \r
-    ***************************************************************************\r
-    ***************************************************************************\r
-    *                                                                         *\r
-    * SAVE TIME AND MONEY!  We can port FreeRTOS.org to your own hardware,    *\r
-    * and even write all or part of your application on your behalf.          *\r
-    * See http://www.OpenRTOS.com for details of the services we provide to   *\r
-    * expedite your project.                                                  *\r
-    *                                                                         *\r
-    ***************************************************************************\r
-    ***************************************************************************\r
+    http://www.FreeRTOS.org - Documentation, latest information, license and\r
+    contact details.\r
 \r
-       Please ensure to read the configuration and relevant port sections of the\r
-       online documentation.\r
+    http://www.SafeRTOS.com - A version that is certified for use in safety\r
+    critical systems.\r
 \r
-       http://www.FreeRTOS.org - Documentation, latest information, license and \r
-       contact details.\r
+    http://www.OpenRTOS.com - Commercial support, development, porting,\r
+    licensing and training services.\r
+*/\r
 \r
-       http://www.SafeRTOS.com - A version that is certified for use in safety \r
-       critical systems.\r
 \r
-       http://www.OpenRTOS.com - Commercial support, development, porting, \r
-       licensing and training services.\r
-*/\r
+/* \r
+ * Defines the 'dice' tasks as described at the top of main.c\r
+ */\r
+\r
 \r
+/* Kernel includes. */\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
 #include "semphr.h"\r
 \r
-#define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms            ( 20 )\r
-#define diceRUN_TIME   ( 2000 / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )\r
+/* Delays used within the dice functionality.  All delays are defined in milliseconds. */\r
+#define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms            ( 20 / portTICK_RATE_MS )\r
+#define diceSHAKE_TIME                                                 ( ( 2000 / portTICK_RATE_MS ) / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )\r
+#define diceSHORT_PAUSE_BEFORE_SHAKE                   ( 250 / portTICK_RATE_MS )\r
+#define diceDELAY_WHILE_DISPLAYING_RESULT              ( 5000 / portTICK_RATE_MS )\r
 \r
+/* Macro to access the display ports. */\r
+#define dice7SEG_Value( x )            ( *( pucDisplayOutput[ x ] ) )\r
 \r
-#define diceEND_DELAY                  ( 5000 / portTICK_RATE_MS )\r
-\r
-#define dice7SEG_Value( x )            *( pucDisplayOutput[ x ] )\r
-\r
+/* Checks the semaphore use to communicate button push events.  A block time\r
+can be specified - this is the time to wait for a button push to occur should\r
+one have not already occurred. */\r
 #define prvButtonHit( ucIndex, xTicksToWait ) xSemaphoreTake( xSemaphores[ ucIndex ], xTicksToWait )\r
 \r
+/* Defines the outputs required for each digit on the display. */\r
 static const char cDisplaySegments[ 2 ][ 11 ] =\r
 {\r
-       { 0x48, 0xeb, 0x8c, 0x89, 0x2b, 0x19, 0x18, 0xcb, 0x08, 0x09, 0xf7 },\r
-       { 0xa0, 0xf3, 0xc4, 0xc1, 0x93, 0x89, 0x88, 0xe3, 0x80, 0x81, 0x7f }\r
+       { 0x48, 0xeb, 0x8c, 0x89, 0x2b, 0x19, 0x18, 0xcb, 0x08, 0x09, 0xf7 }, /* Left display. */\r
+       { 0xa0, 0xf3, 0xc4, 0xc1, 0x93, 0x89, 0x88, 0xe3, 0x80, 0x81, 0x7f }  /* Right display. */\r
 };\r
 \r
+/* The semaphores used to communicate button push events between the button\r
+input interrupt handlers and the dice tasks.  Two dice tasks are created so two\r
+semaphores are required. */\r
 static xSemaphoreHandle xSemaphores[ 2 ] = { 0 };\r
 \r
+/* Defines the ports used to write to the display.  This variable is defined in\r
+partest.c, which contains the LED set/clear/toggle functions. */\r
 extern volatile unsigned char *pucDisplayOutput[ 2 ];\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
+/* \r
+ * Defines the 'dice' tasks as described at the top of main.c\r
+ */\r
 void vDiceTask( void *pvParameters )\r
 {\r
 unsigned char ucDiceValue, ucIndex;\r
 unsigned long ulDiceRunTime;\r
 extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );\r
 \r
+\r
+\r
        /* Two instances of this task are created so the task parameter is used\r
-       to pass in an index that allows this task to know which file scope variables\r
-       it should use.  Cast this index into a usable type. */\r
+       to pass in a constant that indicates whether this task is controlling\r
+       the left side or right side display.  The constant is used as an index\r
+       into the arrays defined at file scope within this file. */\r
        ucIndex = ( unsigned char ) pvParameters;\r
        \r
        /* A binary semaphore is used to signal button push events.  Create the\r
@@ -91,12 +118,18 @@ extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );
        /* Make sure the semaphore starts in the wanted state - no button pushes \r
        pending. This call will just clear any button pushes that are latched.\r
        Passing in 0 as the block time means the call will not wait for any further\r
-       button pushes. */\r
+       button pushes but instead return immediately. */\r
        prvButtonHit( ucIndex, 0 );\r
 \r
        /* Seed the random number generator. */\r
-       srand( ( unsigned char ) diceRUN_TIME );\r
+       srand( ( unsigned char ) diceSHAKE_TIME );\r
+\r
+\r
 \r
+\r
+       /* Start the task proper.  A loop will be performed each time a button is\r
+       pushed.  The task will remain in the blocked state (sleeping) until a \r
+       button is pushed. */\r
        for( ;; )\r
        {\r
                /* Wait for a button push.  This task will enter the Blocked state\r
@@ -104,13 +137,21 @@ extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );
                prvButtonHit( ucIndex, portMAX_DELAY );\r
                \r
                /* The next line will only execute after a button has been pushed -\r
-               initialise the variable used to shake the dice. */\r
-               ulDiceRunTime = diceRUN_TIME;;                          \r
+               initialise the variable used to control the time the dice is shaken\r
+               for. */\r
+               ulDiceRunTime = diceSHAKE_TIME;                         \r
 \r
                /* Suspend the flash tasks so this task has exclusive access to the\r
                display. */\r
                vSuspendFlashTasks( ucIndex, pdTRUE );\r
 \r
+               /* Clear the display and pause for a short time, before starting to\r
+               shake. */\r
+               *pucDisplayOutput[ ucIndex ] = 0xff;\r
+               vTaskDelay( diceSHORT_PAUSE_BEFORE_SHAKE );\r
+\r
+               /* Keep generating and displaying random numbers until the shake time\r
+               expires. */\r
                while( ulDiceRunTime > 0 )\r
                {\r
                        ulDiceRunTime--;\r
@@ -121,31 +162,35 @@ extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );
 \r
                        /* Block/sleep for a very short time before generating the next\r
                        random number. */\r
-                       vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms / portTICK_RATE_MS );\r
+                       vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms );\r
                }\r
 \r
-               /* Wait for a short time before resuming (un-suspending) the flash \r
-               task.  The flash tasks are only restarted if a button is not pushed\r
-               during this delay - if a button is pushed then the dice are shaken\r
-               again. \r
 \r
-               First...clear any button pushes that are already pending.  Again a\r
-               block time of zero is used so the function does not wait for any \r
-               pushes. */\r
+\r
+               /* Clear any button pushes that are pending because a button bounced, or\r
+               was pressed while the dice were shaking.  Again a block time of zero is \r
+               used so the function does not wait for any pushes but instead returns\r
+               immediately. */\r
                prvButtonHit( ucIndex, 0 );\r
 \r
-               /* Second...peek the semaphore.  This task will block/sleep until a\r
-               button is pushed again, but because the peek function is used a \r
-               button being pushed will unblock the task but remain pending. */\r
-               if( xQueuePeek( xSemaphores[ ucIndex ], NULL, diceEND_DELAY ) == pdFALSE )\r
-               {\r
-                       *pucDisplayOutput[ ucIndex ] = 0xff;\r
-                       vSuspendFlashTasks( ucIndex, pdFALSE );\r
-               }\r
+               /* Delay for a short while to display the dice shake result.  Use a queue\r
+               peek here instead of a vTaskDelay() allows the delay to be interrupted by\r
+               a button push.  If a button is pressed xQueuePeek() will return but the\r
+               button push will remain pending to be read again at the top of this for\r
+               loop.  It is safe to uses a queue function on a semaphore handle as\r
+               semaphores are implemented as macros that uses queues, so the two are \r
+               basically the same thing. */\r
+               xQueuePeek( xSemaphores[ ucIndex ], NULL, diceDELAY_WHILE_DISPLAYING_RESULT );\r
+\r
+               /* Clear the display then resume the tasks or co-routines that were using\r
+               the segments of the display. */\r
+               *pucDisplayOutput[ ucIndex ] = 0xff;\r
+               vSuspendFlashTasks( ucIndex, pdFALSE );\r
        }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+/* Handler for the SW2 button push interrupt. */\r
 __interrupt void vExternalInt8Handler( void )\r
 {\r
 short sHigherPriorityTaskWoken = pdFALSE;\r
@@ -153,8 +198,18 @@ short sHigherPriorityTaskWoken = pdFALSE;
        /* Reset the interrupt. */\r
        EIRR1_ER8 = 0;\r
 \r
-       xSemaphoreGiveFromISR( xSemaphores[ 0 ], &sHigherPriorityTaskWoken );\r
+       /* Check the semaphore has been created before attempting to use it. */\r
+       if( xSemaphores[ configLEFT_DISPLAY ] != NULL )\r
+       {\r
+               /* Send a message via the semaphore to the dice task that controls the\r
+               left side display.  This will unblock the task if it is blocked waiting\r
+               for a button push. */\r
+               xSemaphoreGiveFromISR( xSemaphores[ configLEFT_DISPLAY ], &sHigherPriorityTaskWoken );\r
+       }\r
 \r
+       /* If sending the semaphore unblocked a task, and the unblocked task has a\r
+       priority that is higher than the currently running task, then force a context\r
+       switch. */\r
        if( sHigherPriorityTaskWoken != pdFALSE )\r
        {\r
                portYIELD_FROM_ISR();\r
@@ -162,6 +217,7 @@ short sHigherPriorityTaskWoken = pdFALSE;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+/* As per vExternalInt8Handler(), but for SW3 and the right side display. */\r
 __interrupt void vExternalInt9Handler( void )\r
 {\r
 short sHigherPriorityTaskWoken = pdFALSE;\r
@@ -169,7 +225,10 @@ short sHigherPriorityTaskWoken = pdFALSE;
        /* Reset the interrupt. */\r
        EIRR1_ER9 = 0;\r
 \r
-       xSemaphoreGiveFromISR( xSemaphores[ 1 ], &sHigherPriorityTaskWoken );\r
+       if( xSemaphores[ configRIGHT_DISPLAY ] != NULL )\r
+       {\r
+               xSemaphoreGiveFromISR( xSemaphores[ configRIGHT_DISPLAY ], &sHigherPriorityTaskWoken );\r
+       }\r
 \r
        if( sHigherPriorityTaskWoken != pdFALSE )\r
        {\r