]> git.sur5r.net Git - freertos/commitdiff
Extend FX16 functionality.
authorRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sat, 31 Jan 2009 12:56:33 +0000 (12:56 +0000)
committerRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Sat, 31 Jan 2009 12:56:33 +0000 (12:56 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@658 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/MB96350_Softune_Dice_Kit/DiceTask.c
Demo/MB96350_Softune_Dice_Kit/flash.c
Demo/MB96350_Softune_Dice_Kit/vectors.c

index 849b4b723fd53dc014c722a7fa202dc5b0d65bbc..33deebf10a4022043a104a67fa4b1d84d0938462 100644 (file)
 #include "task.h"\r
 #include "semphr.h"\r
 \r
-#define diceMIN    1\r
-#define diceMAX    6\r
-#define diceRUN_MIN  600000L\r
-#define diceRUN_MAX 1200000L\r
+#define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms            ( 20 )\r
+#define diceRUN_TIME   ( 2000 / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )\r
 \r
-#define diceSTATE_STOPPED              0\r
-#define diceSTATE_STARTUP              1\r
-#define diceSTATE_RUNNING              2\r
 \r
 #define diceEND_DELAY                  ( 5000 / portTICK_RATE_MS )\r
 \r
@@ -80,61 +75,72 @@ extern volatile unsigned char *pucDisplayOutput[ 2 ];
 \r
 void vDiceTask( void *pvParameters )\r
 {\r
-char cDiceState = diceSTATE_STOPPED;\r
 unsigned char ucDiceValue, ucIndex;\r
-unsigned long ulDiceRunTime, ulDiceDelay, ulDiceDelayReload;\r
-extern void vToggleFlashTaskSuspendState( void );\r
+unsigned long ulDiceRunTime;\r
+extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks );\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
        ucIndex = ( unsigned char ) pvParameters;\r
+       \r
+       /* A binary semaphore is used to signal button push events.  Create the\r
+       semaphore before it is used. */\r
        vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );\r
-       srand( ( unsigned char ) diceRUN_MIN );\r
+\r
+       /* 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
+       prvButtonHit( ucIndex, 0 );\r
+\r
+       /* Seed the random number generator. */\r
+       srand( ( unsigned char ) diceRUN_TIME );\r
 \r
        for( ;; )\r
        {\r
-               switch( cDiceState )\r
+               /* Wait for a button push.  This task will enter the Blocked state\r
+               (will not run again) until after a button has been pushed. */\r
+               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
+\r
+               /* Suspend the flash tasks so this task has exclusive access to the\r
+               display. */\r
+               vSuspendFlashTasks( ucIndex, pdTRUE );\r
+\r
+               while( ulDiceRunTime > 0 )\r
+               {\r
+                       ulDiceRunTime--;\r
+\r
+                       /* Generate and display a random number. */\r
+                       ucDiceValue = rand() % 6 + 1;\r
+                       dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];\r
+\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
+               }\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
+               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
-                       case diceSTATE_STOPPED:\r
-\r
-                               prvButtonHit( ucIndex, portMAX_DELAY );\r
-                               ulDiceRunTime = diceRUN_MIN;                            \r
-                               cDiceState = diceSTATE_RUNNING;\r
-                               ulDiceDelay = 1;\r
-                               ulDiceDelayReload = 1;\r
-                               cDiceState = diceSTATE_RUNNING;\r
-                               if( ucIndex == 0 )\r
-                               {\r
-                                       vToggleFlashTaskSuspendState();\r
-                               }\r
-\r
-                               break;\r
-\r
-                       case diceSTATE_RUNNING:\r
-\r
-                               ulDiceRunTime--;\r
-                               ulDiceDelay--;\r
-\r
-                               if( !ulDiceDelay )\r
-                               {\r
-                                       ucDiceValue = rand() % 6 + 1;\r
-                                       dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];\r
-                                       ulDiceDelayReload = ulDiceDelayReload + 100;\r
-                                       ulDiceDelay = ulDiceDelayReload;\r
-                               }\r
-\r
-                               if( ulDiceRunTime == 0 )\r
-                               {\r
-                                       dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ rand() % 6 + 1 ];\r
-                                       cDiceState = diceSTATE_STOPPED;\r
-\r
-                                       if( ucIndex == 0 )\r
-                                       {\r
-                                               vTaskDelay( diceEND_DELAY );\r
-                                               *pucDisplayOutput[ ucIndex ] = 0xff;\r
-                                               vToggleFlashTaskSuspendState();\r
-                                       }\r
-                               }\r
-\r
-                               break;\r
+                       *pucDisplayOutput[ ucIndex ] = 0xff;\r
+                       vSuspendFlashTasks( ucIndex, pdFALSE );\r
                }\r
        }\r
 }\r
