From 51b1229641dff1595eacaf78df7b8920680bf9eb Mon Sep 17 00:00:00 2001 From: RichardBarry Date: Sat, 31 Jan 2009 12:56:33 +0000 Subject: [PATCH] Extend FX16 functionality. 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 | 114 ++++++++++--------- Demo/MB96350_Softune_Dice_Kit/flash.c | 134 ++++++++++++++++------- Demo/MB96350_Softune_Dice_Kit/vectors.c | 8 +- 3 files changed, 160 insertions(+), 96 deletions(-) diff --git a/Demo/MB96350_Softune_Dice_Kit/DiceTask.c b/Demo/MB96350_Softune_Dice_Kit/DiceTask.c index 849b4b723..33deebf10 100644 --- a/Demo/MB96350_Softune_Dice_Kit/DiceTask.c +++ b/Demo/MB96350_Softune_Dice_Kit/DiceTask.c @@ -51,14 +51,9 @@ #include "task.h" #include "semphr.h" -#define diceMIN 1 -#define diceMAX 6 -#define diceRUN_MIN 600000L -#define diceRUN_MAX 1200000L +#define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms ( 20 ) +#define diceRUN_TIME ( 2000 / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms ) -#define diceSTATE_STOPPED 0 -#define diceSTATE_STARTUP 1 -#define diceSTATE_RUNNING 2 #define diceEND_DELAY ( 5000 / portTICK_RATE_MS ) @@ -80,61 +75,72 @@ extern volatile unsigned char *pucDisplayOutput[ 2 ]; void vDiceTask( void *pvParameters ) { -char cDiceState = diceSTATE_STOPPED; unsigned char ucDiceValue, ucIndex; -unsigned long ulDiceRunTime, ulDiceDelay, ulDiceDelayReload; -extern void vToggleFlashTaskSuspendState( void ); +unsigned long ulDiceRunTime; +extern void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks ); + /* Two instances of this task are created so the task parameter is used + to pass in an index that allows this task to know which file scope variables + it should use. Cast this index into a usable type. */ ucIndex = ( unsigned char ) pvParameters; + + /* A binary semaphore is used to signal button push events. Create the + semaphore before it is used. */ vSemaphoreCreateBinary( xSemaphores[ ucIndex ] ); - srand( ( unsigned char ) diceRUN_MIN ); + + /* Make sure the semaphore starts in the wanted state - no button pushes + pending. This call will just clear any button pushes that are latched. + Passing in 0 as the block time means the call will not wait for any further + button pushes. */ + prvButtonHit( ucIndex, 0 ); + + /* Seed the random number generator. */ + srand( ( unsigned char ) diceRUN_TIME ); for( ;; ) { - switch( cDiceState ) + /* Wait for a button push. This task will enter the Blocked state + (will not run again) until after a button has been pushed. */ + prvButtonHit( ucIndex, portMAX_DELAY ); + + /* The next line will only execute after a button has been pushed - + initialise the variable used to shake the dice. */ + ulDiceRunTime = diceRUN_TIME;; + + /* Suspend the flash tasks so this task has exclusive access to the + display. */ + vSuspendFlashTasks( ucIndex, pdTRUE ); + + while( ulDiceRunTime > 0 ) + { + ulDiceRunTime--; + + /* Generate and display a random number. */ + ucDiceValue = rand() % 6 + 1; + dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ]; + + /* Block/sleep for a very short time before generating the next + random number. */ + vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms / portTICK_RATE_MS ); + } + + /* Wait for a short time before resuming (un-suspending) the flash + task. The flash tasks are only restarted if a button is not pushed + during this delay - if a button is pushed then the dice are shaken + again. + + First...clear any button pushes that are already pending. Again a + block time of zero is used so the function does not wait for any + pushes. */ + prvButtonHit( ucIndex, 0 ); + + /* Second...peek the semaphore. This task will block/sleep until a + button is pushed again, but because the peek function is used a + button being pushed will unblock the task but remain pending. */ + if( xQueuePeek( xSemaphores[ ucIndex ], NULL, diceEND_DELAY ) == pdFALSE ) { - case diceSTATE_STOPPED: - - prvButtonHit( ucIndex, portMAX_DELAY ); - ulDiceRunTime = diceRUN_MIN; - cDiceState = diceSTATE_RUNNING; - ulDiceDelay = 1; - ulDiceDelayReload = 1; - cDiceState = diceSTATE_RUNNING; - if( ucIndex == 0 ) - { - vToggleFlashTaskSuspendState(); - } - - break; - - case diceSTATE_RUNNING: - - ulDiceRunTime--; - ulDiceDelay--; - - if( !ulDiceDelay ) - { - ucDiceValue = rand() % 6 + 1; - dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ]; - ulDiceDelayReload = ulDiceDelayReload + 100; - ulDiceDelay = ulDiceDelayReload; - } - - if( ulDiceRunTime == 0 ) - { - dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ rand() % 6 + 1 ]; - cDiceState = diceSTATE_STOPPED; - - if( ucIndex == 0 ) - { - vTaskDelay( diceEND_DELAY ); - *pucDisplayOutput[ ucIndex ] = 0xff; - vToggleFlashTaskSuspendState(); - } - } - - break; + *pucDisplayOutput[ ucIndex ] = 0xff; + vSuspendFlashTasks( ucIndex, pdFALSE ); } } } diff --git a/Demo/MB96350_Softune_Dice_Kit/flash.c b/Demo/MB96350_Softune_Dice_Kit/flash.c index d8bd03414..bbf97f595 100644 --- a/Demo/MB96350_Softune_Dice_Kit/flash.c +++ b/Demo/MB96350_Softune_Dice_Kit/flash.c @@ -66,80 +66,92 @@ /* Scheduler include files. */ #include "FreeRTOS.h" #include "task.h" +#include "croutine.h" /* Demo program include files. */ #include "partest.h" #include "flash.h" #define ledSTACK_SIZE configMINIMAL_STACK_SIZE -#define ledNUMBER_OF_LEDS ( 3 ) +#define ledNUMBER_OF_LEDS ( 7 ) #define ledFLASH_RATE_BASE ( ( portTickType ) 333 ) -/* Variable used by the created tasks to calculate the LED number to use, and -the rate at which they should flash the LED. */ -static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0; +#define ledMAX_FLASH_CO_ROUTINES 7 +#define ledCO_ROUTINE_PRIORITY 0 /* The task that is created three times. */ -static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters ); +static void vLEDFlashTask( void *pvParameters ); +static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned short usIndex ); + +/* This task is created once, but itself creates 7 co-routines. */ +static void vLEDCoRoutineControlTask( void *pvParameters ); static xTaskHandle xFlashTaskHandles[ ledNUMBER_OF_LEDS ] = { 0 }; +static xTaskHandle xCoroutineTask; /*-----------------------------------------------------------*/ void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority ) { -signed portBASE_TYPE xLEDTask; +signed short sLEDTask; - /* Create the three tasks. */ - for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask ) + /* Create the three tasks that flash segments on the first LED. */ + for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask ) { /* Spawn the task. */ - xTaskCreate( vLEDFlashTask, ( signed portCHAR * ) "LEDx", ledSTACK_SIZE, NULL, uxPriority, &( xFlashTaskHandles[ xLEDTask ] ) ); + xTaskCreate( vLEDFlashTask, ( signed char * ) "LEDt", ledSTACK_SIZE, ( void * ) sLEDTask, uxPriority, &( xFlashTaskHandles[ sLEDTask ] ) ); } + + /* Create the task in which the co-routines run. */ + xTaskCreate( vLEDCoRoutineControlTask, ( signed char * ) "LEDc", ledSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xCoroutineTask ); } /*-----------------------------------------------------------*/ -void vSuspendFlashTasks( short sSuspendTasks ) +void vSuspendFlashTasks( unsigned char ucIndex, short sSuspendTasks ) { -signed portBASE_TYPE xLEDTask; +short sLEDTask; - for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask ) + if( ucIndex == 0 ) { - if( xFlashTaskHandles[ xLEDTask ] != NULL ) + for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask ) { - if( sSuspendTasks == pdTRUE ) + if( xFlashTaskHandles[ sLEDTask ] != NULL ) { - vTaskSuspend( xFlashTaskHandles[ xLEDTask ] ); - } - else - { - vTaskResume( xFlashTaskHandles[ xLEDTask ] ); + if( sSuspendTasks == pdTRUE ) + { + vTaskSuspend( xFlashTaskHandles[ sLEDTask ] ); + } + else + { + vTaskResume( xFlashTaskHandles[ sLEDTask ] ); + } } } } + else + { + if( sSuspendTasks == pdTRUE ) + { + vTaskSuspend( xCoroutineTask ); + } + else + { + vTaskResume( xCoroutineTask ); + } + } } /*-----------------------------------------------------------*/ -static portTASK_FUNCTION( vLEDFlashTask, pvParameters ) +static void vLEDFlashTask( void * pvParameters ) { portTickType xFlashRate, xLastFlashTime; -unsigned portBASE_TYPE uxLED; +unsigned short usLED; - /* The parameters are not used. */ - ( void ) pvParameters; - - /* Calculate the LED and flash rate. */ - portENTER_CRITICAL(); - { - /* See which of the eight LED's we should use. */ - uxLED = uxFlashTaskNumber; - - /* Update so the next task uses the next LED. */ - uxFlashTaskNumber++; - } - portEXIT_CRITICAL(); + /* The LED to flash is passed in as the task parameter. */ + usLED = ( unsigned short ) pvParameters; - xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) uxLED ); + /* Calculate the rate at which this task is going to toggle its LED. */ + xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) usLED ); xFlashRate /= portTICK_RATE_MS; /* We will turn the LED on and off again in the delay period, so each @@ -154,11 +166,57 @@ unsigned portBASE_TYPE uxLED; { /* Delay for half the flash period then turn the LED on. */ vTaskDelayUntil( &xLastFlashTime, xFlashRate ); - vParTestToggleLED( uxLED ); + vParTestToggleLED( usLED ); /* Delay for half the flash period then turn the LED off. */ vTaskDelayUntil( &xLastFlashTime, xFlashRate ); - vParTestToggleLED( uxLED ); + vParTestToggleLED( usLED ); } -} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */ +} +/*-----------------------------------------------------------*/ + +static void vLEDCoRoutineControlTask( void *pvParameters ) +{ +unsigned short usCoroutine; + + ( void ) pvParameters; + + for( usCoroutine = 0; usCoroutine < ledMAX_FLASH_CO_ROUTINES; usCoroutine++ ) + { + xCoRoutineCreate( prvFixedDelayCoRoutine, ledCO_ROUTINE_PRIORITY, usCoroutine ); + } + + for( ;; ) + { + vCoRoutineSchedule(); + } +} +/*-----------------------------------------------------------*/ + +static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned short usIndex ) +{ +/* The usIndex parameter of the co-routine function is used as an index into +the xFlashRates array to obtain the delay period to use. */ +static const portTickType xFlashRates[ ledMAX_FLASH_CO_ROUTINES ] = { 150 / portTICK_RATE_MS, + 300 / portTICK_RATE_MS, + 450 / portTICK_RATE_MS, + 600 / portTICK_RATE_MS, + 750 / portTICK_RATE_MS, + 900 / portTICK_RATE_MS, + 1050 / portTICK_RATE_MS }; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + + for( ;; ) + { + vParTestToggleLED( usIndex + 8 ); + crDELAY( xHandle, xFlashRates[ usIndex ] ); + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + diff --git a/Demo/MB96350_Softune_Dice_Kit/vectors.c b/Demo/MB96350_Softune_Dice_Kit/vectors.c index 193db79c8..6276081f0 100644 --- a/Demo/MB96350_Softune_Dice_Kit/vectors.c +++ b/Demo/MB96350_Softune_Dice_Kit/vectors.c @@ -34,10 +34,10 @@ void InitIrqLevels(void) ICR = (irq << 8) | DEFAULT_ILM_MASK; } - ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Reload Timer 0 */ - ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Delayed interrupt of 16FX Family */ - ICR = ( (24 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 ); /* INT8 */ - ICR = ( (25 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 ); /* INT9 */ + ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Reload Timer 0 */ + ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Delayed interrupt of 16FX Family */ + ICR = ( (24 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* INT8 */ + ICR = ( (25 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* INT9 */ } /*--------------------------------------------------------------------------- -- 2.39.5