mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-05-29 00:19:04 -04:00
Extend FX16 functionality.
This commit is contained in:
parent
46c3268670
commit
269de4b1e7
|
@ -51,14 +51,9 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "semphr.h"
|
#include "semphr.h"
|
||||||
|
|
||||||
#define diceMIN 1
|
#define diceDELAY_BETWEEN_RANDOM_NUMBERS_ms ( 20 )
|
||||||
#define diceMAX 6
|
#define diceRUN_TIME ( 2000 / diceDELAY_BETWEEN_RANDOM_NUMBERS_ms )
|
||||||
#define diceRUN_MIN 600000L
|
|
||||||
#define diceRUN_MAX 1200000L
|
|
||||||
|
|
||||||
#define diceSTATE_STOPPED 0
|
|
||||||
#define diceSTATE_STARTUP 1
|
|
||||||
#define diceSTATE_RUNNING 2
|
|
||||||
|
|
||||||
#define diceEND_DELAY ( 5000 / portTICK_RATE_MS )
|
#define diceEND_DELAY ( 5000 / portTICK_RATE_MS )
|
||||||
|
|
||||||
|
@ -80,61 +75,72 @@ extern volatile unsigned char *pucDisplayOutput[ 2 ];
|
||||||
|
|
||||||
void vDiceTask( void *pvParameters )
|
void vDiceTask( void *pvParameters )
|
||||||
{
|
{
|
||||||
char cDiceState = diceSTATE_STOPPED;
|
|
||||||
unsigned char ucDiceValue, ucIndex;
|
unsigned char ucDiceValue, ucIndex;
|
||||||
unsigned long ulDiceRunTime, ulDiceDelay, ulDiceDelayReload;
|
unsigned long ulDiceRunTime;
|
||||||
extern void vToggleFlashTaskSuspendState( void );
|
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;
|
ucIndex = ( unsigned char ) pvParameters;
|
||||||
|
|
||||||
|
/* A binary semaphore is used to signal button push events. Create the
|
||||||
|
semaphore before it is used. */
|
||||||
vSemaphoreCreateBinary( xSemaphores[ ucIndex ] );
|
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( ;; )
|
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 )
|
||||||
{
|
{
|
||||||
case diceSTATE_STOPPED:
|
ulDiceRunTime--;
|
||||||
|
|
||||||
prvButtonHit( ucIndex, portMAX_DELAY );
|
/* Generate and display a random number. */
|
||||||
ulDiceRunTime = diceRUN_MIN;
|
ucDiceValue = rand() % 6 + 1;
|
||||||
cDiceState = diceSTATE_RUNNING;
|
dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];
|
||||||
ulDiceDelay = 1;
|
|
||||||
ulDiceDelayReload = 1;
|
|
||||||
cDiceState = diceSTATE_RUNNING;
|
|
||||||
if( ucIndex == 0 )
|
|
||||||
{
|
|
||||||
vToggleFlashTaskSuspendState();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
/* Block/sleep for a very short time before generating the next
|
||||||
|
random number. */
|
||||||
|
vTaskDelay( diceDELAY_BETWEEN_RANDOM_NUMBERS_ms / portTICK_RATE_MS );
|
||||||
|
}
|
||||||
|
|
||||||
case diceSTATE_RUNNING:
|
/* 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.
|
||||||
|
|
||||||
ulDiceRunTime--;
|
First...clear any button pushes that are already pending. Again a
|
||||||
ulDiceDelay--;
|
block time of zero is used so the function does not wait for any
|
||||||
|
pushes. */
|
||||||
|
prvButtonHit( ucIndex, 0 );
|
||||||
|
|
||||||
if( !ulDiceDelay )
|
/* Second...peek the semaphore. This task will block/sleep until a
|
||||||
{
|
button is pushed again, but because the peek function is used a
|
||||||
ucDiceValue = rand() % 6 + 1;
|
button being pushed will unblock the task but remain pending. */
|
||||||
dice7SEG_Value( ucIndex ) = ( dice7SEG_Value( ucIndex ) | 0xf7 ) & cDisplaySegments[ ucIndex ][ ucDiceValue ];
|
if( xQueuePeek( xSemaphores[ ucIndex ], NULL, diceEND_DELAY ) == pdFALSE )
|
||||||
ulDiceDelayReload = ulDiceDelayReload + 100;
|
{
|
||||||
ulDiceDelay = ulDiceDelayReload;
|
*pucDisplayOutput[ ucIndex ] = 0xff;
|
||||||
}
|
vSuspendFlashTasks( ucIndex, pdFALSE );
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,80 +66,92 @@
|
||||||
/* Scheduler include files. */
|
/* Scheduler include files. */
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "croutine.h"
|
||||||
|
|
||||||
/* Demo program include files. */
|
/* Demo program include files. */
|
||||||
#include "partest.h"
|
#include "partest.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
|
||||||
#define ledSTACK_SIZE configMINIMAL_STACK_SIZE
|
#define ledSTACK_SIZE configMINIMAL_STACK_SIZE
|
||||||
#define ledNUMBER_OF_LEDS ( 3 )
|
#define ledNUMBER_OF_LEDS ( 7 )
|
||||||
#define ledFLASH_RATE_BASE ( ( portTickType ) 333 )
|
#define ledFLASH_RATE_BASE ( ( portTickType ) 333 )
|
||||||
|
|
||||||
/* Variable used by the created tasks to calculate the LED number to use, and
|
#define ledMAX_FLASH_CO_ROUTINES 7
|
||||||
the rate at which they should flash the LED. */
|
#define ledCO_ROUTINE_PRIORITY 0
|
||||||
static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0;
|
|
||||||
|
|
||||||
/* The task that is created three times. */
|
/* 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 xFlashTaskHandles[ ledNUMBER_OF_LEDS ] = { 0 };
|
||||||
|
static xTaskHandle xCoroutineTask;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority )
|
void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
{
|
{
|
||||||
signed portBASE_TYPE xLEDTask;
|
signed short sLEDTask;
|
||||||
|
|
||||||
/* Create the three tasks. */
|
/* Create the three tasks that flash segments on the first LED. */
|
||||||
for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask )
|
for( sLEDTask = 0; sLEDTask < ledNUMBER_OF_LEDS; ++sLEDTask )
|
||||||
{
|
{
|
||||||
/* Spawn the task. */
|
/* 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 ] );
|
if( sSuspendTasks == pdTRUE )
|
||||||
}
|
{
|
||||||
else
|
vTaskSuspend( xFlashTaskHandles[ sLEDTask ] );
|
||||||
{
|
}
|
||||||
vTaskResume( xFlashTaskHandles[ xLEDTask ] );
|
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;
|
portTickType xFlashRate, xLastFlashTime;
|
||||||
unsigned portBASE_TYPE uxLED;
|
unsigned short usLED;
|
||||||
|
|
||||||
/* The parameters are not used. */
|
/* The LED to flash is passed in as the task parameter. */
|
||||||
( void ) pvParameters;
|
usLED = ( unsigned short ) pvParameters;
|
||||||
|
|
||||||
/* Calculate the LED and flash rate. */
|
/* Calculate the rate at which this task is going to toggle its LED. */
|
||||||
portENTER_CRITICAL();
|
xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) usLED );
|
||||||
{
|
|
||||||
/* See which of the eight LED's we should use. */
|
|
||||||
uxLED = uxFlashTaskNumber;
|
|
||||||
|
|
||||||
/* Update so the next task uses the next LED. */
|
|
||||||
uxFlashTaskNumber++;
|
|
||||||
}
|
|
||||||
portEXIT_CRITICAL();
|
|
||||||
|
|
||||||
xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) uxLED );
|
|
||||||
xFlashRate /= portTICK_RATE_MS;
|
xFlashRate /= portTICK_RATE_MS;
|
||||||
|
|
||||||
/* We will turn the LED on and off again in the delay period, so each
|
/* 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. */
|
/* Delay for half the flash period then turn the LED on. */
|
||||||
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
|
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
|
||||||
vParTestToggleLED( uxLED );
|
vParTestToggleLED( usLED );
|
||||||
|
|
||||||
/* Delay for half the flash period then turn the LED off. */
|
/* Delay for half the flash period then turn the LED off. */
|
||||||
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
|
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();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ void InitIrqLevels(void)
|
||||||
ICR = (irq << 8) | DEFAULT_ILM_MASK;
|
ICR = (irq << 8) | DEFAULT_ILM_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Reload Timer 0 */
|
ICR = ( (54 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Reload Timer 0 */
|
||||||
ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Delayed interrupt of 16FX Family */
|
ICR = ( (12 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* Delayed interrupt of 16FX Family */
|
||||||
ICR = ( (24 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 ); /* INT8 */
|
ICR = ( (24 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* INT8 */
|
||||||
ICR = ( (25 & 0xFF) << 8 ) | ( configKERNEL_INTERRUPT_PRIORITY - 1 ); /* INT9 */
|
ICR = ( (25 & 0xFF) << 8 ) | configKERNEL_INTERRUPT_PRIORITY; /* INT9 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in a new issue