index d8bd03414d18af2ea7edc80e254055b0caf91540..bbf97f59524ecfe264d13c246878230871eda235 100644 (file)
 /* Scheduler include files. */\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
+#include "croutine.h"\r
 \r
 /* Demo program include files. */\r
 #include "partest.h"\r
 #include "flash.h"\r
 \r
 #define ledSTACK_SIZE          configMINIMAL_STACK_SIZE\r
-#define ledNUMBER_OF_LEDS      ( 3 )\r
+#define ledNUMBER_OF_LEDS      ( 7 )\r
 #define ledFLASH_RATE_BASE     ( ( portTickType ) 333 )\r
 \r
-/* Variable used by the created tasks to calculate the LED number to use, and\r
-the rate at which they should flash the LED. */\r
-static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0;\r
+#define ledMAX_FLASH_CO_ROUTINES       7\r
+#define ledCO_ROUTINE_PRIORITY         0\r
 \r
 /* The task that is created three times. */\r
-static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters );\r
+static void vLEDFlashTask( void *pvParameters );\r
+static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned short usIndex );\r
+\r
+/* This task is created once, but itself creates 7 co-routines. */\r
+static void vLEDCoRoutineControlTask( void *pvParameters );\r
 \r
 static xTaskHandle xFlashTaskHandles[ ledNUMBER_OF_LEDS ] = { 0 };\r
+static xTaskHandle xCoroutineTask;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
 void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority )\r
 {\r
-signed portBASE_TYPE xLEDTask;\r
+signed short sLEDTask;\r
 \r
-       /* Create the three tasks. */\r
-       for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )\r
+       /* Create the three tasks that flash segments on the first LED. */\r
+       for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask )\r
        {\r
                /* Spawn the task. */\r
-               xTaskCreate( vLEDFlashTask, ( signed portCHAR * ) "LEDx", ledSTACK_SIZE, NULL, uxPriority, &( xFlashTaskHandles[ xLEDTask ] ) );\r
+               xTaskCreate( vLEDFlashTask, ( signed char * ) "LEDt", ledSTACK_SIZE, ( void * ) sLEDTask, uxPriority, &( xFlashTaskHandles[ sLEDTask ] ) );\r
        }\r
+\r
+       /* Create the task in which the co-routines run. */\r
+       xTaskCreate( vLEDCoRoutineControlTask, ( signed char * ) "LEDc", ledSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xCoroutineTask );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vSuspendFlashTasks( short sSuspendTasks )\r
+void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks )\r
 {\r
-signed portBASE_TYPE xLEDTask;\r
+short sLEDTask;\r
 \r
-       for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )\r
+       if( ucIndex == 0 )\r
        {\r
-               if( xFlashTaskHandles[ xLEDTask ] != NULL )\r
+               for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask )\r
                {\r
-                       if( sSuspendTasks == pdTRUE )\r
+                       if( xFlashTaskHandles[ sLEDTask ] != NULL )\r
                        {\r
-                               vTaskSuspend( xFlashTaskHandles[ xLEDTask ] );\r
-                       }\r
-                       else\r
-                       {\r
-                               vTaskResume( xFlashTaskHandles[ xLEDTask ] );\r
+                               if( sSuspendTasks == pdTRUE )\r
+                               {\r
+                                       vTaskSuspend( xFlashTaskHandles[ sLEDTask ] );\r
+                               }\r
+                               else\r
+                               {\r
+                                       vTaskResume( xFlashTaskHandles[ sLEDTask ] );\r
+                               }\r
                        }\r
                }\r
        }\r
