|
|
|
@ -119,12 +119,12 @@ coverage. */
|
|
|
|
|
/* Each task and interrupt is given a unique identifier. This value is used to
|
|
|
|
|
identify which task sent or received each value. The identifier is also used
|
|
|
|
|
to distinguish between two tasks that are running the same task function. */
|
|
|
|
|
#define intqHIGH_PRIORITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 )
|
|
|
|
|
#define intqHIGH_PRIORITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 )
|
|
|
|
|
#define intqLOW_PRIORITY_TASK ( ( unsigned portBASE_TYPE ) 3 )
|
|
|
|
|
#define intqFIRST_INTERRUPT ( ( unsigned portBASE_TYPE ) 4 )
|
|
|
|
|
#define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 )
|
|
|
|
|
#define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 )
|
|
|
|
|
#define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
|
|
|
|
|
#define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
|
|
|
|
|
#define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
|
|
|
|
|
#define intqFIRST_INTERRUPT ( ( UBaseType_t ) 4 )
|
|
|
|
|
#define intqSECOND_INTERRUPT ( ( UBaseType_t ) 5 )
|
|
|
|
|
#define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
|
|
|
|
|
|
|
|
|
|
/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
|
|
|
|
|
from each queue by each task, otherwise an error is detected. */
|
|
|
|
@ -135,7 +135,7 @@ from within the interrupts. */
|
|
|
|
|
#define timerNORMALLY_EMPTY_TX() \
|
|
|
|
|
if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
|
|
|
|
|
{ \
|
|
|
|
|
unsigned portBASE_TYPE uxSavedInterruptStatus; \
|
|
|
|
|
UBaseType_t uxSavedInterruptStatus; \
|
|
|
|
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
|
|
|
|
|
{ \
|
|
|
|
|
uxValueForNormallyEmptyQueue++; \
|
|
|
|
@ -149,7 +149,7 @@ from within the interrupts. */
|
|
|
|
|
#define timerNORMALLY_FULL_TX() \
|
|
|
|
|
if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
|
|
|
|
|
{ \
|
|
|
|
|
unsigned portBASE_TYPE uxSavedInterruptStatus; \
|
|
|
|
|
UBaseType_t uxSavedInterruptStatus; \
|
|
|
|
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \
|
|
|
|
|
{ \
|
|
|
|
|
uxValueForNormallyFullQueue++; \
|
|
|
|
@ -185,19 +185,19 @@ an interrupt. */
|
|
|
|
|
static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
|
|
|
|
|
|
|
|
|
|
/* Variables used to detect a stall in one of the tasks. */
|
|
|
|
|
static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
|
|
|
|
|
static UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
|
|
|
|
|
|
|
|
|
|
/* Any unexpected behaviour sets xErrorStatus to fail and log the line that
|
|
|
|
|
caused the error in xErrorLine. */
|
|
|
|
|
static portBASE_TYPE xErrorStatus = pdPASS;
|
|
|
|
|
static volatile unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0;
|
|
|
|
|
static BaseType_t xErrorStatus = pdPASS;
|
|
|
|
|
static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
|
|
|
|
|
|
|
|
|
|
/* Used for sequencing between tasks. */
|
|
|
|
|
static portBASE_TYPE xWasSuspended = pdFALSE;
|
|
|
|
|
static BaseType_t xWasSuspended = pdFALSE;
|
|
|
|
|
|
|
|
|
|
/* The values that are sent to the queues. An incremented value is sent each
|
|
|
|
|
time to each queue. */
|
|
|
|
|
volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
|
|
|
|
|
volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
|
|
|
|
|
|
|
|
|
|
/* A handle to some of the tasks is required so they can be suspended/resumed. */
|
|
|
|
|
TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
|
|
|
|
@ -206,8 +206,8 @@ TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, x
|
|
|
|
|
the array position of the value is set to a the identifier of the task or
|
|
|
|
|
interrupt that accessed the queue. This way missing or duplicate values can be
|
|
|
|
|
detected. */
|
|
|
|
|
static unsigned char ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
|
|
|
|
static unsigned char ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
|
|
|
|
static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
|
|
|
|
static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
|
|
|
|
|
|
|
|
|
/* The test tasks themselves. */
|
|
|
|
|
static void prvLowerPriorityNormallyEmptyTask( void *pvParameters );
|
|
|
|
@ -218,11 +218,11 @@ static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters );
|
|
|
|
|
|
|
|
|
|
/* Used to mark the positions within the ucNormallyEmptyReceivedValues and
|
|
|
|
|
ucNormallyFullReceivedValues arrays, while checking for duplicates. */
|
|
|
|
|
static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
|
|
|
|
|
static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource );
|
|
|
|
|
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource );
|
|
|
|
|
static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource );
|
|
|
|
|
|
|
|
|
|
/* Logs the line on which an error occurred. */
|
|
|
|
|
static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine );
|
|
|
|
|
static void prvQueueAccessLogError( UBaseType_t uxLine );
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -238,8 +238,8 @@ void vStartInterruptQueueTasks( void )
|
|
|
|
|
|
|
|
|
|
/* Create the queues that are accessed by multiple tasks and multiple
|
|
|
|
|
interrupts. */
|
|
|
|
|
xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
|
|
|
|
|
xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
|
|
|
|
|
xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
|
|
|
|
|
xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
|
|
|
|
|
|
|
|
|
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
|
|
|
|
in use. The queue registry is provided as a means for kernel aware
|
|
|
|
@ -252,7 +252,7 @@ void vStartInterruptQueueTasks( void )
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
|
|
|
|
|
static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource )
|
|
|
|
|
{
|
|
|
|
|
if( uxValue < intqNUM_VALUES_TO_LOG )
|
|
|
|
|
{
|
|
|
|
@ -264,12 +264,12 @@ static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigne
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Log that this value has been received. */
|
|
|
|
|
ucNormallyFullReceivedValues[ uxValue ] = ( unsigned char ) uxSource;
|
|
|
|
|
ucNormallyFullReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource )
|
|
|
|
|
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource )
|
|
|
|
|
{
|
|
|
|
|
if( uxValue < intqNUM_VALUES_TO_LOG )
|
|
|
|
|
{
|
|
|
|
@ -281,12 +281,12 @@ static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsign
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Log that this value has been received. */
|
|
|
|
|
ucNormallyEmptyReceivedValues[ uxValue ] = ( unsigned char ) uxSource;
|
|
|
|
|
ucNormallyEmptyReceivedValues[ uxValue ] = ( uint8_t ) uxSource;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
|
|
|
|
|
static void prvQueueAccessLogError( UBaseType_t uxLine )
|
|
|
|
|
{
|
|
|
|
|
/* Latch the line number that caused the error. */
|
|
|
|
|
xErrorLine = uxLine;
|
|
|
|
@ -296,12 +296,12 @@ static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine )
|
|
|
|
|
|
|
|
|
|
static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
|
|
|
|
|
UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErrorCount2 = 0;
|
|
|
|
|
|
|
|
|
|
/* The timer should not be started until after the scheduler has started.
|
|
|
|
|
More than one task is running this code so we check the parameter value
|
|
|
|
|
to determine which task should start the timer. */
|
|
|
|
|
if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
|
|
|
|
if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
|
|
|
|
{
|
|
|
|
|
vInitialiseTimerForIntQueueTest();
|
|
|
|
|
}
|
|
|
|
@ -318,13 +318,13 @@ unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1
|
|
|
|
|
{
|
|
|
|
|
/* Note which value was received so we can check all expected
|
|
|
|
|
values are received and no values are duplicated. */
|
|
|
|
|
prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters );
|
|
|
|
|
prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ensure the other task running this code gets a chance to execute. */
|
|
|
|
|
taskYIELD();
|
|
|
|
|
|
|
|
|
|
if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
|
|
|
|
if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
|
|
|
|
{
|
|
|
|
|
/* Have we received all the expected values? */
|
|
|
|
|
if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
|
|
|
|
@ -419,7 +419,7 @@ unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1
|
|
|
|
|
|
|
|
|
|
static void prvLowerPriorityNormallyEmptyTask( void *pvParameters )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxValue, uxRxed;
|
|
|
|
|
UBaseType_t uxValue, uxRxed;
|
|
|
|
|
|
|
|
|
|
/* The parameters are not being used so avoid compiler warnings. */
|
|
|
|
|
( void ) pvParameters;
|
|
|
|
@ -467,7 +467,7 @@ unsigned portBASE_TYPE uxValue, uxRxed;
|
|
|
|
|
|
|
|
|
|
static void prv1stHigherPriorityNormallyFullTask( void *pvParameters )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxValueToTx, ux, uxInterrupts;
|
|
|
|
|
UBaseType_t uxValueToTx, ux, uxInterrupts;
|
|
|
|
|
|
|
|
|
|
/* The parameters are not being used so avoid compiler warnings. */
|
|
|
|
|
( void ) pvParameters;
|
|
|
|
@ -570,7 +570,7 @@ unsigned portBASE_TYPE uxValueToTx, ux, uxInterrupts;
|
|
|
|
|
|
|
|
|
|
static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxValueToTx, ux;
|
|
|
|
|
UBaseType_t uxValueToTx, ux;
|
|
|
|
|
|
|
|
|
|
/* The parameters are not being used so avoid compiler warnings. */
|
|
|
|
|
( void ) pvParameters;
|
|
|
|
@ -616,7 +616,7 @@ unsigned portBASE_TYPE uxValueToTx, ux;
|
|
|
|
|
|
|
|
|
|
static void prvLowerPriorityNormallyFullTask( void *pvParameters )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxValue, uxTxed = 9999;
|
|
|
|
|
UBaseType_t uxValue, uxTxed = 9999;
|
|
|
|
|
|
|
|
|
|
/* The parameters are not being used so avoid compiler warnings. */
|
|
|
|
|
( void ) pvParameters;
|
|
|
|
@ -655,18 +655,18 @@ unsigned portBASE_TYPE uxValue, uxTxed = 9999;
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
portBASE_TYPE xFirstTimerHandler( void )
|
|
|
|
|
BaseType_t xFirstTimerHandler( void )
|
|
|
|
|
{
|
|
|
|
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
|
unsigned portBASE_TYPE uxRxedValue;
|
|
|
|
|
static unsigned portBASE_TYPE uxNextOperation = 0;
|
|
|
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
|
UBaseType_t uxRxedValue;
|
|
|
|
|
static UBaseType_t uxNextOperation = 0;
|
|
|
|
|
|
|
|
|
|
/* Called from a timer interrupt. Perform various read and write
|
|
|
|
|
accesses on the queues. */
|
|
|
|
|
|
|
|
|
|
uxNextOperation++;
|
|
|
|
|
|
|
|
|
|
if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
|
|
|
|
|
if( uxNextOperation & ( UBaseType_t ) 0x01 )
|
|
|
|
|
{
|
|
|
|
|
timerNORMALLY_EMPTY_TX();
|
|
|
|
|
timerNORMALLY_EMPTY_TX();
|
|
|
|
@ -683,18 +683,18 @@ static unsigned portBASE_TYPE uxNextOperation = 0;
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
portBASE_TYPE xSecondTimerHandler( void )
|
|
|
|
|
BaseType_t xSecondTimerHandler( void )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxRxedValue;
|
|
|
|
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
|
static unsigned portBASE_TYPE uxNextOperation = 0;
|
|
|
|
|
UBaseType_t uxRxedValue;
|
|
|
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
|
static UBaseType_t uxNextOperation = 0;
|
|
|
|
|
|
|
|
|
|
/* Called from a timer interrupt. Perform various read and write
|
|
|
|
|
accesses on the queues. */
|
|
|
|
|
|
|
|
|
|
uxNextOperation++;
|
|
|
|
|
|
|
|
|
|
if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 )
|
|
|
|
|
if( uxNextOperation & ( UBaseType_t ) 0x01 )
|
|
|
|
|
{
|
|
|
|
|
timerNORMALLY_EMPTY_TX();
|
|
|
|
|
timerNORMALLY_EMPTY_TX();
|
|
|
|
@ -716,9 +716,9 @@ static unsigned portBASE_TYPE uxNextOperation = 0;
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
portBASE_TYPE xAreIntQueueTasksStillRunning( void )
|
|
|
|
|
BaseType_t xAreIntQueueTasksStillRunning( void )
|
|
|
|
|
{
|
|
|
|
|
static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
|
|
|
|
|
static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0;
|
|
|
|
|
|
|
|
|
|
/* xErrorStatus can be set outside of this function. This function just
|
|
|
|
|
checks that all the tasks are still cycling. */
|
|
|
|
|