+       else\r
+       {\r
+               if( sSuspendTasks == pdTRUE )\r
+               {\r
+                       vTaskSuspend( xCoroutineTask );\r
+               }\r
+               else\r
+               {\r
+                       vTaskResume( xCoroutineTask );\r
+               }\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static portTASK_FUNCTION( vLEDFlashTask, pvParameters )\r
+static void vLEDFlashTask( void * pvParameters )\r
 {\r
 portTickType xFlashRate, xLastFlashTime;\r
-unsigned portBASE_TYPE uxLED;\r
+unsigned short usLED;\r
 \r
-       /* The parameters are not used. */\r
-       ( void ) pvParameters;\r
-\r
-       /* Calculate the LED and flash rate. */\r
-       portENTER_CRITICAL();\r
-       {\r
-               /* See which of the eight LED's we should use. */\r
-               uxLED = uxFlashTaskNumber;\r
-\r
-               /* Update so the next task uses the next LED. */\r
-               uxFlashTaskNumber++;\r
-       }\r
-       portEXIT_CRITICAL();\r
+       /* The LED to flash is passed in as the task parameter. */\r
+       usLED = ( unsigned short ) pvParameters;\r
 \r
-       xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) uxLED );\r
+       /* Calculate the rate at which this task is going to toggle its LED. */\r
+       xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) usLED );\r
        xFlashRate /= portTICK_RATE_MS;\r
 \r
        /* We will turn the LED on and off again in the delay period, so each\r
@@ -154,11 +166,57 @@ unsigned portBASE_TYPE uxLED;
        {\r
                /* Delay for half the flash period then turn the LED on. */\r
                vTaskDelayUntil( &xLastFlashTime, xFlashRate );\r
-               vParTestToggleLED( uxLED );\r
+               vParTestToggleLED( usLED );\r
 \r
                /* Delay for half the flash period then turn the LED off. */\r
                vTaskDelayUntil( &xLastFlashTime, xFlashRate );\r
-               vParTestToggleLED( uxLED );\r
+               vParTestToggleLED( usLED );\r
        }\r
-} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vLEDCoRoutineControlTask( void *pvParameters )\r
+{\r
+unsigned short usCoroutine;\r
+\r
+       ( void ) pvParameters;\r
+\r
+       for( usCoroutine = 0; usCoroutine < ledMAX_FLASH_CO_ROUTINES; usCoroutine++ )\r
+       {\r
+               xCoRoutineCreate( prvFixedDelayCoRoutine, ledCO_ROUTINE_PRIORITY, usCoroutine );\r
+       }\r
+\r
+       for( ;; )\r
+       {\r
+               vCoRoutineSchedule();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned short usIndex )\r
+{\r
+/* The usIndex parameter of the co-routine function is used as an index into\r
+the xFlashRates array to obtain the delay period to use. */\r
+static const portTickType xFlashRates[ ledMAX_FLASH_CO_ROUTINES ] = { 150 / portTICK_RATE_MS,\r
+                                                                                                                               300 / portTICK_RATE_MS,\r
+                                                                                                                               450 / portTICK_RATE_MS,\r
+                                                                                                                               600 / portTICK_RATE_MS,\r
+                                                                                                                               750 / portTICK_RATE_MS,\r
+                                                                                                                               900 / portTICK_RATE_MS,\r
+                                                                                                                               1050 / portTICK_RATE_MS };\r
+\r
+       /* Co-routines MUST start with a call to crSTART. */\r
+       crSTART( xHandle );\r
+\r
+       for( ;; )\r
+       {\r
+               vParTestToggleLED( usIndex + 8 );\r
+               crDELAY( xHandle, xFlashRates[ usIndex ] );\r
+       }\r
+\r
+       /* Co-routines MUST end with a call to crEND. */\r
+       crEND();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 \r
index 193db79c8969f5d7114523a99d9b1cd53896babc..6276081f0b43216f0120d905030a10109e26f19e 100644 (file)
@@ -34,10 +34,10 @@ void InitIrqLevels(void)
     ICR = (irq << 8) | DEFAULT_ILM_MASK;\r
   }\r
 \r
-       ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY;                   /* Reload Timer 0 */\r
-       ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY;                   /* Delayed interrupt of 16FX Family */\r
-       ICR = ( (24 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 );   /* INT8 */\r
-       ICR = ( (25 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 );   /* INT9 */      \r
+       ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY;   /* Reload Timer 0 */\r
+       ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY;   /* Delayed interrupt of 16FX Family */\r
+       ICR = ( (24 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY;   /* INT8 */\r
+       ICR = ( (25 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY;   /* INT9 */      \r
 }\r
 \r
 /*---------------------------------------------------------------------------\r