mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-08 20:55:14 -05:00
Add uncrustify github workflow (#659)
* Add uncrustify github workflow * Fix exclusion pattern * fix find expression * exclude uncrustify files * Uncrustify common demo and test files * exlude white space checking files * Fix EOL whitespace checker * Remove whitespaces from EOL * Fix space at EOL * Fix find spaces at EOL Co-authored-by: Archit Aggarwal <architag@amazon.com>
This commit is contained in:
parent
dd80d615b5
commit
ae92d8c6ee
191 changed files with 17540 additions and 17102 deletions
32
.github/workflows/ci.yml
vendored
32
.github/workflows/ci.yml
vendored
|
|
@ -24,6 +24,38 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
git-secrets --register-aws
|
git-secrets --register-aws
|
||||||
git-secrets --scan
|
git-secrets --scan
|
||||||
|
|
||||||
|
formatting:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install Uncrustify
|
||||||
|
run: sudo apt-get install uncrustify
|
||||||
|
- name: Run Uncrustify
|
||||||
|
run: |
|
||||||
|
uncrustify --version
|
||||||
|
find FreeRTOS/Demo/Common FreeRTOS/Test \( -name ethernet -o -name drivers -o -path 'FreeRTOS/Test/CMock/CMock' \) -prune -false -o -name "*.[hc]" -exec uncrustify --check -c tools/uncrustify.cfg {} +
|
||||||
|
- name: Check For Trailing Whitespace
|
||||||
|
run: |
|
||||||
|
set +e
|
||||||
|
ERROR=0
|
||||||
|
find . \( -name '.git' -o -path "./FreeRTOS/Test/CBMC/patches" -o -path "./FreeRTOS-Plus" -o -path "./FreeRTOS/Source" -o -path "./FreeRTOS/Test/CMock/CMock" -o -path "./FreeRTOS/Demo" \) -prune -false -o -type f -a -name "*" -exec grep -In -e "[[:blank:]]$" {} +
|
||||||
|
if [ "$?" = "0" ]; then
|
||||||
|
echo "Files have trailing whitespace."
|
||||||
|
ERROR=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
find FreeRTOS/Demo/Common \( -name "ethernet" \) -prune -o -false -o -type f -a -name "*" -exec grep --color=yes -In -e "[[:blank:]]$" {} +
|
||||||
|
if [ "$?" = "0" ]; then
|
||||||
|
echo "Files have trailing whitespace."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
if [ "$ERROR" -eq "1" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
doxygen:
|
doxygen:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ int main()
|
||||||
#error "Invalid Selection...\nPlease Select a Demo application from the main command"
|
#error "Invalid Selection...\nPlease Select a Demo application from the main command"
|
||||||
}
|
}
|
||||||
#endif /* if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) */
|
#endif /* if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) */
|
||||||
|
snprint
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,8 @@ TaskParameters_t xROAccessTaskParameters =
|
||||||
.pvParameters = NULL,
|
.pvParameters = NULL,
|
||||||
.uxPriority = tskIDLE_PRIORITY,
|
.uxPriority = tskIDLE_PRIORITY,
|
||||||
.puxStackBuffer = xROAccessTaskStack,
|
.puxStackBuffer = xROAccessTaskStack,
|
||||||
.xRegions = {
|
.xRegions =
|
||||||
|
{
|
||||||
{ ucSharedMemory, 32, tskMPU_REGION_READ_ONLY | tskMPU_REGION_EXECUTE_NEVER },
|
{ ucSharedMemory, 32, tskMPU_REGION_READ_ONLY | tskMPU_REGION_EXECUTE_NEVER },
|
||||||
{ ucROTaskFaultTracker, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },
|
{ ucROTaskFaultTracker, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
|
|
@ -147,7 +148,8 @@ TaskParameters_t xRWAccessTaskParameters =
|
||||||
.pvParameters = NULL,
|
.pvParameters = NULL,
|
||||||
.uxPriority = tskIDLE_PRIORITY,
|
.uxPriority = tskIDLE_PRIORITY,
|
||||||
.puxStackBuffer = xRWAccessTaskStack,
|
.puxStackBuffer = xRWAccessTaskStack,
|
||||||
.xRegions = {
|
.xRegions =
|
||||||
|
{
|
||||||
{ ucSharedMemory, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },
|
{ ucSharedMemory, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
|
|
@ -192,9 +194,9 @@ uint16_t usOffendingInstruction;
|
||||||
|
|
||||||
/* Determine if the offending instruction is a 32-bit instruction or
|
/* Determine if the offending instruction is a 32-bit instruction or
|
||||||
* a 16-bit instruction. */
|
* a 16-bit instruction. */
|
||||||
if( usOffendingInstruction == 0x001F ||
|
if( ( usOffendingInstruction == 0x001F ) ||
|
||||||
usOffendingInstruction == 0x001E ||
|
( usOffendingInstruction == 0x001E ) ||
|
||||||
usOffendingInstruction == 0x001D )
|
( usOffendingInstruction == 0x001D ) )
|
||||||
{
|
{
|
||||||
/* Since the offending instruction is a 32-bit instruction,
|
/* Since the offending instruction is a 32-bit instruction,
|
||||||
* increment the program counter by 4 to move to the next
|
* increment the program counter by 4 to move to the next
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,8 @@ TaskParameters_t xSecureCallingTaskParameters =
|
||||||
.pvParameters = NULL,
|
.pvParameters = NULL,
|
||||||
.uxPriority = tskIDLE_PRIORITY,
|
.uxPriority = tskIDLE_PRIORITY,
|
||||||
.puxStackBuffer = xSecureCallingTaskStack,
|
.puxStackBuffer = xSecureCallingTaskStack,
|
||||||
.xRegions = {
|
.xRegions =
|
||||||
|
{
|
||||||
{ ulNonSecureCounter, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },
|
{ ulNonSecureCounter, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
|
|
|
||||||
|
|
@ -53,20 +53,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V1.00:
|
* Changes from V1.00:
|
||||||
|
*
|
||||||
+ Reversed the priority and block times of the second two demo tasks so
|
+ Reversed the priority and block times of the second two demo tasks so
|
||||||
they operate as per the description above.
|
+ they operate as per the description above.
|
||||||
|
+
|
||||||
Changes from V2.0.0
|
+ Changes from V2.0.0
|
||||||
|
+
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
|
+
|
||||||
Changes from V4.0.2
|
+ Changes from V4.0.2
|
||||||
|
+
|
||||||
+ The second set of tasks were created the wrong way around. This has been
|
+ The second set of tasks were created the wrong way around. This has been
|
||||||
corrected.
|
+ corrected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -96,16 +96,16 @@ typedef struct BLOCKING_QUEUE_PARAMETERS
|
||||||
static void vBlockingQueueProducer( void * pvParameters );
|
static void vBlockingQueueProducer( void * pvParameters );
|
||||||
|
|
||||||
/* Task function that removes the incrementing number from a queue and checks that
|
/* Task function that removes the incrementing number from a queue and checks that
|
||||||
it is the expected number. */
|
* it is the expected number. */
|
||||||
static void vBlockingQueueConsumer( void * pvParameters );
|
static void vBlockingQueueConsumer( void * pvParameters );
|
||||||
|
|
||||||
/* Variables which are incremented each time an item is removed from a queue, and
|
/* Variables which are incremented each time an item is removed from a queue, and
|
||||||
found to be the expected value.
|
* found to be the expected value.
|
||||||
These are used to check that the tasks are still running. */
|
* These are used to check that the tasks are still running. */
|
||||||
static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
||||||
|
|
||||||
/* Variable which are incremented each time an item is posted on a queue. These
|
/* Variable which are incremented each time an item is posted on a queue. These
|
||||||
are used to check that the tasks are still running. */
|
* are used to check that the tasks are still running. */
|
||||||
static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, ( short ) 0, ( short ) 0 };
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -125,14 +125,14 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
||||||
pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
|
|
||||||
/* Create the queue used by the first two tasks to pass the incrementing number.
|
/* Create the queue used by the first two tasks to pass the incrementing number.
|
||||||
Pass a pointer to the queue in the parameter structure. */
|
* Pass a pointer to the queue in the parameter structure. */
|
||||||
pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
|
|
||||||
/* The consumer is created first so gets a block time as described above. */
|
/* The consumer is created first so gets a block time as described above. */
|
||||||
pxQueueParameters1->xBlockTime = xBlockTime;
|
pxQueueParameters1->xBlockTime = xBlockTime;
|
||||||
|
|
||||||
/* Pass in the variable that this task is going to increment so we can check it
|
/* Pass in the variable that this task is going to increment so we can check it
|
||||||
is still running. */
|
* is still running. */
|
||||||
pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );
|
pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );
|
||||||
|
|
||||||
/* Create the structure used to pass parameters to the producer task. */
|
/* Create the structure used to pass parameters to the producer task. */
|
||||||
|
|
@ -142,23 +142,23 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
||||||
pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
|
pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
|
||||||
|
|
||||||
/* The producer is not going to block - as soon as it posts the consumer will
|
/* The producer is not going to block - as soon as it posts the consumer will
|
||||||
wake and remove the item so the producer should always have room to post. */
|
* wake and remove the item so the producer should always have room to post. */
|
||||||
pxQueueParameters2->xBlockTime = xDontBlock;
|
pxQueueParameters2->xBlockTime = xDontBlock;
|
||||||
|
|
||||||
/* Pass in the variable that this task is going to increment so we can check
|
/* Pass in the variable that this task is going to increment so we can check
|
||||||
it is still running. */
|
* it is still running. */
|
||||||
pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );
|
pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );
|
||||||
|
|
||||||
|
|
||||||
/* Note the producer has a lower priority than the consumer when the tasks are
|
/* Note the producer has a lower priority than the consumer when the tasks are
|
||||||
spawned. */
|
* spawned. */
|
||||||
xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );
|
xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );
|
||||||
xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the second two tasks as described at the top of the file. This uses
|
/* Create the second two tasks as described at the top of the file. This uses
|
||||||
the same mechanism but reverses the task priorities. */
|
* the same mechanism but reverses the task priorities. */
|
||||||
|
|
||||||
pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
|
|
@ -176,7 +176,7 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
||||||
|
|
||||||
|
|
||||||
/* Create the last two tasks as described above. The mechanism is again just
|
/* Create the last two tasks as described above. The mechanism is again just
|
||||||
the same. This time both parameter structures are given a block time. */
|
* the same. This time both parameter structures are given a block time. */
|
||||||
pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned short ) );
|
||||||
pxQueueParameters5->xBlockTime = xBlockTime;
|
pxQueueParameters5->xBlockTime = xBlockTime;
|
||||||
|
|
@ -215,14 +215,14 @@ short sErrorEverOccurred = pdFALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We have successfully posted a message, so increment the variable
|
/* We have successfully posted a message, so increment the variable
|
||||||
used to check we are still running. */
|
* used to check we are still running. */
|
||||||
if( sErrorEverOccurred == pdFALSE )
|
if( sErrorEverOccurred == pdFALSE )
|
||||||
{
|
{
|
||||||
( *pxQueueParameters->psCheckVariable )++;
|
( *pxQueueParameters->psCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the variable we are going to post next time round. The
|
/* Increment the variable we are going to post next time round. The
|
||||||
consumer will expect the numbers to follow in numerical order. */
|
* consumer will expect the numbers to follow in numerical order. */
|
||||||
++usValue;
|
++usValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,14 +258,14 @@ short sErrorEverOccurred = pdFALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We have successfully received a message, so increment the
|
/* We have successfully received a message, so increment the
|
||||||
variable used to check we are still running. */
|
* variable used to check we are still running. */
|
||||||
if( sErrorEverOccurred == pdFALSE )
|
if( sErrorEverOccurred == pdFALSE )
|
||||||
{
|
{
|
||||||
( *pxQueueParameters->psCheckVariable )++;
|
( *pxQueueParameters->psCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the value we expect to remove from the queue next time
|
/* Increment the value we expect to remove from the queue next time
|
||||||
round. */
|
* round. */
|
||||||
++usExpectedValue;
|
++usExpectedValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -281,11 +281,11 @@ static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( short ) 0, (
|
||||||
portBASE_TYPE xReturn = pdPASS, xTasks;
|
portBASE_TYPE xReturn = pdPASS, xTasks;
|
||||||
|
|
||||||
/* Not too worried about mutual exclusion on these variables as they are 16
|
/* Not too worried about mutual exclusion on these variables as they are 16
|
||||||
bits and we are only reading them. We also only care to see if they have
|
* bits and we are only reading them. We also only care to see if they have
|
||||||
changed or not.
|
* changed or not.
|
||||||
|
*
|
||||||
Loop through each check variable and return pdFALSE if any are found not
|
* Loop through each check variable and return pdFALSE if any are found not
|
||||||
to have changed since the last call. */
|
* to have changed since the last call. */
|
||||||
|
|
||||||
for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )
|
for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )
|
||||||
{
|
{
|
||||||
|
|
@ -293,16 +293,16 @@ portBASE_TYPE xReturn = pdPASS, xTasks;
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
|
|
||||||
|
|
||||||
|
sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
|
||||||
|
|
||||||
if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] )
|
if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] )
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
|
sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
|
||||||
}
|
}
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
* Changes from V2.0.0
|
||||||
|
*
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -128,7 +128,7 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If an error has ever been recorded we stop incrementing the
|
/* If an error has ever been recorded we stop incrementing the
|
||||||
check variable. */
|
* check variable. */
|
||||||
++sPollingProducerCount;
|
++sPollingProducerCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait before we start posting again to ensure the consumer runs and
|
/* Wait before we start posting again to ensure the consumer runs and
|
||||||
empties the queue. */
|
* empties the queue. */
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -169,11 +169,12 @@ short sError = pdFALSE;
|
||||||
if( usData != usExpectedValue )
|
if( usData != usExpectedValue )
|
||||||
{
|
{
|
||||||
/* This is not what we expected to receive so an error has
|
/* This is not what we expected to receive so an error has
|
||||||
occurred. */
|
* occurred. */
|
||||||
vPrintDisplayMessage( &pcTaskErrorMsg );
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
||||||
/* Catch-up to the value we received so our next expected value
|
/* Catch-up to the value we received so our next expected value
|
||||||
should again be correct. */
|
* should again be correct. */
|
||||||
usExpectedValue = usData;
|
usExpectedValue = usData;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -181,16 +182,17 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* Only increment the check variable if no errors have
|
/* Only increment the check variable if no errors have
|
||||||
occurred. */
|
* occurred. */
|
||||||
++sPollingConsumerCount;
|
++sPollingConsumerCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++usExpectedValue;
|
++usExpectedValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the queue is empty we block, allowing the producer to place more
|
/* Now the queue is empty we block, allowing the producer to place more
|
||||||
items in the queue. */
|
* items in the queue. */
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,35 +55,35 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V1.00:
|
* Changes from V1.00:
|
||||||
|
*
|
||||||
+ The priority of the Rx task has been lowered. Received characters are
|
+ The priority of the Rx task has been lowered. Received characters are
|
||||||
now processed (read from the queue) at the idle priority, allowing low
|
+ now processed (read from the queue) at the idle priority, allowing low
|
||||||
priority tasks to run evenly at times of a high communications overhead.
|
+ priority tasks to run evenly at times of a high communications overhead.
|
||||||
|
+
|
||||||
Changes from V1.01:
|
+ Changes from V1.01:
|
||||||
|
+
|
||||||
+ The Tx task now waits a pseudo random time between transmissions.
|
+ The Tx task now waits a pseudo random time between transmissions.
|
||||||
Previously a fixed period was used but this was not such a good test as
|
+ Previously a fixed period was used but this was not such a good test as
|
||||||
interrupts fired at regular intervals.
|
+ interrupts fired at regular intervals.
|
||||||
|
+
|
||||||
Changes From V1.2.0:
|
+ Changes From V1.2.0:
|
||||||
|
+
|
||||||
+ Use vSerialPutString() instead of single character puts.
|
+ Use vSerialPutString() instead of single character puts.
|
||||||
+ Only stop the check variable incrementing after two consecutive errors.
|
+ Only stop the check variable incrementing after two consecutive errors.
|
||||||
|
+
|
||||||
Changed from V1.2.5
|
+ Changed from V1.2.5
|
||||||
|
+
|
||||||
+ Made the Rx task 2 priorities higher than the Tx task. Previously it was
|
+ Made the Rx task 2 priorities higher than the Tx task. Previously it was
|
||||||
only 1. This is done to tie in better with the other demo application
|
+ only 1. This is done to tie in better with the other demo application
|
||||||
tasks.
|
+ tasks.
|
||||||
|
+
|
||||||
Changes from V2.0.0
|
+ Changes from V2.0.0
|
||||||
|
+
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
+ Slight modification to task priorities.
|
+ Slight modification to task priorities.
|
||||||
|
+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -99,7 +99,7 @@ Changes from V2.0.0
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
/* The Tx task will transmit the sequence of characters at a pseudo random
|
/* The Tx task will transmit the sequence of characters at a pseudo random
|
||||||
interval. This is the maximum and minimum block time between sends. */
|
* interval. This is the maximum and minimum block time between sends. */
|
||||||
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x15e )
|
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x15e )
|
||||||
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0xc8 )
|
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0xc8 )
|
||||||
|
|
||||||
|
|
@ -126,7 +126,7 @@ const char * const pcMessageToExchange = "Send this message over and over again
|
||||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
|
||||||
|
|
||||||
/* Variables that are incremented on each cycle of each task. These are used to
|
/* Variables that are incremented on each cycle of each task. These are used to
|
||||||
check that both tasks are still executing. */
|
* check that both tasks are still executing. */
|
||||||
volatile short sTxCount = 0, sRxCount = 0, sSemCount = 0;
|
volatile short sTxCount = 0, sRxCount = 0, sSemCount = 0;
|
||||||
|
|
||||||
/* The handle to the semaphore test task. */
|
/* The handle to the semaphore test task. */
|
||||||
|
|
@ -134,7 +134,9 @@ static TaskHandle_t xSemTestTaskHandle = NULL;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate )
|
void vStartComTestTasks( unsigned portBASE_TYPE uxPriority,
|
||||||
|
eCOMPort ePort,
|
||||||
|
eBaud eBaudRate )
|
||||||
{
|
{
|
||||||
const unsigned portBASE_TYPE uxBufferLength = 255;
|
const unsigned portBASE_TYPE uxBufferLength = 255;
|
||||||
|
|
||||||
|
|
@ -163,8 +165,8 @@ TickType_t xTimeToWait;
|
||||||
vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) );
|
vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) );
|
||||||
|
|
||||||
/* We have posted all the characters in the string - increment the variable
|
/* We have posted all the characters in the string - increment the variable
|
||||||
used to check that this task is still running, then wait before re-sending
|
* used to check that this task is still running, then wait before re-sending
|
||||||
the string. */
|
* the string. */
|
||||||
sTxCount++;
|
sTxCount++;
|
||||||
|
|
||||||
xTimeToWait = xTaskGetTickCount();
|
xTimeToWait = xTaskGetTickCount();
|
||||||
|
|
@ -210,28 +212,30 @@ short sResyncRequired, sConsecutiveErrors, sLatchedError;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Receive a message from the com port interrupt routine. If a message is
|
/* Receive a message from the com port interrupt routine. If a message is
|
||||||
not yet available the call will block the task. */
|
* not yet available the call will block the task. */
|
||||||
xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime );
|
xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime );
|
||||||
|
|
||||||
if( xGotChar == pdTRUE )
|
if( xGotChar == pdTRUE )
|
||||||
{
|
{
|
||||||
if( sResyncRequired == pdTRUE )
|
if( sResyncRequired == pdTRUE )
|
||||||
{
|
{
|
||||||
/* We got out of sequence and are waiting for the start of the next
|
/* We got out of sequence and are waiting for the start of the next
|
||||||
transmission of the string. */
|
* transmission of the string. */
|
||||||
if( cRxedChar == '\n' )
|
if( cRxedChar == '\n' )
|
||||||
{
|
{
|
||||||
/* This is the end of the message so we can start again - with
|
/* This is the end of the message so we can start again - with
|
||||||
the first character in the string being the next thing we expect
|
* the first character in the string being the next thing we expect
|
||||||
to receive. */
|
* to receive. */
|
||||||
pcExpectedChar = pcMessageToExchange;
|
pcExpectedChar = pcMessageToExchange;
|
||||||
sResyncRequired = pdFALSE;
|
sResyncRequired = pdFALSE;
|
||||||
|
|
||||||
/* Queue a message for printing to say that we are going to try
|
/* Queue a message for printing to say that we are going to try
|
||||||
again. */
|
* again. */
|
||||||
vPrintDisplayMessage( &pcTaskRestartMsg );
|
vPrintDisplayMessage( &pcTaskRestartMsg );
|
||||||
|
|
||||||
/* Stop incrementing the check variable, if consecutive errors occur. */
|
/* Stop incrementing the check variable, if consecutive errors occur. */
|
||||||
sConsecutiveErrors++;
|
sConsecutiveErrors++;
|
||||||
|
|
||||||
if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS )
|
if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS )
|
||||||
{
|
{
|
||||||
sLatchedError = pdTRUE;
|
sLatchedError = pdTRUE;
|
||||||
|
|
@ -244,17 +248,18 @@ short sResyncRequired, sConsecutiveErrors, sLatchedError;
|
||||||
if( cRxedChar != *pcExpectedChar )
|
if( cRxedChar != *pcExpectedChar )
|
||||||
{
|
{
|
||||||
/* This was not the expected character so post a message for
|
/* This was not the expected character so post a message for
|
||||||
printing to say that an error has occurred. We will then wait
|
* printing to say that an error has occurred. We will then wait
|
||||||
to resynchronise. */
|
* to resynchronise. */
|
||||||
vPrintDisplayMessage( &pcTaskErrorMsg );
|
vPrintDisplayMessage( &pcTaskErrorMsg );
|
||||||
sResyncRequired = pdTRUE;
|
sResyncRequired = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This was the expected character so next time we will expect
|
/* This was the expected character so next time we will expect
|
||||||
the next character in the string. Wrap back to the beginning
|
* the next character in the string. Wrap back to the beginning
|
||||||
of the string when the null terminator has been reached. */
|
* of the string when the null terminator has been reached. */
|
||||||
pcExpectedChar++;
|
pcExpectedChar++;
|
||||||
|
|
||||||
if( *pcExpectedChar == '\0' )
|
if( *pcExpectedChar == '\0' )
|
||||||
{
|
{
|
||||||
pcExpectedChar = pcMessageToExchange;
|
pcExpectedChar = pcMessageToExchange;
|
||||||
|
|
@ -266,7 +271,7 @@ short sResyncRequired, sConsecutiveErrors, sLatchedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the count that is used to check that this task is still
|
/* Increment the count that is used to check that this task is still
|
||||||
running. This is only done if an error has never occurred. */
|
* running. This is only done if an error has never occurred. */
|
||||||
if( sLatchedError == pdFALSE )
|
if( sLatchedError == pdFALSE )
|
||||||
{
|
{
|
||||||
sRxCount++;
|
sRxCount++;
|
||||||
|
|
@ -315,8 +320,8 @@ static short sLastTxCount = 0, sLastRxCount = 0, sLastSemCount = 0;
|
||||||
portBASE_TYPE xReturn;
|
portBASE_TYPE xReturn;
|
||||||
|
|
||||||
/* Not too worried about mutual exclusion on these variables as they are 16
|
/* Not too worried about mutual exclusion on these variables as they are 16
|
||||||
bits and we are only reading them. We also only care to see if they have
|
* bits and we are only reading them. We also only care to see if they have
|
||||||
changed or not. */
|
* changed or not. */
|
||||||
|
|
||||||
if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) )
|
if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) )
|
||||||
{
|
{
|
||||||
|
|
@ -338,8 +343,8 @@ portBASE_TYPE xReturn;
|
||||||
void vComTestUnsuspendTask( void )
|
void vComTestUnsuspendTask( void )
|
||||||
{
|
{
|
||||||
/* The task that is suspended on the semaphore will be referenced from the
|
/* The task that is suspended on the semaphore will be referenced from the
|
||||||
Suspended list as it is blocking indefinitely. This call just checks that
|
* Suspended list as it is blocking indefinitely. This call just checks that
|
||||||
the kernel correctly detects this and does not attempt to unsuspend the
|
* the kernel correctly detects this and does not attempt to unsuspend the
|
||||||
task. */
|
* task. */
|
||||||
xTaskResumeFromISR( xSemTestTaskHandle );
|
xTaskResumeFromISR( xSemTestTaskHandle );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
* Changes from V2.0.0
|
||||||
|
*
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -63,23 +63,23 @@ Changes from V2.0.0
|
||||||
#define deathSTACK_SIZE ( ( unsigned short ) 512 )
|
#define deathSTACK_SIZE ( ( unsigned short ) 512 )
|
||||||
|
|
||||||
/* The task originally created which is responsible for periodically dynamically
|
/* The task originally created which is responsible for periodically dynamically
|
||||||
creating another four tasks. */
|
* creating another four tasks. */
|
||||||
static void vCreateTasks( void * pvParameters );
|
static void vCreateTasks( void * pvParameters );
|
||||||
|
|
||||||
/* The task function of the dynamically created tasks. */
|
/* The task function of the dynamically created tasks. */
|
||||||
static void vSuicidalTask( void * pvParameters );
|
static void vSuicidalTask( void * pvParameters );
|
||||||
|
|
||||||
/* A variable which is incremented every time the dynamic tasks are created. This
|
/* A variable which is incremented every time the dynamic tasks are created. This
|
||||||
is used to check that the task is still running. */
|
* is used to check that the task is still running. */
|
||||||
static volatile short sCreationCount = 0;
|
static volatile short sCreationCount = 0;
|
||||||
|
|
||||||
/* Used to store the number of tasks that were originally running so the creator
|
/* Used to store the number of tasks that were originally running so the creator
|
||||||
task can tell if any of the suicidal tasks have failed to die. */
|
* task can tell if any of the suicidal tasks have failed to die. */
|
||||||
static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0;
|
static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0;
|
||||||
static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5;
|
static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5;
|
||||||
|
|
||||||
/* Used to store a handle to the tasks that should be killed by a suicidal task,
|
/* Used to store a handle to the tasks that should be killed by a suicidal task,
|
||||||
before it kills itself. */
|
* before it kills itself. */
|
||||||
TaskHandle_t xCreatedTask1, xCreatedTask2;
|
TaskHandle_t xCreatedTask1, xCreatedTask2;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -89,14 +89,14 @@ void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )
|
||||||
unsigned portBASE_TYPE * puxPriority;
|
unsigned portBASE_TYPE * puxPriority;
|
||||||
|
|
||||||
/* Create the Creator tasks - passing in as a parameter the priority at which
|
/* Create the Creator tasks - passing in as a parameter the priority at which
|
||||||
the suicidal tasks should be created. */
|
* the suicidal tasks should be created. */
|
||||||
puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
|
puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );
|
||||||
*puxPriority = uxPriority;
|
*puxPriority = uxPriority;
|
||||||
|
|
||||||
xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );
|
xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );
|
||||||
|
|
||||||
/* Record the number of tasks that are running now so we know if any of the
|
/* Record the number of tasks that are running now so we know if any of the
|
||||||
suicidal tasks have failed to be killed. */
|
* suicidal tasks have failed to be killed. */
|
||||||
uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
|
uxTasksRunningAtStart = uxTaskGetNumberOfTasks();
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -110,8 +110,8 @@ const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS;
|
||||||
if( pvParameters != NULL )
|
if( pvParameters != NULL )
|
||||||
{
|
{
|
||||||
/* This task is periodically created four times. Tow created tasks are
|
/* This task is periodically created four times. Tow created tasks are
|
||||||
passed a handle to the other task so it can kill it before killing itself.
|
* passed a handle to the other task so it can kill it before killing itself.
|
||||||
The other task is passed in null. */
|
* The other task is passed in null. */
|
||||||
xTaskToKill = *( TaskHandle_t * ) pvParameters;
|
xTaskToKill = *( TaskHandle_t * ) pvParameters;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -169,7 +169,7 @@ const char * const pcTaskStartMsg = "Create task started.\r\n";
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* This is called to check that the creator task is still running and that there
|
/* This is called to check that the creator task is still running and that there
|
||||||
are not any more than four extra tasks. */
|
* are not any more than four extra tasks. */
|
||||||
portBASE_TYPE xIsCreateTaskStillRunning( void )
|
portBASE_TYPE xIsCreateTaskStillRunning( void )
|
||||||
{
|
{
|
||||||
static short sLastCreationCount = 0;
|
static short sLastCreationCount = 0;
|
||||||
|
|
@ -180,6 +180,7 @@ unsigned portBASE_TYPE uxTasksRunningNow;
|
||||||
{
|
{
|
||||||
sReturn = pdFALSE;
|
sReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLastCreationCount = sCreationCount;
|
sLastCreationCount = sCreationCount;
|
||||||
|
|
||||||
uxTasksRunningNow = uxTaskGetNumberOfTasks();
|
uxTasksRunningNow = uxTaskGetNumberOfTasks();
|
||||||
|
|
@ -199,5 +200,3 @@ unsigned portBASE_TYPE uxTasksRunningNow;
|
||||||
|
|
||||||
return sReturn;
|
return sReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,19 +91,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
* Changes from V2.0.0
|
||||||
|
*
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
+ Added a second, simple test that uses the functions
|
+ Added a second, simple test that uses the functions
|
||||||
vQueueReceiveWhenSuspendedTask() and vQueueSendWhenSuspendedTask().
|
+ vQueueReceiveWhenSuspendedTask() and vQueueSendWhenSuspendedTask().
|
||||||
|
+
|
||||||
Changes from V3.1.1
|
+ Changes from V3.1.1
|
||||||
|
+
|
||||||
+ Added a third simple test that uses the vTaskPrioritySet() function
|
+ Added a third simple test that uses the vTaskPrioritySet() function
|
||||||
while the scheduler is suspended.
|
+ while the scheduler is suspended.
|
||||||
+ Modified the controller task slightly to test the calling of
|
+ Modified the controller task slightly to test the calling of
|
||||||
vTaskResumeAll() while the scheduler is suspended.
|
+ vTaskResumeAll() while the scheduler is suspended.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -127,12 +127,12 @@ static void vContinuousIncrementTask( void * pvParameters );
|
||||||
static void vCounterControlTask( void * pvParameters );
|
static void vCounterControlTask( void * pvParameters );
|
||||||
|
|
||||||
/* The simple test functions that check sending and receiving while the
|
/* The simple test functions that check sending and receiving while the
|
||||||
scheduler is suspended. */
|
* scheduler is suspended. */
|
||||||
static void vQueueReceiveWhenSuspendedTask( void * pvParameters );
|
static void vQueueReceiveWhenSuspendedTask( void * pvParameters );
|
||||||
static void vQueueSendWhenSuspendedTask( void * pvParameters );
|
static void vQueueSendWhenSuspendedTask( void * pvParameters );
|
||||||
|
|
||||||
/* The simple test functions that check raising and lowering of task priorities
|
/* The simple test functions that check raising and lowering of task priorities
|
||||||
while the scheduler is suspended. */
|
* while the scheduler is suspended. */
|
||||||
static void prvChangePriorityWhenSuspendedTask( void * pvParameters );
|
static void prvChangePriorityWhenSuspendedTask( void * pvParameters );
|
||||||
static void prvChangePriorityHelperTask( void * pvParameters );
|
static void prvChangePriorityHelperTask( void * pvParameters );
|
||||||
|
|
||||||
|
|
@ -148,21 +148,21 @@ static void prvChangePriorityHelperTask( void *pvParameters );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Handles to the two counter tasks. These could be passed in as parameters
|
/* Handles to the two counter tasks. These could be passed in as parameters
|
||||||
to the controller task to prevent them having to be file scope. */
|
* to the controller task to prevent them having to be file scope. */
|
||||||
static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle, xChangePriorityWhenSuspendedHandle;
|
static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle, xChangePriorityWhenSuspendedHandle;
|
||||||
|
|
||||||
/* The shared counter variable. This is passed in as a parameter to the two
|
/* The shared counter variable. This is passed in as a parameter to the two
|
||||||
counter variables for demonstration purposes. */
|
* counter variables for demonstration purposes. */
|
||||||
static unsigned long ulCounter;
|
static unsigned long ulCounter;
|
||||||
|
|
||||||
/* Variable used in a similar way by the test that checks the raising and
|
/* Variable used in a similar way by the test that checks the raising and
|
||||||
lowering of task priorities while the scheduler is suspended. */
|
* lowering of task priorities while the scheduler is suspended. */
|
||||||
static unsigned long ulPrioritySetCounter;
|
static unsigned long ulPrioritySetCounter;
|
||||||
|
|
||||||
/* Variables used to check that the tasks are still operating without error.
|
/* Variables used to check that the tasks are still operating without error.
|
||||||
Each complete iteration of the controller task increments this variable
|
* Each complete iteration of the controller task increments this variable
|
||||||
provided no errors have been found. The variable maintaining the same value
|
* provided no errors have been found. The variable maintaining the same value
|
||||||
is therefore indication of an error. */
|
* is therefore indication of an error. */
|
||||||
static unsigned short usCheckVariable = ( unsigned short ) 0;
|
static unsigned short usCheckVariable = ( unsigned short ) 0;
|
||||||
static portBASE_TYPE xSuspendedQueueSendError = pdFALSE;
|
static portBASE_TYPE xSuspendedQueueSendError = pdFALSE;
|
||||||
static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE;
|
static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE;
|
||||||
|
|
@ -172,6 +172,7 @@ static portBASE_TYPE xPriorityRaiseWhenSuspendedError = pdFALSE;
|
||||||
QueueHandle_t xSuspendedTestQueue;
|
QueueHandle_t xSuspendedTestQueue;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the seven tasks as described at the top of the file.
|
* Start the seven tasks as described at the top of the file.
|
||||||
* Note that the limited count task is given a higher priority.
|
* Note that the limited count task is given a higher priority.
|
||||||
|
|
@ -198,11 +199,11 @@ static void vLimitedIncrementTask( void * pvParameters )
|
||||||
unsigned long * pulCounter;
|
unsigned long * pulCounter;
|
||||||
|
|
||||||
/* Take a pointer to the shared variable from the parameters passed into
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
the task. */
|
* the task. */
|
||||||
pulCounter = ( unsigned long * ) pvParameters;
|
pulCounter = ( unsigned long * ) pvParameters;
|
||||||
|
|
||||||
/* This will run before the control task, so the first thing it does is
|
/* This will run before the control task, so the first thing it does is
|
||||||
suspend - the control task will resume it when ready. */
|
* suspend - the control task will resume it when ready. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
|
|
@ -228,17 +229,17 @@ unsigned long *pulCounter;
|
||||||
unsigned portBASE_TYPE uxOurPriority;
|
unsigned portBASE_TYPE uxOurPriority;
|
||||||
|
|
||||||
/* Take a pointer to the shared variable from the parameters passed into
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
the task. */
|
* the task. */
|
||||||
pulCounter = ( unsigned long * ) pvParameters;
|
pulCounter = ( unsigned long * ) pvParameters;
|
||||||
|
|
||||||
/* Query our priority so we can raise it when exclusive access to the
|
/* Query our priority so we can raise it when exclusive access to the
|
||||||
shared variable is required. */
|
* shared variable is required. */
|
||||||
uxOurPriority = uxTaskPriorityGet( NULL );
|
uxOurPriority = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Raise our priority above the controller task to ensure a context
|
/* Raise our priority above the controller task to ensure a context
|
||||||
switch does not occur while we are accessing this variable. */
|
* switch does not occur while we are accessing this variable. */
|
||||||
vTaskPrioritySet( NULL, uxOurPriority + 1 );
|
vTaskPrioritySet( NULL, uxOurPriority + 1 );
|
||||||
( *pulCounter )++;
|
( *pulCounter )++;
|
||||||
vTaskPrioritySet( NULL, uxOurPriority );
|
vTaskPrioritySet( NULL, uxOurPriority );
|
||||||
|
|
@ -278,7 +279,7 @@ const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n";
|
||||||
for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
|
for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
|
||||||
{
|
{
|
||||||
/* Suspend the continuous count task so we can take a mirror of the
|
/* Suspend the continuous count task so we can take a mirror of the
|
||||||
shared variable without risk of corruption. */
|
* shared variable without risk of corruption. */
|
||||||
vTaskSuspend( xContinuousIncrementHandle );
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
ulLastCounter = ulCounter;
|
ulLastCounter = ulCounter;
|
||||||
vTaskResume( xContinuousIncrementHandle );
|
vTaskResume( xContinuousIncrementHandle );
|
||||||
|
|
@ -287,14 +288,14 @@ const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n";
|
||||||
vTaskDelay( priSLEEP_TIME );
|
vTaskDelay( priSLEEP_TIME );
|
||||||
|
|
||||||
/* Check the shared variable again. This time to ensure mutual
|
/* Check the shared variable again. This time to ensure mutual
|
||||||
exclusion the whole scheduler will be locked. This is just for
|
* exclusion the whole scheduler will be locked. This is just for
|
||||||
demo purposes! */
|
* demo purposes! */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
if( ulLastCounter == ulCounter )
|
if( ulLastCounter == ulCounter )
|
||||||
{
|
{
|
||||||
/* The shared variable has not changed. There is a problem
|
/* The shared variable has not changed. There is a problem
|
||||||
with the continuous count task so flag an error. */
|
* with the continuous count task so flag an error. */
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -304,7 +305,6 @@ const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n";
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Second section: */
|
/* Second section: */
|
||||||
|
|
||||||
/* Suspend the continuous counter task so it stops accessing the shared variable. */
|
/* Suspend the continuous counter task so it stops accessing the shared variable. */
|
||||||
|
|
@ -314,10 +314,10 @@ const char * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n";
|
||||||
ulCounter = ( unsigned long ) 0;
|
ulCounter = ( unsigned long ) 0;
|
||||||
|
|
||||||
/* Resume the limited count task which has a higher priority than us.
|
/* Resume the limited count task which has a higher priority than us.
|
||||||
We should therefore not return from this call until the limited count
|
* We should therefore not return from this call until the limited count
|
||||||
task has suspended itself with a known value in the counter variable.
|
* task has suspended itself with a known value in the counter variable.
|
||||||
The scheduler suspension is not necessary but is included for test
|
* The scheduler suspension is not necessary but is included for test
|
||||||
purposes. */
|
* purposes. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
vTaskResume( xLimitedIncrementHandle );
|
vTaskResume( xLimitedIncrementHandle );
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
|
|
@ -403,16 +403,17 @@ portBASE_TYPE xGotValue;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Suspending the scheduler here is fairly pointless and
|
/* Suspending the scheduler here is fairly pointless and
|
||||||
undesirable for a normal application. It is done here purely
|
* undesirable for a normal application. It is done here purely
|
||||||
to test the scheduler. The inner xTaskResumeAll() should
|
* to test the scheduler. The inner xTaskResumeAll() should
|
||||||
never return pdTRUE as the scheduler is still locked by the
|
* never return pdTRUE as the scheduler is still locked by the
|
||||||
outer call. */
|
* outer call. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
|
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xTaskResumeAll() )
|
if( xTaskResumeAll() )
|
||||||
{
|
{
|
||||||
xSuspendedQueueReceiveError = pdTRUE;
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
|
|
@ -423,7 +424,6 @@ portBASE_TYPE xGotValue;
|
||||||
#if configUSE_PREEMPTION == 0
|
#if configUSE_PREEMPTION == 0
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} while( xGotValue == pdFALSE );
|
} while( xGotValue == pdFALSE );
|
||||||
|
|
||||||
if( ulReceivedValue != ulExpectedValue )
|
if( ulReceivedValue != ulExpectedValue )
|
||||||
|
|
@ -432,6 +432,7 @@ portBASE_TYPE xGotValue;
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
}
|
}
|
||||||
|
|
||||||
xSuspendedQueueReceiveError = pdTRUE;
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -454,11 +455,11 @@ const char * const pcTaskFailMsg = "Priority change when suspended task failed.\
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Start with the counter at 0 so we know what the counter should be
|
/* Start with the counter at 0 so we know what the counter should be
|
||||||
when we check it next. */
|
* when we check it next. */
|
||||||
ulPrioritySetCounter = ( unsigned long ) 0;
|
ulPrioritySetCounter = ( unsigned long ) 0;
|
||||||
|
|
||||||
/* Resume the helper task. At this time it has a priority lower than
|
/* Resume the helper task. At this time it has a priority lower than
|
||||||
ours so no context switch should occur. */
|
* ours so no context switch should occur. */
|
||||||
vTaskResume( xChangePriorityWhenSuspendedHandle );
|
vTaskResume( xChangePriorityWhenSuspendedHandle );
|
||||||
|
|
||||||
/* Check to ensure the task just resumed has not executed. */
|
/* Check to ensure the task just resumed has not executed. */
|
||||||
|
|
@ -478,8 +479,8 @@ const char * const pcTaskFailMsg = "Priority change when suspended task failed.\
|
||||||
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) );
|
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) );
|
||||||
|
|
||||||
/* Again, even though the helper task has a priority greater than
|
/* Again, even though the helper task has a priority greater than
|
||||||
ours, it should not have executed yet because the scheduler is
|
* ours, it should not have executed yet because the scheduler is
|
||||||
suspended. */
|
* suspended. */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
if( ulPrioritySetCounter != ( unsigned long ) 0 )
|
if( ulPrioritySetCounter != ( unsigned long ) 0 )
|
||||||
|
|
@ -493,10 +494,10 @@ const char * const pcTaskFailMsg = "Priority change when suspended task failed.\
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
|
|
||||||
/* Now the scheduler has been resumed the helper task should
|
/* Now the scheduler has been resumed the helper task should
|
||||||
immediately preempt us and execute. When it executes it will increment
|
* immediately preempt us and execute. When it executes it will increment
|
||||||
the ulPrioritySetCounter exactly once before suspending itself.
|
* the ulPrioritySetCounter exactly once before suspending itself.
|
||||||
|
*
|
||||||
We should now always find the counter set to 1. */
|
* We should now always find the counter set to 1. */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
if( ulPrioritySetCounter != ( unsigned long ) 1 )
|
if( ulPrioritySetCounter != ( unsigned long ) 1 )
|
||||||
|
|
@ -511,7 +512,7 @@ const char * const pcTaskFailMsg = "Priority change when suspended task failed.\
|
||||||
vTaskDelay( priSLEEP_TIME * 2 );
|
vTaskDelay( priSLEEP_TIME * 2 );
|
||||||
|
|
||||||
/* Set the priority of the helper task back ready for the next
|
/* Set the priority of the helper task back ready for the next
|
||||||
execution of this task. */
|
* execution of this task. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY );
|
vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY );
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
|
|
@ -527,10 +528,10 @@ static void prvChangePriorityHelperTask( void *pvParameters )
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* This is the helper task for prvChangePriorityWhenSuspendedTask().
|
/* This is the helper task for prvChangePriorityWhenSuspendedTask().
|
||||||
It has it's priority raised and lowered. When it runs it simply
|
* It has it's priority raised and lowered. When it runs it simply
|
||||||
increments the counter then suspends itself again. This allows
|
* increments the counter then suspends itself again. This allows
|
||||||
prvChangePriorityWhenSuspendedTask() to know how many times it has
|
* prvChangePriorityWhenSuspendedTask() to know how many times it has
|
||||||
executed. */
|
* executed. */
|
||||||
ulPrioritySetCounter++;
|
ulPrioritySetCounter++;
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -541,12 +542,12 @@ static void prvChangePriorityHelperTask( void *pvParameters )
|
||||||
portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )
|
portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void )
|
||||||
{
|
{
|
||||||
/* Keep a history of the check variables so we know if it has been incremented
|
/* Keep a history of the check variables so we know if it has been incremented
|
||||||
since the last call. */
|
* since the last call. */
|
||||||
static unsigned short usLastTaskCheck = ( unsigned short ) 0;
|
static unsigned short usLastTaskCheck = ( unsigned short ) 0;
|
||||||
portBASE_TYPE xReturn = pdTRUE;
|
portBASE_TYPE xReturn = pdTRUE;
|
||||||
|
|
||||||
/* Check the tasks are still running by ensuring the check variable
|
/* Check the tasks are still running by ensuring the check variable
|
||||||
is still incrementing. */
|
* is still incrementing. */
|
||||||
|
|
||||||
if( usCheckVariable == usLastTaskCheck )
|
if( usCheckVariable == usLastTaskCheck )
|
||||||
{
|
{
|
||||||
|
|
@ -572,7 +573,3 @@ portBASE_TYPE xReturn = pdTRUE;
|
||||||
usLastTaskCheck = usCheckVariable;
|
usLastTaskCheck = usCheckVariable;
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,37 +66,37 @@
|
||||||
#define evtNO_DELAY 0
|
#define evtNO_DELAY 0
|
||||||
|
|
||||||
/* Just indexes used to uniquely identify the tasks. Note that two tasks are
|
/* Just indexes used to uniquely identify the tasks. Note that two tasks are
|
||||||
'highest' priority. */
|
* 'highest' priority. */
|
||||||
#define evtHIGHEST_PRIORITY_INDEX_2 3
|
#define evtHIGHEST_PRIORITY_INDEX_2 3
|
||||||
#define evtHIGHEST_PRIORITY_INDEX_1 2
|
#define evtHIGHEST_PRIORITY_INDEX_1 2
|
||||||
#define evtMEDIUM_PRIORITY_INDEX 1
|
#define evtMEDIUM_PRIORITY_INDEX 1
|
||||||
#define evtLOWEST_PRIORITY_INDEX 0
|
#define evtLOWEST_PRIORITY_INDEX 0
|
||||||
|
|
||||||
/* Each event task increments one of these counters each time it reads data
|
/* Each event task increments one of these counters each time it reads data
|
||||||
from the queue. */
|
* from the queue. */
|
||||||
static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
|
static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
/* Each time the controlling task posts onto the queue it increments the
|
/* Each time the controlling task posts onto the queue it increments the
|
||||||
expected count of the task that it expected to read the data from the queue
|
* expected count of the task that it expected to read the data from the queue
|
||||||
(i.e. the task with the highest priority that should be blocked on the queue).
|
* (i.e. the task with the highest priority that should be blocked on the queue).
|
||||||
|
*
|
||||||
xExpectedTaskCounters are incremented from the controlling task, and
|
* xExpectedTaskCounters are incremented from the controlling task, and
|
||||||
xTaskCounters are incremented from the individual event tasks - therefore
|
* xTaskCounters are incremented from the individual event tasks - therefore
|
||||||
comparing xTaskCounters to xExpectedTaskCounters shows whether or not the
|
* comparing xTaskCounters to xExpectedTaskCounters shows whether or not the
|
||||||
correct task was unblocked by the post. */
|
* correct task was unblocked by the post. */
|
||||||
static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
|
static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
/* Handles to the four event tasks. These are required to suspend and resume
|
/* Handles to the four event tasks. These are required to suspend and resume
|
||||||
the tasks. */
|
* the tasks. */
|
||||||
static TaskHandle_t xCreatedTasks[ evtNUM_TASKS ];
|
static TaskHandle_t xCreatedTasks[ evtNUM_TASKS ];
|
||||||
|
|
||||||
/* The single queue onto which the controlling task posts, and the four event
|
/* The single queue onto which the controlling task posts, and the four event
|
||||||
tasks block. */
|
* tasks block. */
|
||||||
static QueueHandle_t xQueue;
|
static QueueHandle_t xQueue;
|
||||||
|
|
||||||
/* Flag used to indicate whether or not an error has occurred at any time.
|
/* Flag used to indicate whether or not an error has occurred at any time.
|
||||||
An error is either the queue being full when not expected, or an unexpected
|
* An error is either the queue being full when not expected, or an unexpected
|
||||||
task reading data from the queue. */
|
* task reading data from the queue. */
|
||||||
static portBASE_TYPE xHealthStatus = pdPASS;
|
static portBASE_TYPE xHealthStatus = pdPASS;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -108,23 +108,24 @@ static void prvMultiEventTask( void *pvParameters );
|
||||||
static void prvEventControllerTask( void * pvParameters );
|
static void prvEventControllerTask( void * pvParameters );
|
||||||
|
|
||||||
/* This is a utility function that posts data to the queue, then compares
|
/* This is a utility function that posts data to the queue, then compares
|
||||||
xExpectedTaskCounters with xTaskCounters to ensure everything worked as
|
* xExpectedTaskCounters with xTaskCounters to ensure everything worked as
|
||||||
expected.
|
* expected.
|
||||||
|
*
|
||||||
The event tasks all have higher priorities the controlling task. Therefore
|
* The event tasks all have higher priorities the controlling task. Therefore
|
||||||
the controlling task will always get preempted between writhing to the queue
|
* the controlling task will always get preempted between writhing to the queue
|
||||||
and checking the task counters.
|
* and checking the task counters.
|
||||||
|
*
|
||||||
@param xExpectedTask The index to the task that the controlling task thinks
|
* @param xExpectedTask The index to the task that the controlling task thinks
|
||||||
should be the highest priority task waiting for data, and
|
* should be the highest priority task waiting for data, and
|
||||||
therefore the task that will unblock.
|
* therefore the task that will unblock.
|
||||||
|
*
|
||||||
@param xIncrement The number of items that should be written to the queue.
|
* @param xIncrement The number of items that should be written to the queue.
|
||||||
*/
|
*/
|
||||||
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement );
|
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask,
|
||||||
|
portBASE_TYPE xIncrement );
|
||||||
|
|
||||||
/* This is just incremented each cycle of the controlling tasks function so
|
/* This is just incremented each cycle of the controlling tasks function so
|
||||||
the main application can ensure the test is still running. */
|
* the main application can ensure the test is still running. */
|
||||||
static portBASE_TYPE xCheckVariable = 0;
|
static portBASE_TYPE xCheckVariable = 0;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -135,11 +136,11 @@ void vStartMultiEventTasks( void )
|
||||||
xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
|
xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
|
||||||
|
|
||||||
/* Start the controlling task. This has the idle priority to ensure it is
|
/* Start the controlling task. This has the idle priority to ensure it is
|
||||||
always preempted by the event tasks. */
|
* always preempted by the event tasks. */
|
||||||
xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
||||||
/* Start the four event tasks. Note that two have priority 3, one
|
/* Start the four event tasks. Note that two have priority 3, one
|
||||||
priority 2 and the other priority 1. */
|
* priority 2 and the other priority 1. */
|
||||||
xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) );
|
xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) );
|
||||||
xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) );
|
xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) );
|
||||||
xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) );
|
xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) );
|
||||||
|
|
@ -164,7 +165,7 @@ const char * const pcTaskStartMsg = "Multi event task started.\r\n";
|
||||||
if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) )
|
if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) )
|
||||||
{
|
{
|
||||||
/* We unblocked by reading the queue - so simply increment
|
/* We unblocked by reading the queue - so simply increment
|
||||||
the counter specific to this task instance. */
|
* the counter specific to this task instance. */
|
||||||
( *pxCounter )++;
|
( *pxCounter )++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -188,10 +189,10 @@ portBASE_TYPE xDummy = 0;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* All tasks are blocked on the queue. When a message is posted one of
|
/* All tasks are blocked on the queue. When a message is posted one of
|
||||||
the two tasks that share the highest priority should unblock to read
|
* the two tasks that share the highest priority should unblock to read
|
||||||
the queue. The next message written should unblock the other task with
|
* the queue. The next message written should unblock the other task with
|
||||||
the same high priority, and so on in order. No other task should
|
* the same high priority, and so on in order. No other task should
|
||||||
unblock to read data as they have lower priorities. */
|
* unblock to read data as they have lower priorities. */
|
||||||
|
|
||||||
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 );
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 );
|
||||||
|
|
@ -200,32 +201,32 @@ portBASE_TYPE xDummy = 0;
|
||||||
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
||||||
/* For the rest of these tests we don't need the second 'highest'
|
/* For the rest of these tests we don't need the second 'highest'
|
||||||
priority task - so it is suspended. */
|
* priority task - so it is suspended. */
|
||||||
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Now suspend the other highest priority task. The medium priority
|
/* Now suspend the other highest priority task. The medium priority
|
||||||
task will then be the task with the highest priority that remains
|
* task will then be the task with the highest priority that remains
|
||||||
blocked on the queue. */
|
* blocked on the queue. */
|
||||||
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
|
|
||||||
/* This time, when we post onto the queue we will expect the medium
|
/* This time, when we post onto the queue we will expect the medium
|
||||||
priority task to unblock and preempt us. */
|
* priority task to unblock and preempt us. */
|
||||||
prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 );
|
prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 );
|
||||||
|
|
||||||
/* Now try resuming the highest priority task while the scheduler is
|
/* Now try resuming the highest priority task while the scheduler is
|
||||||
suspended. The task should start executing as soon as the scheduler
|
* suspended. The task should start executing as soon as the scheduler
|
||||||
is resumed - therefore when we post to the queue again, the highest
|
* is resumed - therefore when we post to the queue again, the highest
|
||||||
priority task should again preempt us. */
|
* priority task should again preempt us. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
||||||
/* Now we are going to suspend the high and medium priority tasks. The
|
/* Now we are going to suspend the high and medium priority tasks. The
|
||||||
low priority task should then preempt us. Again the task suspension is
|
* low priority task should then preempt us. Again the task suspension is
|
||||||
done with the whole scheduler suspended just for test purposes. */
|
* done with the whole scheduler suspended just for test purposes. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
||||||
|
|
@ -233,9 +234,9 @@ portBASE_TYPE xDummy = 0;
|
||||||
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 );
|
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 );
|
||||||
|
|
||||||
/* Do the same basic test another few times - selectively suspending
|
/* Do the same basic test another few times - selectively suspending
|
||||||
and resuming tasks and each time calling prvCheckTaskCounters() passing
|
* and resuming tasks and each time calling prvCheckTaskCounters() passing
|
||||||
to the function the number of the task we expected to be unblocked by
|
* to the function the number of the task we expected to be unblocked by
|
||||||
the post. */
|
* the post. */
|
||||||
|
|
||||||
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] );
|
||||||
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 );
|
||||||
|
|
@ -261,19 +262,19 @@ portBASE_TYPE xDummy = 0;
|
||||||
vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
|
||||||
/* Now when we resume the low priority task and write to the queue 3
|
/* Now when we resume the low priority task and write to the queue 3
|
||||||
times. We expect the low priority task to service the queue three
|
* times. We expect the low priority task to service the queue three
|
||||||
times. */
|
* times. */
|
||||||
vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH );
|
prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH );
|
||||||
|
|
||||||
/* Again suspend all tasks (only the low priority task is not suspended
|
/* Again suspend all tasks (only the low priority task is not suspended
|
||||||
already). */
|
* already). */
|
||||||
vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
|
||||||
/* This time we are going to suspend the scheduler, resume the low
|
/* This time we are going to suspend the scheduler, resume the low
|
||||||
priority task, then resume the high priority task. In this state we
|
* priority task, then resume the high priority task. In this state we
|
||||||
will write to the queue three times. When the scheduler is resumed
|
* will write to the queue three times. When the scheduler is resumed
|
||||||
we expect the high priority task to service all three messages. */
|
* we expect the high priority task to service all three messages. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] );
|
||||||
|
|
@ -288,7 +289,7 @@ portBASE_TYPE xDummy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The queue should not have been serviced yet!. The scheduler
|
/* The queue should not have been serviced yet!. The scheduler
|
||||||
is still suspended. */
|
* is still suspended. */
|
||||||
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
||||||
{
|
{
|
||||||
xHealthStatus = pdFAIL;
|
xHealthStatus = pdFAIL;
|
||||||
|
|
@ -297,16 +298,17 @@ portBASE_TYPE xDummy = 0;
|
||||||
xTaskResumeAll();
|
xTaskResumeAll();
|
||||||
|
|
||||||
/* We should have been preempted by resuming the scheduler - so by the
|
/* We should have been preempted by resuming the scheduler - so by the
|
||||||
time we are running again we expect the high priority task to have
|
* time we are running again we expect the high priority task to have
|
||||||
removed three items from the queue. */
|
* removed three items from the queue. */
|
||||||
xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH;
|
xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH;
|
||||||
|
|
||||||
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
||||||
{
|
{
|
||||||
xHealthStatus = pdFAIL;
|
xHealthStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The medium priority and second high priority tasks are still
|
/* The medium priority and second high priority tasks are still
|
||||||
suspended. Make sure to resume them before starting again. */
|
* suspended. Make sure to resume them before starting again. */
|
||||||
vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] );
|
||||||
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
|
vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] );
|
||||||
|
|
||||||
|
|
@ -316,12 +318,13 @@ portBASE_TYPE xDummy = 0;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement )
|
static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask,
|
||||||
|
portBASE_TYPE xIncrement )
|
||||||
{
|
{
|
||||||
portBASE_TYPE xDummy = 0;
|
portBASE_TYPE xDummy = 0;
|
||||||
|
|
||||||
/* Write to the queue the requested number of times. The data written is
|
/* Write to the queue the requested number of times. The data written is
|
||||||
not important. */
|
* not important. */
|
||||||
for( xDummy = 0; xDummy < xIncrement; xDummy++ )
|
for( xDummy = 0; xDummy < xIncrement; xDummy++ )
|
||||||
{
|
{
|
||||||
if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE )
|
if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE )
|
||||||
|
|
@ -332,17 +335,17 @@ portBASE_TYPE xDummy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All the tasks blocked on the queue have a priority higher than the
|
/* All the tasks blocked on the queue have a priority higher than the
|
||||||
controlling task. Writing to the queue will therefore have caused this
|
* controlling task. Writing to the queue will therefore have caused this
|
||||||
task to be preempted. By the time this line executes the event task will
|
* task to be preempted. By the time this line executes the event task will
|
||||||
have executed and incremented its counter. Increment the expected counter
|
* have executed and incremented its counter. Increment the expected counter
|
||||||
to the same value. */
|
* to the same value. */
|
||||||
( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement;
|
( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement;
|
||||||
|
|
||||||
/* Check the actual counts and expected counts really are the same. */
|
/* Check the actual counts and expected counts really are the same. */
|
||||||
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) )
|
||||||
{
|
{
|
||||||
/* The counters were not the same. This means a task we did not expect
|
/* The counters were not the same. This means a task we did not expect
|
||||||
to unblock actually did unblock. */
|
* to unblock actually did unblock. */
|
||||||
xHealthStatus = pdFAIL;
|
xHealthStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +356,7 @@ portBASE_TYPE xAreMultiEventTasksStillRunning( void )
|
||||||
static portBASE_TYPE xPreviousCheckVariable = 0;
|
static portBASE_TYPE xPreviousCheckVariable = 0;
|
||||||
|
|
||||||
/* Called externally to periodically check that this test is still
|
/* Called externally to periodically check that this test is still
|
||||||
operational. */
|
* operational. */
|
||||||
|
|
||||||
if( xPreviousCheckVariable == xCheckVariable )
|
if( xPreviousCheckVariable == xCheckVariable )
|
||||||
{
|
{
|
||||||
|
|
@ -364,5 +367,3 @@ static portBASE_TYPE xPreviousCheckVariable = 0;
|
||||||
|
|
||||||
return xHealthStatus;
|
return xHealthStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
* Changes from V2.0.0
|
||||||
|
*
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
|
+
|
||||||
Changes from V2.1.1
|
+ Changes from V2.1.1
|
||||||
|
+
|
||||||
+ The stack size now uses configMINIMAL_STACK_SIZE.
|
+ The stack size now uses configMINIMAL_STACK_SIZE.
|
||||||
+ String constants made file scope to decrease stack depth on 8051 port.
|
+ String constants made file scope to decrease stack depth on 8051 port.
|
||||||
*/
|
*/
|
||||||
|
|
@ -74,7 +74,7 @@ typedef struct LED_PARAMETERS
|
||||||
} xLEDParameters;
|
} xLEDParameters;
|
||||||
|
|
||||||
/* The task that is created eight times - each time with a different xLEDParaemtes
|
/* The task that is created eight times - each time with a different xLEDParaemtes
|
||||||
structure passed in as the parameter. */
|
* structure passed in as the parameter. */
|
||||||
static void vLEDFlashTask( void * pvParameters );
|
static void vLEDFlashTask( void * pvParameters );
|
||||||
|
|
||||||
/* String to print if USE_STDIO is defined. */
|
/* String to print if USE_STDIO is defined. */
|
||||||
|
|
@ -93,7 +93,7 @@ const TickType_t xFlashRate = 125;
|
||||||
for( uxLEDTask = 0; uxLEDTask < uxNumOfLEDs; ++uxLEDTask )
|
for( uxLEDTask = 0; uxLEDTask < uxNumOfLEDs; ++uxLEDTask )
|
||||||
{
|
{
|
||||||
/* Create and complete the structure used to pass parameters to the next
|
/* Create and complete the structure used to pass parameters to the next
|
||||||
created task. */
|
* created task. */
|
||||||
pxLEDParameters = ( xLEDParameters * ) pvPortMalloc( sizeof( xLEDParameters ) );
|
pxLEDParameters = ( xLEDParameters * ) pvPortMalloc( sizeof( xLEDParameters ) );
|
||||||
pxLEDParameters->uxLED = uxLEDTask;
|
pxLEDParameters->uxLED = uxLEDTask;
|
||||||
pxLEDParameters->xFlashRate = ( xFlashRate + ( xFlashRate * ( TickType_t ) uxLEDTask ) );
|
pxLEDParameters->xFlashRate = ( xFlashRate + ( xFlashRate * ( TickType_t ) uxLEDTask ) );
|
||||||
|
|
@ -125,4 +125,3 @@ xLEDParameters *pxParameters;
|
||||||
vParTestToggleLED( pxParameters->uxLED );
|
vParTestToggleLED( pxParameters->uxLED );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V1.2.3
|
* Changes from V1.2.3
|
||||||
|
*
|
||||||
+ The created tasks now include calls to tskYIELD(), allowing them to be used
|
+ The created tasks now include calls to tskYIELD(), allowing them to be used
|
||||||
with the cooperative scheduler.
|
+ with the cooperative scheduler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -64,15 +64,15 @@ Changes from V1.2.3
|
||||||
#define mathNUMBER_OF_TASKS ( 8 )
|
#define mathNUMBER_OF_TASKS ( 8 )
|
||||||
|
|
||||||
/* Four tasks, each of which performs a different floating point calculation.
|
/* Four tasks, each of which performs a different floating point calculation.
|
||||||
Each of the four is created twice. */
|
* Each of the four is created twice. */
|
||||||
static void vCompetingMathTask1( void * pvParameters );
|
static void vCompetingMathTask1( void * pvParameters );
|
||||||
static void vCompetingMathTask2( void * pvParameters );
|
static void vCompetingMathTask2( void * pvParameters );
|
||||||
static void vCompetingMathTask3( void * pvParameters );
|
static void vCompetingMathTask3( void * pvParameters );
|
||||||
static void vCompetingMathTask4( void * pvParameters );
|
static void vCompetingMathTask4( void * pvParameters );
|
||||||
|
|
||||||
/* These variables are used to check that all the tasks are still running. If a
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
task gets a calculation wrong it will
|
* task gets a calculation wrong it will
|
||||||
stop incrementing its check variable. */
|
* stop incrementing its check variable. */
|
||||||
static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
static volatile unsigned short usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -103,7 +103,7 @@ short sError = pdFALSE;
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -118,7 +118,7 @@ short sError = pdFALSE;
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( fabs( d4 - dAnswer ) > 0.001 )
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -128,7 +128,7 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ short sError = pdFALSE;
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -165,7 +165,7 @@ short sError = pdFALSE;
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( fabs( d4 - dAnswer ) > 0.001 )
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -175,8 +175,8 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know
|
* variable so we know
|
||||||
this task is still running okay. */
|
* this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,14 +199,14 @@ short sError = pdFALSE;
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );
|
pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
/* Keep filling an array, keeping a running total of the values placed in the
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
dTotal1 = 0.0;
|
dTotal1 = 0.0;
|
||||||
|
|
@ -226,6 +226,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dDifference = dTotal1 - dTotal2;
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
|
||||||
if( fabs( dDifference ) > 0.001 )
|
if( fabs( dDifference ) > 0.001 )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -237,7 +238,7 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,14 +259,14 @@ short sError = pdFALSE;
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );
|
pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
/* Keep filling an array, keeping a running total of the values placed in the
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
dTotal1 = 0.0;
|
dTotal1 = 0.0;
|
||||||
|
|
@ -285,6 +286,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dDifference = dTotal1 - dTotal2;
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
|
||||||
if( fabs( dDifference ) > 0.001 )
|
if( fabs( dDifference ) > 0.001 )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -296,7 +298,7 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -307,12 +309,12 @@ short sError = pdFALSE;
|
||||||
portBASE_TYPE xAreMathsTaskStillRunning( void )
|
portBASE_TYPE xAreMathsTaskStillRunning( void )
|
||||||
{
|
{
|
||||||
/* Keep a history of the check variables so we know if they have been incremented
|
/* Keep a history of the check variables so we know if they have been incremented
|
||||||
since the last call. */
|
* since the last call. */
|
||||||
static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
static unsigned short usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
portBASE_TYPE xReturn = pdTRUE, xTask;
|
portBASE_TYPE xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
/* Check the maths tasks are still running by ensuring their check variables
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
are still incrementing. */
|
* are still incrementing. */
|
||||||
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
||||||
{
|
{
|
||||||
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
||||||
|
|
@ -326,6 +328,3 @@ portBASE_TYPE xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V1.2.3
|
* Changes from V1.2.3
|
||||||
|
*
|
||||||
+ The created tasks now include calls to tskYIELD(), allowing them to be used
|
+ The created tasks now include calls to tskYIELD(), allowing them to be used
|
||||||
with the cooperative scheduler.
|
+ with the cooperative scheduler.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -49,10 +49,10 @@ Changes from V1.2.3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V1.2.1
|
* Changes from V1.2.1
|
||||||
|
*
|
||||||
+ The constants used in the calculations are larger to ensure the
|
+ The constants used in the calculations are larger to ensure the
|
||||||
optimiser does not truncate them to 16 bits.
|
+ optimiser does not truncate them to 16 bits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -69,14 +69,14 @@ Changes from V1.2.1
|
||||||
#define intgNUMBER_OF_TASKS ( 8 )
|
#define intgNUMBER_OF_TASKS ( 8 )
|
||||||
|
|
||||||
/* Four tasks, each of which performs a different calculation on four byte
|
/* Four tasks, each of which performs a different calculation on four byte
|
||||||
variables. Each of the four is created twice. */
|
* variables. Each of the four is created twice. */
|
||||||
static void vCompeteingIntMathTask1( void * pvParameters );
|
static void vCompeteingIntMathTask1( void * pvParameters );
|
||||||
static void vCompeteingIntMathTask2( void * pvParameters );
|
static void vCompeteingIntMathTask2( void * pvParameters );
|
||||||
static void vCompeteingIntMathTask3( void * pvParameters );
|
static void vCompeteingIntMathTask3( void * pvParameters );
|
||||||
static void vCompeteingIntMathTask4( void * pvParameters );
|
static void vCompeteingIntMathTask4( void * pvParameters );
|
||||||
|
|
||||||
/* These variables are used to check that all the tasks are still running. If a
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
task gets a calculation wrong it will stop incrementing its check variable. */
|
* task gets a calculation wrong it will stop incrementing its check variable. */
|
||||||
static volatile unsigned short usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
static volatile unsigned short usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -121,7 +121,7 @@ const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( l4 != lAnswer )
|
if( l4 != lAnswer )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -131,7 +131,7 @@ const char * const pcTaskFailMsg = "Integer math task 1 failed.\r\n";
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +151,7 @@ const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -166,7 +166,7 @@ const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( l4 != lAnswer )
|
if( l4 != lAnswer )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -176,7 +176,7 @@ const char * const pcTaskFailMsg = "Integer math task 2 failed.\r\n";
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -197,15 +197,15 @@ const char * const pcTaskFailMsg = "Integer math task 3 failed.\r\n";
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
/* Create the array we are going to use for our check calculation. */
|
/* Create the array we are going to use for our check calculation. */
|
||||||
plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
|
plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
|
||||||
|
|
||||||
/* Keep filling the array, keeping a running total of the values placed in the
|
/* Keep filling the array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
lTotal1 = ( long ) 0;
|
lTotal1 = ( long ) 0;
|
||||||
|
|
@ -235,7 +235,7 @@ const char * const pcTaskFailMsg = "Integer math task 3 failed.\r\n";
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -256,15 +256,15 @@ const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
|
||||||
vPrintDisplayMessage( &pcTaskStartMsg );
|
vPrintDisplayMessage( &pcTaskStartMsg );
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
pusTaskCheckVariable = ( unsigned short * ) pvParameters;
|
||||||
|
|
||||||
/* Create the array we are going to use for our check calculation. */
|
/* Create the array we are going to use for our check calculation. */
|
||||||
plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
|
plArray = ( long * ) pvPortMalloc( ( size_t ) 250 * sizeof( long ) );
|
||||||
|
|
||||||
/* Keep filling the array, keeping a running total of the values placed in the
|
/* Keep filling the array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
lTotal1 = ( long ) 0;
|
lTotal1 = ( long ) 0;
|
||||||
|
|
@ -283,7 +283,6 @@ const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
|
||||||
lTotal2 += plArray[ usPosition ];
|
lTotal2 += plArray[ usPosition ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( lTotal1 != lTotal2 )
|
if( lTotal1 != lTotal2 )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcTaskFailMsg );
|
vPrintDisplayMessage( &pcTaskFailMsg );
|
||||||
|
|
@ -295,7 +294,7 @@ const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -306,12 +305,12 @@ const char * const pcTaskFailMsg = "Integer math task 4 failed.\r\n";
|
||||||
portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )
|
portBASE_TYPE xAreIntegerMathsTaskStillRunning( void )
|
||||||
{
|
{
|
||||||
/* Keep a history of the check variables so we know if they have been incremented
|
/* Keep a history of the check variables so we know if they have been incremented
|
||||||
since the last call. */
|
* since the last call. */
|
||||||
static unsigned short usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
static unsigned short usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned short ) 0 };
|
||||||
portBASE_TYPE xReturn = pdTRUE, xTask;
|
portBASE_TYPE xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
/* Check the maths tasks are still running by ensuring their check variables
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
are still incrementing. */
|
* are still incrementing. */
|
||||||
for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ )
|
for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ )
|
||||||
{
|
{
|
||||||
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
* Changes from V2.0.0
|
||||||
|
*
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -102,5 +102,3 @@ char *pcMessage;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,21 +52,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V1.2.0:
|
* Changes from V1.2.0:
|
||||||
|
*
|
||||||
+ The tasks that operate at the idle priority now use a lower expected
|
+ The tasks that operate at the idle priority now use a lower expected
|
||||||
count than those running at a higher priority. This prevents the low
|
+ count than those running at a higher priority. This prevents the low
|
||||||
priority tasks from signaling an error because they have not been
|
+ priority tasks from signaling an error because they have not been
|
||||||
scheduled enough time for each of them to count the shared variable to
|
+ scheduled enough time for each of them to count the shared variable to
|
||||||
the high value.
|
+ the high value.
|
||||||
|
+
|
||||||
Changes from V2.0.0
|
+ Changes from V2.0.0
|
||||||
|
+
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than unsigned long.
|
+ TickType_t rather than unsigned long.
|
||||||
|
+
|
||||||
Changes from V2.1.1
|
+ Changes from V2.1.1
|
||||||
|
+
|
||||||
+ The stack size now uses configMINIMAL_STACK_SIZE.
|
+ The stack size now uses configMINIMAL_STACK_SIZE.
|
||||||
+ String constants made file scope to decrease stack depth on 8051 port.
|
+ String constants made file scope to decrease stack depth on 8051 port.
|
||||||
*/
|
*/
|
||||||
|
|
@ -144,8 +144,9 @@ const TickType_t xBlockTime = ( TickType_t ) 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do exactly the same to create the second set of tasks, only this time
|
/* Do exactly the same to create the second set of tasks, only this time
|
||||||
provide a block time for the semaphore calls. */
|
* provide a block time for the semaphore calls. */
|
||||||
pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
||||||
|
|
||||||
if( pxSecondSemaphoreParameters != NULL )
|
if( pxSecondSemaphoreParameters != NULL )
|
||||||
{
|
{
|
||||||
vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore );
|
vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore );
|
||||||
|
|
@ -171,7 +172,7 @@ unsigned long ulCounter;
|
||||||
short sError = pdFALSE, sCheckVariableToUse;
|
short sError = pdFALSE, sCheckVariableToUse;
|
||||||
|
|
||||||
/* See which check variable to use. sNextCheckVariable is not semaphore
|
/* See which check variable to use. sNextCheckVariable is not semaphore
|
||||||
protected! */
|
* protected! */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
sCheckVariableToUse = sNextCheckVariable;
|
sCheckVariableToUse = sNextCheckVariable;
|
||||||
sNextCheckVariable++;
|
sNextCheckVariable++;
|
||||||
|
|
@ -181,12 +182,12 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
vPrintDisplayMessage( &pcSemaphoreTaskStart );
|
vPrintDisplayMessage( &pcSemaphoreTaskStart );
|
||||||
|
|
||||||
/* A structure is passed in as the parameter. This contains the shared
|
/* A structure is passed in as the parameter. This contains the shared
|
||||||
variable being guarded. */
|
* variable being guarded. */
|
||||||
pxParameters = ( xSemaphoreParameters * ) pvParameters;
|
pxParameters = ( xSemaphoreParameters * ) pvParameters;
|
||||||
pulSharedVariable = pxParameters->pulSharedVariable;
|
pulSharedVariable = pxParameters->pulSharedVariable;
|
||||||
|
|
||||||
/* If we are blocking we use a much higher count to ensure loads of context
|
/* If we are blocking we use a much higher count to ensure loads of context
|
||||||
switches occur during the count. */
|
* switches occur during the count. */
|
||||||
if( pxParameters->xBlockTime > ( TickType_t ) 0 )
|
if( pxParameters->xBlockTime > ( TickType_t ) 0 )
|
||||||
{
|
{
|
||||||
ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
|
ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
|
||||||
|
|
@ -202,8 +203,8 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
|
if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
|
||||||
{
|
{
|
||||||
/* We have the semaphore and so expect any other tasks using the
|
/* We have the semaphore and so expect any other tasks using the
|
||||||
shared variable to have left it in the state we expect to find
|
* shared variable to have left it in the state we expect to find
|
||||||
it. */
|
* it. */
|
||||||
if( *pulSharedVariable != ulExpectedValue )
|
if( *pulSharedVariable != ulExpectedValue )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
||||||
|
|
@ -211,23 +212,25 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the variable, then count it back up to the expected value
|
/* Clear the variable, then count it back up to the expected value
|
||||||
before releasing the semaphore. Would expect a context switch or
|
* before releasing the semaphore. Would expect a context switch or
|
||||||
two during this time. */
|
* two during this time. */
|
||||||
for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
|
for( ulCounter = ( unsigned long ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
|
||||||
{
|
{
|
||||||
*pulSharedVariable = ulCounter;
|
*pulSharedVariable = ulCounter;
|
||||||
|
|
||||||
if( *pulSharedVariable != ulCounter )
|
if( *pulSharedVariable != ulCounter )
|
||||||
{
|
{
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
||||||
}
|
}
|
||||||
|
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the semaphore, and if no errors have occurred increment the check
|
/* Release the semaphore, and if no errors have occurred increment the check
|
||||||
variable. */
|
* variable. */
|
||||||
if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
|
if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
|
||||||
{
|
{
|
||||||
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
vPrintDisplayMessage( &pcPollingSemaphoreTaskError );
|
||||||
|
|
@ -243,10 +246,10 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have a block time then we are running at a priority higher
|
/* If we have a block time then we are running at a priority higher
|
||||||
than the idle priority. This task takes a long time to complete
|
* than the idle priority. This task takes a long time to complete
|
||||||
a cycle (deliberately so to test the guarding) so will be starving
|
* a cycle (deliberately so to test the guarding) so will be starving
|
||||||
out lower priority tasks. Block for some time to allow give lower
|
* out lower priority tasks. Block for some time to allow give lower
|
||||||
priority tasks some processor time. */
|
* priority tasks some processor time. */
|
||||||
vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
|
vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -254,8 +257,8 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
if( pxParameters->xBlockTime == ( TickType_t ) 0 )
|
if( pxParameters->xBlockTime == ( TickType_t ) 0 )
|
||||||
{
|
{
|
||||||
/* We have not got the semaphore yet, so no point using the
|
/* We have not got the semaphore yet, so no point using the
|
||||||
processor. We are not blocking when attempting to obtain the
|
* processor. We are not blocking when attempting to obtain the
|
||||||
semaphore. */
|
* semaphore. */
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -281,5 +284,3 @@ portBASE_TYPE xTask, xReturn = pdTRUE;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
#include "AbortDelay.h"
|
#include "AbortDelay.h"
|
||||||
|
|
||||||
/* This file can only be used if the functionality it tests is included in the
|
/* This file can only be used if the functionality it tests is included in the
|
||||||
build. Remove the whole file if this is not the case. */
|
* build. Remove the whole file if this is not the case. */
|
||||||
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
|
|
||||||
#if ( INCLUDE_xTaskGetHandle != 1 )
|
#if ( INCLUDE_xTaskGetHandle != 1 )
|
||||||
|
|
@ -111,7 +111,8 @@ static void prvPerformSingleTaskTests( void );
|
||||||
* Checks the amount of time a task spent in the Blocked state is within the
|
* Checks the amount of time a task spent in the Blocked state is within the
|
||||||
* expected bounds.
|
* expected bounds.
|
||||||
*/
|
*/
|
||||||
static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime );
|
static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime,
|
||||||
|
TickType_t xExpectedBlockTime );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -120,7 +121,7 @@ static volatile BaseType_t xControllingCycles = 0, xBlockingCycles = 0;
|
||||||
static volatile BaseType_t xErrorOccurred = pdFALSE;
|
static volatile BaseType_t xErrorOccurred = pdFALSE;
|
||||||
|
|
||||||
/* Each task needs to know the other tasks handle so they can send signals to
|
/* Each task needs to know the other tasks handle so they can send signals to
|
||||||
each other. The handle is obtained from the task's name. */
|
* each other. The handle is obtained from the task's name. */
|
||||||
static const char * pcControllingTaskName = "AbtCtrl", * pcBlockingTaskName = "AbtBlk";
|
static const char * pcControllingTaskName = "AbtCtrl", * pcBlockingTaskName = "AbtBlk";
|
||||||
|
|
||||||
/* The maximum amount of time a task will block for. */
|
/* The maximum amount of time a task will block for. */
|
||||||
|
|
@ -128,8 +129,8 @@ const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 100 );
|
||||||
const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );
|
const TickType_t xHalfMaxBlockTime = pdMS_TO_TICKS( 50 );
|
||||||
|
|
||||||
/* The actual block time is dependent on the priority of other tasks in the
|
/* The actual block time is dependent on the priority of other tasks in the
|
||||||
system so the actual block time might be greater than that expected, but it
|
* system so the actual block time might be greater than that expected, but it
|
||||||
should be within an acceptable upper bound. */
|
* should be within an acceptable upper bound. */
|
||||||
const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );
|
const TickType_t xAllowableMargin = pdMS_TO_TICKS( 7 );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -162,18 +163,19 @@ const TickType_t xStartMargin = 2UL;
|
||||||
xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
|
xTaskNotify( xBlockingTask, ulTestToPerform, eSetValueWithOverwrite );
|
||||||
|
|
||||||
/* The secondary task has a higher priority, so will now be in the
|
/* The secondary task has a higher priority, so will now be in the
|
||||||
Blocked state to wait for a maximum of xMaxBlockTime. It expects that
|
* Blocked state to wait for a maximum of xMaxBlockTime. It expects that
|
||||||
period to complete with a timeout. It will then block for
|
* period to complete with a timeout. It will then block for
|
||||||
xMaxBlockTimeAgain, but this time it expects to the block time to abort
|
* xMaxBlockTimeAgain, but this time it expects to the block time to abort
|
||||||
half way through. Block until it is time to send the abort to the
|
* half way through. Block until it is time to send the abort to the
|
||||||
secondary task. xStartMargin is used because this task takes timing
|
* secondary task. xStartMargin is used because this task takes timing
|
||||||
from the beginning of the test, whereas the blocking task takes timing
|
* from the beginning of the test, whereas the blocking task takes timing
|
||||||
from the entry into the Blocked state - and as the tasks run at
|
* from the entry into the Blocked state - and as the tasks run at
|
||||||
different priorities, there may be some discrepancy. Also, temporarily
|
* different priorities, there may be some discrepancy. Also, temporarily
|
||||||
raise the priority of the controlling task to that of the blocking
|
* raise the priority of the controlling task to that of the blocking
|
||||||
task to minimise discrepancies. */
|
* task to minimise discrepancies. */
|
||||||
vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );
|
vTaskPrioritySet( NULL, abtBLOCKING_PRIORITY );
|
||||||
vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
|
vTaskDelay( xMaxBlockTime + xHalfMaxBlockTime + xStartMargin );
|
||||||
|
|
||||||
if( xTaskAbortDelay( xBlockingTask ) != pdPASS )
|
if( xTaskAbortDelay( xBlockingTask ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -183,12 +185,12 @@ const TickType_t xStartMargin = 2UL;
|
||||||
vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
|
vTaskPrioritySet( NULL, abtCONTROLLING_PRIORITY );
|
||||||
|
|
||||||
/* Now wait to be notified that the secondary task has completed its
|
/* Now wait to be notified that the secondary task has completed its
|
||||||
test. */
|
* test. */
|
||||||
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
|
|
||||||
/* Did the entire test run for the expected time, which is two full
|
/* Did the entire test run for the expected time, which is two full
|
||||||
block times plus the half block time caused by calling
|
* block times plus the half block time caused by calling
|
||||||
xTaskAbortDelay()? */
|
* xTaskAbortDelay()? */
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, ( xMaxBlockTime + xMaxBlockTime + xHalfMaxBlockTime ) );
|
||||||
|
|
||||||
/* Move onto the next test. */
|
/* Move onto the next test. */
|
||||||
|
|
@ -215,7 +217,7 @@ const uint32_t ulMax = 0xffffffffUL;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Start by performing a few tests to cover code not exercised in the loops
|
/* Start by performing a few tests to cover code not exercised in the loops
|
||||||
below. */
|
* below. */
|
||||||
prvPerformSingleTaskTests();
|
prvPerformSingleTaskTests();
|
||||||
|
|
||||||
xControllingTask = xTaskGetHandle( pcControllingTaskName );
|
xControllingTask = xTaskGetHandle( pcControllingTaskName );
|
||||||
|
|
@ -280,10 +282,11 @@ TaskHandle_t xThisTask;
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
|
|
||||||
/* Try unblocking this task using both the task and ISR versions of the API -
|
/* Try unblocking this task using both the task and ISR versions of the API -
|
||||||
both should return false as this task is not blocked. */
|
* both should return false as this task is not blocked. */
|
||||||
xThisTask = xTaskGetCurrentTaskHandle();
|
xThisTask = xTaskGetCurrentTaskHandle();
|
||||||
|
|
||||||
xReturned = xTaskAbortDelay( xThisTask );
|
xReturned = xTaskAbortDelay( xThisTask );
|
||||||
|
|
||||||
if( xReturned != pdFALSE )
|
if( xReturned != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -300,23 +303,24 @@ BaseType_t xReturned;
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* Take a copy of the time as it is updated in the call to
|
/* Take a copy of the time as it is updated in the call to
|
||||||
xTaskDelayUntil() but its original value is needed to determine the actual
|
* xTaskDelayUntil() but its original value is needed to determine the actual
|
||||||
time spend in the Blocked state. */
|
* time spend in the Blocked state. */
|
||||||
xLastBlockTime = xTimeAtStart;
|
xLastBlockTime = xTimeAtStart;
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
xReturned = xTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
xReturned = xTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
configASSERT( xReturned == pdTRUE );
|
configASSERT( xReturned == pdTRUE );
|
||||||
|
|
||||||
/* Remove compiler warning about value being set but not used in the case
|
/* Remove compiler warning about value being set but not used in the case
|
||||||
configASSERT() is not defined. */
|
* configASSERT() is not defined. */
|
||||||
( void ) xReturned;
|
( void ) xReturned;
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through. Again take a copy of the time as it is updated in the call to
|
* through. Again take a copy of the time as it is updated in the call to
|
||||||
vTaskDelayUntil() buts its original value is needed to determine the amount
|
* vTaskDelayUntil() buts its original value is needed to determine the amount
|
||||||
of time actually spent in the Blocked state. This uses vTaskDelayUntil()
|
* of time actually spent in the Blocked state. This uses vTaskDelayUntil()
|
||||||
in place of xTaskDelayUntil() for test coverage. */
|
* in place of xTaskDelayUntil() for test coverage. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
xLastBlockTime = xTimeAtStart;
|
xLastBlockTime = xTimeAtStart;
|
||||||
vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
vTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
||||||
|
|
@ -328,8 +332,9 @@ BaseType_t xReturned;
|
||||||
xReturned = xTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
xReturned = xTaskDelayUntil( &xLastBlockTime, xMaxBlockTime );
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
configASSERT( xReturned == pdTRUE );
|
configASSERT( xReturned == pdTRUE );
|
||||||
|
|
||||||
/* Remove compiler warning about value being set but not used in the case
|
/* Remove compiler warning about value being set but not used in the case
|
||||||
configASSERT() is not defined. */
|
* configASSERT() is not defined. */
|
||||||
( void ) xReturned;
|
( void ) xReturned;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -349,7 +354,7 @@ TickType_t xTimeAtStart;
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through. */
|
* through. */
|
||||||
vTaskDelay( xMaxBlockTime );
|
vTaskDelay( xMaxBlockTime );
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
|
|
@ -372,22 +377,26 @@ uint32_t ulReturn;
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
||||||
|
|
||||||
if( ulReturn != 0 )
|
if( ulReturn != 0 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through. */
|
* through. */
|
||||||
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
||||||
|
|
||||||
if( ulReturn != 0 )
|
if( ulReturn != 0 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
|
@ -395,10 +404,12 @@ uint32_t ulReturn;
|
||||||
|
|
||||||
/* This third delay should just time out again. */
|
/* This third delay should just time out again. */
|
||||||
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
ulReturn = ulTaskNotifyTake( pdFALSE, xMaxBlockTime );
|
||||||
|
|
||||||
if( ulReturn != 0 )
|
if( ulReturn != 0 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -414,7 +425,7 @@ EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
|
||||||
static StaticEventGroup_t xEventGroupBuffer;
|
static StaticEventGroup_t xEventGroupBuffer;
|
||||||
|
|
||||||
/* Create the event group. Statically allocated memory is used so the
|
/* Create the event group. Statically allocated memory is used so the
|
||||||
creation cannot fail. */
|
* creation cannot fail. */
|
||||||
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
@ -422,29 +433,33 @@ EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
|
||||||
xEventGroup = xEventGroupCreate();
|
xEventGroup = xEventGroupCreate();
|
||||||
configASSERT( xEventGroup );
|
configASSERT( xEventGroup );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != 0x00 )
|
if( xReturn != 0x00 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through. */
|
* through. */
|
||||||
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != 0x00 )
|
if( xReturn != 0x00 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
|
@ -452,10 +467,12 @@ EventBits_t xBitsToWaitFor = ( EventBits_t ) 0x01, xReturn;
|
||||||
|
|
||||||
/* This third delay should just time out again. */
|
/* This third delay should just time out again. */
|
||||||
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
xReturn = xEventGroupWaitBits( xEventGroup, xBitsToWaitFor, pdTRUE, pdTRUE, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != 0x00 )
|
if( xReturn != 0x00 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Not really necessary in this case, but for completeness. */
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
|
@ -474,7 +491,7 @@ uint8_t uxRxData;
|
||||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
/* Defines the memory that will actually hold the streams within the
|
/* Defines the memory that will actually hold the streams within the
|
||||||
stream buffer. */
|
* stream buffer. */
|
||||||
static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];
|
static uint8_t ucStorageBuffer[ sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) + 1 ];
|
||||||
|
|
||||||
/* The variable used to hold the stream buffer structure. */
|
/* The variable used to hold the stream buffer structure. */
|
||||||
|
|
@ -486,34 +503,38 @@ uint8_t uxRxData;
|
||||||
ucStorageBuffer,
|
ucStorageBuffer,
|
||||||
&xStreamBufferStruct );
|
&xStreamBufferStruct );
|
||||||
}
|
}
|
||||||
#else
|
#else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
||||||
{
|
{
|
||||||
xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );
|
xStreamBuffer = xStreamBufferCreate( sizeof( uint8_t ), xTriggerLevelBytes );
|
||||||
configASSERT( xStreamBuffer );
|
configASSERT( xStreamBuffer );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
|
xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != 0x00 )
|
if( xReturn != 0x00 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through xMaxBlockTime. */
|
* through xMaxBlockTime. */
|
||||||
xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
|
xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != 0x00 )
|
if( xReturn != 0x00 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
|
@ -521,10 +542,12 @@ uint8_t uxRxData;
|
||||||
|
|
||||||
/* This third delay should just time out again. */
|
/* This third delay should just time out again. */
|
||||||
xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
|
xReturn = xStreamBufferReceive( xStreamBuffer, &uxRxData, sizeof( uxRxData ), xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != 0x00 )
|
if( xReturn != 0x00 )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Not really necessary in this case, but for completeness. */
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
|
@ -546,7 +569,7 @@ uint8_t ucItemToQueue;
|
||||||
static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
|
static uint8_t ucQueueStorage[ sizeof( uint8_t ) ];
|
||||||
|
|
||||||
/* Create the queue. Statically allocated memory is used so the
|
/* Create the queue. Statically allocated memory is used so the
|
||||||
creation cannot fail. */
|
* creation cannot fail. */
|
||||||
xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
|
xQueue = xQueueCreateStatic( xQueueLength, sizeof( uint8_t ), ucQueueStorage, &xQueueBuffer );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
@ -554,11 +577,12 @@ uint8_t ucItemToQueue;
|
||||||
xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
|
xQueue = xQueueCreate( xQueueLength, sizeof( uint8_t ) );
|
||||||
configASSERT( xQueue );
|
configASSERT( xQueue );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
||||||
|
|
||||||
/* This function tests aborting when in the blocked state waiting to send,
|
/* This function tests aborting when in the blocked state waiting to send,
|
||||||
so the queue must be full. There is only one space in the queue. */
|
* so the queue must be full. There is only one space in the queue. */
|
||||||
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdPASS )
|
if( xReturn != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -569,22 +593,26 @@ uint8_t ucItemToQueue;
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through. */
|
* through. */
|
||||||
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
|
@ -592,10 +620,12 @@ uint8_t ucItemToQueue;
|
||||||
|
|
||||||
/* This third delay should just time out again. */
|
/* This third delay should just time out again. */
|
||||||
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
xReturn = xQueueSend( xQueue, &ucItemToQueue, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Not really necessary in this case, but for completeness. */
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
|
@ -614,7 +644,7 @@ SemaphoreHandle_t xSemaphore;
|
||||||
static StaticSemaphore_t xSemaphoreBuffer;
|
static StaticSemaphore_t xSemaphoreBuffer;
|
||||||
|
|
||||||
/* Create the semaphore. Statically allocated memory is used so the
|
/* Create the semaphore. Statically allocated memory is used so the
|
||||||
creation cannot fail. */
|
* creation cannot fail. */
|
||||||
xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
|
xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
@ -628,22 +658,26 @@ SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through xMaxBlockTime. */
|
* through xMaxBlockTime. */
|
||||||
xReturn = xSemaphoreTake( xSemaphore, portMAX_DELAY );
|
xReturn = xSemaphoreTake( xSemaphore, portMAX_DELAY );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
|
@ -651,10 +685,12 @@ SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
/* This third delay should just time out again. */
|
/* This third delay should just time out again. */
|
||||||
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
xReturn = xSemaphoreTake( xSemaphore, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Not really necessary in this case, but for completeness. */
|
/* Not really necessary in this case, but for completeness. */
|
||||||
|
|
@ -672,22 +708,26 @@ BaseType_t xReturn;
|
||||||
|
|
||||||
/* This first delay should just time out. */
|
/* This first delay should just time out. */
|
||||||
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
xTimeAtStart = xTaskGetTickCount();
|
xTimeAtStart = xTaskGetTickCount();
|
||||||
|
|
||||||
/* This second delay should be aborted by the primary task half way
|
/* This second delay should be aborted by the primary task half way
|
||||||
through xMaxBlockTime. */
|
* through xMaxBlockTime. */
|
||||||
xReturn = xTaskNotifyWait( 0, 0, NULL, portMAX_DELAY );
|
xReturn = xTaskNotifyWait( 0, 0, NULL, portMAX_DELAY );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xHalfMaxBlockTime );
|
||||||
|
|
||||||
/* Note the time before the delay so the length of the delay is known. */
|
/* Note the time before the delay so the length of the delay is known. */
|
||||||
|
|
@ -695,15 +735,18 @@ BaseType_t xReturn;
|
||||||
|
|
||||||
/* This third delay should just time out again. */
|
/* This third delay should just time out again. */
|
||||||
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
xReturn = xTaskNotifyWait( 0, 0, NULL, xMaxBlockTime );
|
||||||
|
|
||||||
if( xReturn != pdFALSE )
|
if( xReturn != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
prvCheckExpectedTimeIsWithinAnAcceptableMargin( xTimeAtStart, xMaxBlockTime );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime, TickType_t xExpectedBlockTime )
|
static void prvCheckExpectedTimeIsWithinAnAcceptableMargin( TickType_t xStartTime,
|
||||||
|
TickType_t xExpectedBlockTime )
|
||||||
{
|
{
|
||||||
TickType_t xTimeNow, xActualBlockTime;
|
TickType_t xTimeNow, xActualBlockTime;
|
||||||
|
|
||||||
|
|
@ -717,8 +760,8 @@ TickType_t xTimeNow, xActualBlockTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The actual block time can be greater than the expected block time, as it
|
/* The actual block time can be greater than the expected block time, as it
|
||||||
depends on the priority of the other tasks, but it should be within an
|
* depends on the priority of the other tasks, but it should be within an
|
||||||
acceptable margin. */
|
* acceptable margin. */
|
||||||
if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
|
if( xActualBlockTime > ( xExpectedBlockTime + xAllowableMargin ) )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -732,7 +775,7 @@ static BaseType_t xLastControllingCycleCount = 0, xLastBlockingCycleCount = 0;
|
||||||
BaseType_t xReturn = pdPASS;
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
/* Have both tasks performed at least one cycle since this function was
|
/* Have both tasks performed at least one cycle since this function was
|
||||||
last called? */
|
* last called? */
|
||||||
if( xControllingCycles == xLastControllingCycleCount )
|
if( xControllingCycles == xLastControllingCycleCount )
|
||||||
{
|
{
|
||||||
xReturn = pdFAIL;
|
xReturn = pdFAIL;
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,16 @@ typedef struct BLOCKING_QUEUE_PARAMETERS
|
||||||
static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters );
|
static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters );
|
||||||
|
|
||||||
/* Task function that removes the incrementing number from a queue and checks that
|
/* Task function that removes the incrementing number from a queue and checks that
|
||||||
it is the expected number. */
|
* it is the expected number. */
|
||||||
static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters );
|
static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters );
|
||||||
|
|
||||||
/* Variables which are incremented each time an item is removed from a queue, and
|
/* Variables which are incremented each time an item is removed from a queue, and
|
||||||
found to be the expected value.
|
* found to be the expected value.
|
||||||
These are used to check that the tasks are still running. */
|
* These are used to check that the tasks are still running. */
|
||||||
static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
||||||
|
|
||||||
/* Variable which are incremented each time an item is posted on a queue. These
|
/* Variable which are incremented each time an item is posted on a queue. These
|
||||||
are used to check that the tasks are still running. */
|
* are used to check that the tasks are still running. */
|
||||||
static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0, ( uint16_t ) 0, ( uint16_t ) 0 };
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -107,14 +107,14 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
||||||
pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
|
|
||||||
/* Create the queue used by the first two tasks to pass the incrementing number.
|
/* Create the queue used by the first two tasks to pass the incrementing number.
|
||||||
Pass a pointer to the queue in the parameter structure. */
|
* Pass a pointer to the queue in the parameter structure. */
|
||||||
pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) );
|
pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) );
|
||||||
|
|
||||||
/* The consumer is created first so gets a block time as described above. */
|
/* The consumer is created first so gets a block time as described above. */
|
||||||
pxQueueParameters1->xBlockTime = xBlockTime;
|
pxQueueParameters1->xBlockTime = xBlockTime;
|
||||||
|
|
||||||
/* Pass in the variable that this task is going to increment so we can check it
|
/* Pass in the variable that this task is going to increment so we can check it
|
||||||
is still running. */
|
* is still running. */
|
||||||
pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );
|
pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] );
|
||||||
|
|
||||||
/* Create the structure used to pass parameters to the producer task. */
|
/* Create the structure used to pass parameters to the producer task. */
|
||||||
|
|
@ -124,23 +124,23 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
||||||
pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
|
pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
|
||||||
|
|
||||||
/* The producer is not going to block - as soon as it posts the consumer will
|
/* The producer is not going to block - as soon as it posts the consumer will
|
||||||
wake and remove the item so the producer should always have room to post. */
|
* wake and remove the item so the producer should always have room to post. */
|
||||||
pxQueueParameters2->xBlockTime = xDontBlock;
|
pxQueueParameters2->xBlockTime = xDontBlock;
|
||||||
|
|
||||||
/* Pass in the variable that this task is going to increment so we can check
|
/* Pass in the variable that this task is going to increment so we can check
|
||||||
it is still running. */
|
* it is still running. */
|
||||||
pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );
|
pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] );
|
||||||
|
|
||||||
|
|
||||||
/* Note the producer has a lower priority than the consumer when the tasks are
|
/* Note the producer has a lower priority than the consumer when the tasks are
|
||||||
spawned. */
|
* spawned. */
|
||||||
xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );
|
xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL );
|
||||||
xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the second two tasks as described at the top of the file. This uses
|
/* Create the second two tasks as described at the top of the file. This uses
|
||||||
the same mechanism but reverses the task priorities. */
|
* the same mechanism but reverses the task priorities. */
|
||||||
|
|
||||||
pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) );
|
pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( UBaseType_t ) sizeof( uint16_t ) );
|
||||||
|
|
@ -158,7 +158,7 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
||||||
|
|
||||||
|
|
||||||
/* Create the last two tasks as described above. The mechanism is again just
|
/* Create the last two tasks as described above. The mechanism is again just
|
||||||
the same. This time both parameter structures are given a block time. */
|
* the same. This time both parameter structures are given a block time. */
|
||||||
pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) );
|
||||||
pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) );
|
pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( UBaseType_t ) sizeof( uint16_t ) );
|
||||||
pxQueueParameters5->xBlockTime = xBlockTime;
|
pxQueueParameters5->xBlockTime = xBlockTime;
|
||||||
|
|
@ -191,14 +191,14 @@ short sErrorEverOccurred = pdFALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We have successfully posted a message, so increment the variable
|
/* We have successfully posted a message, so increment the variable
|
||||||
used to check we are still running. */
|
* used to check we are still running. */
|
||||||
if( sErrorEverOccurred == pdFALSE )
|
if( sErrorEverOccurred == pdFALSE )
|
||||||
{
|
{
|
||||||
( *pxQueueParameters->psCheckVariable )++;
|
( *pxQueueParameters->psCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the variable we are going to post next time round. The
|
/* Increment the variable we are going to post next time round. The
|
||||||
consumer will expect the numbers to follow in numerical order. */
|
* consumer will expect the numbers to follow in numerical order. */
|
||||||
++usValue;
|
++usValue;
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
#if configUSE_PREEMPTION == 0
|
||||||
|
|
@ -231,14 +231,14 @@ short sErrorEverOccurred = pdFALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We have successfully received a message, so increment the
|
/* We have successfully received a message, so increment the
|
||||||
variable used to check we are still running. */
|
* variable used to check we are still running. */
|
||||||
if( sErrorEverOccurred == pdFALSE )
|
if( sErrorEverOccurred == pdFALSE )
|
||||||
{
|
{
|
||||||
( *pxQueueParameters->psCheckVariable )++;
|
( *pxQueueParameters->psCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the value we expect to remove from the queue next time
|
/* Increment the value we expect to remove from the queue next time
|
||||||
round. */
|
* round. */
|
||||||
++usExpectedValue;
|
++usExpectedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,11 +263,11 @@ static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( uint16_t ) 0
|
||||||
BaseType_t xReturn = pdPASS, xTasks;
|
BaseType_t xReturn = pdPASS, xTasks;
|
||||||
|
|
||||||
/* Not too worried about mutual exclusion on these variables as they are 16
|
/* Not too worried about mutual exclusion on these variables as they are 16
|
||||||
bits and we are only reading them. We also only care to see if they have
|
* bits and we are only reading them. We also only care to see if they have
|
||||||
changed or not.
|
* changed or not.
|
||||||
|
*
|
||||||
Loop through each check variable to and return pdFALSE if any are found not
|
* Loop through each check variable to and return pdFALSE if any are found not
|
||||||
to have changed since the last call. */
|
* to have changed since the last call. */
|
||||||
|
|
||||||
for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )
|
for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ )
|
||||||
{
|
{
|
||||||
|
|
@ -275,16 +275,16 @@ BaseType_t xReturn = pdPASS, xTasks;
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
|
|
||||||
|
|
||||||
|
sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
|
||||||
|
|
||||||
if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] )
|
if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] )
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
|
sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
|
||||||
}
|
}
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
#define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )
|
#define ebALL_BITS ( ebBIT_0 | ebBIT_1 | ebBIT_2 | ebBIT_3 | ebBIT_4 | ebBIT_5 | ebBIT_6 | ebBIT_7 )
|
||||||
|
|
||||||
/* Associate a bit to each task. These bits are used to identify all the tasks
|
/* Associate a bit to each task. These bits are used to identify all the tasks
|
||||||
that synchronise with the xEventGroupSync() function. */
|
* that synchronise with the xEventGroupSync() function. */
|
||||||
#define ebSET_BIT_TASK_SYNC_BIT ebBIT_0
|
#define ebSET_BIT_TASK_SYNC_BIT ebBIT_0
|
||||||
#define ebWAIT_BIT_TASK_SYNC_BIT ebBIT_1
|
#define ebWAIT_BIT_TASK_SYNC_BIT ebBIT_1
|
||||||
#define ebRENDESVOUS_TASK_1_SYNC_BIT ebBIT_2
|
#define ebRENDESVOUS_TASK_1_SYNC_BIT ebBIT_2
|
||||||
|
|
@ -83,7 +83,7 @@ that synchronise with the xEventGroupSync() function. */
|
||||||
#define ebSHORT_DELAY pdMS_TO_TICKS( ( TickType_t ) 5 )
|
#define ebSHORT_DELAY pdMS_TO_TICKS( ( TickType_t ) 5 )
|
||||||
|
|
||||||
/* Used in the selective bits test which checks no, one or both tasks blocked on
|
/* Used in the selective bits test which checks no, one or both tasks blocked on
|
||||||
event bits in a group are unblocked as appropriate as different bits get set. */
|
* event bits in a group are unblocked as appropriate as different bits get set. */
|
||||||
#define ebSELECTIVE_BITS_1 0x03
|
#define ebSELECTIVE_BITS_1 0x03
|
||||||
#define ebSELECTIVE_BITS_2 0x05
|
#define ebSELECTIVE_BITS_2 0x05
|
||||||
|
|
||||||
|
|
@ -130,13 +130,15 @@ static void prvTestSlaveTask( void *pvParameters );
|
||||||
* 'test slave' task to test the behaviour when the slave blocks on various
|
* 'test slave' task to test the behaviour when the slave blocks on various
|
||||||
* event bit combinations.
|
* event bit combinations.
|
||||||
*/
|
*/
|
||||||
static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );
|
static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError,
|
||||||
|
TaskHandle_t xTestSlaveTaskHandle );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The part of the test that uses all the tasks to test the task synchronisation
|
* The part of the test that uses all the tasks to test the task synchronisation
|
||||||
* behaviour.
|
* behaviour.
|
||||||
*/
|
*/
|
||||||
static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle );
|
static BaseType_t prvPerformTaskSyncTests( BaseType_t xError,
|
||||||
|
TaskHandle_t xTestSlaveTaskHandle );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Two instances of prvSyncTask() are created. They start by calling
|
* Two instances of prvSyncTask() are created. They start by calling
|
||||||
|
|
@ -157,7 +159,7 @@ static void prvSelectiveBitsTestSlaveFunction( void );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Variables that are incremented by the tasks on each cycle provided no errors
|
/* Variables that are incremented by the tasks on each cycle provided no errors
|
||||||
have been found. Used to detect an error or stall in the test cycling. */
|
* have been found. Used to detect an error or stall in the test cycling. */
|
||||||
static volatile uint32_t ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0;
|
static volatile uint32_t ulTestMasterCycles = 0, ulTestSlaveCycles = 0, ulISRCycles = 0;
|
||||||
|
|
||||||
/* The event group used by all the task based tests. */
|
/* The event group used by all the task based tests. */
|
||||||
|
|
@ -195,7 +197,7 @@ TaskHandle_t xTestSlaveTaskHandle;
|
||||||
configASSERT( xSyncTask2 );
|
configASSERT( xSyncTask2 );
|
||||||
|
|
||||||
/* Create the event group used by the ISR tests. The event group used by
|
/* Create the event group used by the ISR tests. The event group used by
|
||||||
the tasks is created by the tasks themselves. */
|
* the tasks is created by the tasks themselves. */
|
||||||
xISREventGroup = xEventGroupCreate();
|
xISREventGroup = xEventGroupCreate();
|
||||||
configASSERT( xISREventGroup );
|
configASSERT( xISREventGroup );
|
||||||
}
|
}
|
||||||
|
|
@ -216,8 +218,8 @@ TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters;
|
||||||
configASSERT( xEventGroup );
|
configASSERT( xEventGroup );
|
||||||
|
|
||||||
/* Perform the tests that block two tasks on different combinations of bits,
|
/* Perform the tests that block two tasks on different combinations of bits,
|
||||||
then set each bit in turn and check the correct tasks unblock at the correct
|
* then set each bit in turn and check the correct tasks unblock at the correct
|
||||||
times. */
|
* times. */
|
||||||
xError = prvSelectiveBitsTestMasterFunction();
|
xError = prvSelectiveBitsTestMasterFunction();
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
|
|
@ -227,7 +229,7 @@ TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters;
|
||||||
configASSERT( xEventGroup );
|
configASSERT( xEventGroup );
|
||||||
|
|
||||||
/* Perform the tests that check the behaviour when a single task is
|
/* Perform the tests that check the behaviour when a single task is
|
||||||
blocked on various combinations of event bits. */
|
* blocked on various combinations of event bits. */
|
||||||
xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle );
|
xError = prvBitCombinationTestMasterFunction( xError, xTestSlaveTaskHandle );
|
||||||
|
|
||||||
/* Perform the task synchronisation tests. */
|
/* Perform the task synchronisation tests. */
|
||||||
|
|
@ -237,7 +239,7 @@ TaskHandle_t xTestSlaveTaskHandle = ( TaskHandle_t ) pvParameters;
|
||||||
vEventGroupDelete( xEventGroup );
|
vEventGroupDelete( xEventGroup );
|
||||||
|
|
||||||
/* Now all the other tasks should have completed and suspended
|
/* Now all the other tasks should have completed and suspended
|
||||||
themselves ready for the next go around the loop. */
|
* themselves ready for the next go around the loop. */
|
||||||
if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
|
if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -269,37 +271,37 @@ static void prvSyncTask( void *pvParameters )
|
||||||
EventBits_t uxSynchronisationBit, uxReturned;
|
EventBits_t uxSynchronisationBit, uxReturned;
|
||||||
|
|
||||||
/* A few tests that check the behaviour when two tasks are blocked on
|
/* A few tests that check the behaviour when two tasks are blocked on
|
||||||
various different bits within an event group are performed before this task
|
* various different bits within an event group are performed before this task
|
||||||
enters its infinite loop to carry out its main demo function. */
|
* enters its infinite loop to carry out its main demo function. */
|
||||||
prvSelectiveBitsTestSlaveFunction();
|
prvSelectiveBitsTestSlaveFunction();
|
||||||
|
|
||||||
/* The bit to use to indicate this task is at the synchronisation point is
|
/* The bit to use to indicate this task is at the synchronisation point is
|
||||||
passed in as the task parameter. */
|
* passed in as the task parameter. */
|
||||||
uxSynchronisationBit = ( EventBits_t ) pvParameters;
|
uxSynchronisationBit = ( EventBits_t ) pvParameters;
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Now this task takes part in a task synchronisation - sometimes known
|
/* Now this task takes part in a task synchronisation - sometimes known
|
||||||
as a 'rendezvous'. Its execution pattern is controlled by the 'test
|
* as a 'rendezvous'. Its execution pattern is controlled by the 'test
|
||||||
master' task, which is responsible for taking this task out of the
|
* master' task, which is responsible for taking this task out of the
|
||||||
Suspended state when it is time to test the synchronisation behaviour.
|
* Suspended state when it is time to test the synchronisation behaviour.
|
||||||
See: http://www.freertos.org/xEventGroupSync.html. */
|
* See: http://www.freertos.org/xEventGroupSync.html. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* Set the bit that indicates this task is at the synchronisation
|
/* Set the bit that indicates this task is at the synchronisation
|
||||||
point. The first time this is done the 'test master' task has a lower
|
* point. The first time this is done the 'test master' task has a lower
|
||||||
priority than this task so this task will get to the sync point before
|
* priority than this task so this task will get to the sync point before
|
||||||
the set bits task - test this by calling xEventGroupSync() with a zero
|
* the set bits task - test this by calling xEventGroupSync() with a zero
|
||||||
block time before calling again with a max delay - the first call should
|
* block time before calling again with a max delay - the first call should
|
||||||
return before the rendezvous completes, the second only after the
|
* return before the rendezvous completes, the second only after the
|
||||||
rendezvous is complete. */
|
* rendezvous is complete. */
|
||||||
uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
|
uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
|
||||||
uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */
|
uxSynchronisationBit, /* The bit to set in the event group to indicate this task is at the sync point. */
|
||||||
ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks taking part in the sync. */
|
ebALL_SYNC_BITS, /* The bits to wait for - these bits are set by the other tasks taking part in the sync. */
|
||||||
ebDONT_BLOCK ); /* The maximum time to wait for the sync condition to be met before giving up. */
|
ebDONT_BLOCK ); /* The maximum time to wait for the sync condition to be met before giving up. */
|
||||||
|
|
||||||
/* No block time was specified, so as per the comments above, the
|
/* No block time was specified, so as per the comments above, the
|
||||||
rendezvous is not expected to have completed yet. */
|
* rendezvous is not expected to have completed yet. */
|
||||||
configASSERT( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS );
|
configASSERT( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS );
|
||||||
|
|
||||||
uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
|
uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */
|
||||||
|
|
@ -308,8 +310,8 @@ EventBits_t uxSynchronisationBit, uxReturned;
|
||||||
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */
|
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */
|
||||||
|
|
||||||
/* A max delay was used, so this task should only exit the above
|
/* A max delay was used, so this task should only exit the above
|
||||||
function call when the sync condition is met. Check this is the
|
* function call when the sync condition is met. Check this is the
|
||||||
case. */
|
* case. */
|
||||||
configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
|
configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
|
||||||
|
|
||||||
/* Remove compiler warning if configASSERT() is not defined. */
|
/* Remove compiler warning if configASSERT() is not defined. */
|
||||||
|
|
@ -319,18 +321,18 @@ EventBits_t uxSynchronisationBit, uxReturned;
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* Set the bit that indicates this task is at the synchronisation
|
/* Set the bit that indicates this task is at the synchronisation
|
||||||
point again. This time the 'test master' task has a higher priority
|
* point again. This time the 'test master' task has a higher priority
|
||||||
than this task so will get to the sync point before this task. */
|
* than this task so will get to the sync point before this task. */
|
||||||
uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );
|
uxReturned = xEventGroupSync( xEventGroup, uxSynchronisationBit, ebALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
|
||||||
/* Again a max delay was used, so this task should only exit the above
|
/* Again a max delay was used, so this task should only exit the above
|
||||||
function call when the sync condition is met. Check this is the
|
* function call when the sync condition is met. Check this is the
|
||||||
case. */
|
* case. */
|
||||||
configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
|
configASSERT( ( uxReturned & ebALL_SYNC_BITS ) == ebALL_SYNC_BITS );
|
||||||
|
|
||||||
/* Block on the event group again. This time the event group is going
|
/* Block on the event group again. This time the event group is going
|
||||||
to be deleted while this task is blocked on it so it is expected that 0
|
* to be deleted while this task is blocked on it so it is expected that 0
|
||||||
be returned. */
|
* be returned. */
|
||||||
uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
|
uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
|
||||||
configASSERT( uxReturned == 0 );
|
configASSERT( uxReturned == 0 );
|
||||||
}
|
}
|
||||||
|
|
@ -352,14 +354,14 @@ BaseType_t xError = pdFALSE;
|
||||||
* prvBitCombinationTestMasterFunction() function which is called by the
|
* prvBitCombinationTestMasterFunction() function which is called by the
|
||||||
* test master task.
|
* test master task.
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
*
|
||||||
This task is controller by the 'test master' task (which is
|
* This task is controller by the 'test master' task (which is
|
||||||
implemented by prvTestMasterTask()). Suspend until resumed by the
|
* implemented by prvTestMasterTask()). Suspend until resumed by the
|
||||||
'test master' task. */
|
* 'test master' task. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get
|
/* Wait indefinitely for one of the bits in ebCOMBINED_BITS to get
|
||||||
set. Clear the bit on exit. */
|
* set. Clear the bit on exit. */
|
||||||
uxReturned = xEventGroupWaitBits( xEventGroup, /* The event group that contains the event bits being queried. */
|
uxReturned = xEventGroupWaitBits( xEventGroup, /* The event group that contains the event bits being queried. */
|
||||||
ebBIT_1, /* The bit to wait for. */
|
ebBIT_1, /* The bit to wait for. */
|
||||||
pdTRUE, /* Clear the bit on exit. */
|
pdTRUE, /* Clear the bit on exit. */
|
||||||
|
|
@ -367,19 +369,19 @@ BaseType_t xError = pdFALSE;
|
||||||
portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */
|
portMAX_DELAY ); /* Block indefinitely to wait for the condition to be met. */
|
||||||
|
|
||||||
/* The 'test master' task set all the bits defined by ebCOMBINED_BITS,
|
/* The 'test master' task set all the bits defined by ebCOMBINED_BITS,
|
||||||
only one of which was being waited for by this task. The return value
|
* only one of which was being waited for by this task. The return value
|
||||||
shows the state of the event bits when the task was unblocked, however
|
* shows the state of the event bits when the task was unblocked, however
|
||||||
because the task was waiting for ebBIT_1 and 'clear on exit' was set to
|
* because the task was waiting for ebBIT_1 and 'clear on exit' was set to
|
||||||
the current state of the event bits will have ebBIT_1 clear. */
|
* the current state of the event bits will have ebBIT_1 clear. */
|
||||||
if( uxReturned != ebCOMBINED_BITS )
|
if( uxReturned != ebCOMBINED_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now call xEventGroupWaitBits() again, this time waiting for all the
|
/* Now call xEventGroupWaitBits() again, this time waiting for all the
|
||||||
bits in ebCOMBINED_BITS to be set. This call should block until the
|
* bits in ebCOMBINED_BITS to be set. This call should block until the
|
||||||
'test master' task sets ebBIT_1 - which was the bit cleared in the call
|
* 'test master' task sets ebBIT_1 - which was the bit cleared in the call
|
||||||
to xEventGroupWaitBits() above. */
|
* to xEventGroupWaitBits() above. */
|
||||||
uxReturned = xEventGroupWaitBits( xEventGroup,
|
uxReturned = xEventGroupWaitBits( xEventGroup,
|
||||||
ebCOMBINED_BITS, /* The bits being waited on. */
|
ebCOMBINED_BITS, /* The bits being waited on. */
|
||||||
pdFALSE, /* Don't clear the bits on exit. */
|
pdFALSE, /* Don't clear the bits on exit. */
|
||||||
|
|
@ -396,8 +398,8 @@ BaseType_t xError = pdFALSE;
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* Now call xEventGroupWaitBits() again, again waiting for all the bits
|
/* Now call xEventGroupWaitBits() again, again waiting for all the bits
|
||||||
in ebCOMBINED_BITS to be set, but this time clearing the bits when the
|
* in ebCOMBINED_BITS to be set, but this time clearing the bits when the
|
||||||
task is unblocked. */
|
* task is unblocked. */
|
||||||
uxReturned = xEventGroupWaitBits( xEventGroup,
|
uxReturned = xEventGroupWaitBits( xEventGroup,
|
||||||
ebCOMBINED_BITS, /* The bits being waited on. */
|
ebCOMBINED_BITS, /* The bits being waited on. */
|
||||||
pdTRUE, /* Clear the bits on exit. */
|
pdTRUE, /* Clear the bits on exit. */
|
||||||
|
|
@ -405,48 +407,44 @@ BaseType_t xError = pdFALSE;
|
||||||
portMAX_DELAY );
|
portMAX_DELAY );
|
||||||
|
|
||||||
/* The 'test master' task set all the bits in the event group, so that
|
/* The 'test master' task set all the bits in the event group, so that
|
||||||
is the value that should have been returned. The bits defined by
|
* is the value that should have been returned. The bits defined by
|
||||||
ebCOMBINED_BITS will have been clear again in the current value though
|
* ebCOMBINED_BITS will have been clear again in the current value though
|
||||||
as 'clear on exit' was set to pdTRUE. */
|
* as 'clear on exit' was set to pdTRUE. */
|
||||||
if( uxReturned != ebALL_BITS )
|
if( uxReturned != ebALL_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Part 2: This section is the counterpart to the
|
* Part 2: This section is the counterpart to the
|
||||||
* prvPerformTaskSyncTests() function which is called by the
|
* prvPerformTaskSyncTests() function which is called by the
|
||||||
* test master task.
|
* test master task.
|
||||||
***********************************************************************
|
***********************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
Once again wait for the 'test master' task to unsuspend this task
|
* Once again wait for the 'test master' task to unsuspend this task
|
||||||
when it is time for the next test. */
|
* when it is time for the next test. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* Now peform a synchronisation with all the other tasks. At this point
|
/* Now peform a synchronisation with all the other tasks. At this point
|
||||||
the 'test master' task has the lowest priority so will get to the sync
|
* the 'test master' task has the lowest priority so will get to the sync
|
||||||
point after all the other synchronising tasks. */
|
* point after all the other synchronising tasks. */
|
||||||
uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the sync. */
|
uxReturned = xEventGroupSync( xEventGroup, /* The event group used for the sync. */
|
||||||
ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */
|
ebWAIT_BIT_TASK_SYNC_BIT, /* The bit in the event group used to indicate this task is at the sync point. */
|
||||||
ebALL_SYNC_BITS, /* The bits to wait for. These bits are set by the other tasks taking part in the sync. */
|
ebALL_SYNC_BITS, /* The bits to wait for. These bits are set by the other tasks taking part in the sync. */
|
||||||
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */
|
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met before giving up. */
|
||||||
|
|
||||||
/* A sync with a max delay should only exit when all the synchronisation
|
/* A sync with a max delay should only exit when all the synchronisation
|
||||||
bits are set... */
|
* bits are set... */
|
||||||
if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ...but now the synchronisation bits should be clear again. Read back
|
/* ...but now the synchronisation bits should be clear again. Read back
|
||||||
the current value of the bits within the event group to check that is
|
* the current value of the bits within the event group to check that is
|
||||||
the case. Setting the bits to zero will return the bits previous value
|
* the case. Setting the bits to zero will return the bits previous value
|
||||||
then leave all the bits clear. */
|
* then leave all the bits clear. */
|
||||||
if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )
|
if( xEventGroupSetBits( xEventGroup, 0x00 ) != 0 )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -467,12 +465,12 @@ BaseType_t xError = pdFALSE;
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* This time sync when the 'test master' task has the highest priority
|
/* This time sync when the 'test master' task has the highest priority
|
||||||
at the point where it sets its sync bit - so this time the 'test master'
|
* at the point where it sets its sync bit - so this time the 'test master'
|
||||||
task will get to the sync point before this task. */
|
* task will get to the sync point before this task. */
|
||||||
uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
|
uxReturned = xEventGroupSync( xEventGroup, ebWAIT_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
|
||||||
/* A sync with a max delay should only exit when all the synchronisation
|
/* A sync with a max delay should only exit when all the synchronisation
|
||||||
bits are set... */
|
* bits are set... */
|
||||||
if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
if( ( uxReturned & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -485,8 +483,8 @@ BaseType_t xError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Block on the event group again. This time the event group is going
|
/* Block on the event group again. This time the event group is going
|
||||||
to be deleted while this task is blocked on it, so it is expected that 0
|
* to be deleted while this task is blocked on it, so it is expected that 0
|
||||||
will be returned. */
|
* will be returned. */
|
||||||
uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
|
uxReturned = xEventGroupWaitBits( xEventGroup, ebALL_SYNC_BITS, pdFALSE, pdTRUE, portMAX_DELAY );
|
||||||
|
|
||||||
if( uxReturned != 0 )
|
if( uxReturned != 0 )
|
||||||
|
|
@ -505,12 +503,13 @@ BaseType_t xError = pdFALSE;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static BaseType_t prvPerformTaskSyncTests( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )
|
static BaseType_t prvPerformTaskSyncTests( BaseType_t xError,
|
||||||
|
TaskHandle_t xTestSlaveTaskHandle )
|
||||||
{
|
{
|
||||||
EventBits_t uxBits;
|
EventBits_t uxBits;
|
||||||
|
|
||||||
/* The three tasks that take part in the synchronisation (rendezvous) are
|
/* The three tasks that take part in the synchronisation (rendezvous) are
|
||||||
expected to be in the suspended state at the start of the test. */
|
* expected to be in the suspended state at the start of the test. */
|
||||||
if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
|
if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -527,7 +526,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try a synch with no other tasks involved. First set all the bits other
|
/* Try a synch with no other tasks involved. First set all the bits other
|
||||||
than this task's bit. */
|
* than this task's bit. */
|
||||||
xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );
|
xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );
|
||||||
|
|
||||||
/* Then wait on just one bit - the bit that is being set. */
|
/* Then wait on just one bit - the bit that is being set. */
|
||||||
|
|
@ -537,15 +536,15 @@ EventBits_t uxBits;
|
||||||
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */
|
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */
|
||||||
|
|
||||||
/* A sync with a max delay should only exit when all the synchronise
|
/* A sync with a max delay should only exit when all the synchronise
|
||||||
bits are set...check that is the case. In this case there is only one
|
* bits are set...check that is the case. In this case there is only one
|
||||||
sync bit anyway. */
|
* sync bit anyway. */
|
||||||
if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT )
|
if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ...but now the sync bits should be clear again, leaving all the other
|
/* ...but now the sync bits should be clear again, leaving all the other
|
||||||
bits set (as only one bit was being waited for). */
|
* bits set (as only one bit was being waited for). */
|
||||||
if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) )
|
if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -553,13 +552,14 @@ EventBits_t uxBits;
|
||||||
|
|
||||||
/* Clear all the bits to zero again. */
|
/* Clear all the bits to zero again. */
|
||||||
xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );
|
xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) );
|
||||||
|
|
||||||
if( xEventGroupGetBits( xEventGroup ) != 0 )
|
if( xEventGroupGetBits( xEventGroup ) != 0 )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unsuspend the other tasks then check they have executed up to the
|
/* Unsuspend the other tasks then check they have executed up to the
|
||||||
synchronisation point. */
|
* synchronisation point. */
|
||||||
vTaskResume( xTestSlaveTaskHandle );
|
vTaskResume( xTestSlaveTaskHandle );
|
||||||
vTaskResume( xSyncTask1 );
|
vTaskResume( xSyncTask1 );
|
||||||
vTaskResume( xSyncTask2 );
|
vTaskResume( xSyncTask2 );
|
||||||
|
|
@ -586,7 +586,7 @@ EventBits_t uxBits;
|
||||||
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */
|
portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */
|
||||||
|
|
||||||
/* A sync with a max delay should only exit when all the synchronise
|
/* A sync with a max delay should only exit when all the synchronise
|
||||||
bits are set...check that is the case. */
|
* bits are set...check that is the case. */
|
||||||
if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -598,9 +598,8 @@ EventBits_t uxBits;
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The other tasks should now all be suspended again, ready for the next
|
/* The other tasks should now all be suspended again, ready for the next
|
||||||
synchronisation. */
|
* synchronisation. */
|
||||||
if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
|
if( eTaskGetState( xTestSlaveTaskHandle ) != eSuspended )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -616,11 +615,10 @@ EventBits_t uxBits;
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Sync again - but this time set the last necessary bit as the
|
/* Sync again - but this time set the last necessary bit as the
|
||||||
highest priority task, rather than the lowest priority task. Unsuspend
|
* highest priority task, rather than the lowest priority task. Unsuspend
|
||||||
the other tasks then check they have executed up to the synchronisation
|
* the other tasks then check they have executed up to the synchronisation
|
||||||
point. */
|
* point. */
|
||||||
vTaskResume( xTestSlaveTaskHandle );
|
vTaskResume( xTestSlaveTaskHandle );
|
||||||
vTaskResume( xSyncTask1 );
|
vTaskResume( xSyncTask1 );
|
||||||
vTaskResume( xSyncTask2 );
|
vTaskResume( xSyncTask2 );
|
||||||
|
|
@ -647,7 +645,7 @@ EventBits_t uxBits;
|
||||||
uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
|
uxBits = xEventGroupSync( xEventGroup, ebSET_BIT_TASK_SYNC_BIT, ebALL_SYNC_BITS, portMAX_DELAY );
|
||||||
|
|
||||||
/* A sync with a max delay should only exit when all the synchronisation
|
/* A sync with a max delay should only exit when all the synchronisation
|
||||||
bits are set... */
|
* bits are set... */
|
||||||
if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
if( ( uxBits & ebALL_SYNC_BITS ) != ebALL_SYNC_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -659,9 +657,8 @@ EventBits_t uxBits;
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The other tasks should now all be in the ready state again, but not
|
/* The other tasks should now all be in the ready state again, but not
|
||||||
executed yet as this task still has a higher relative priority. */
|
* executed yet as this task still has a higher relative priority. */
|
||||||
if( eTaskGetState( xTestSlaveTaskHandle ) != eReady )
|
if( eTaskGetState( xTestSlaveTaskHandle ) != eReady )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -677,12 +674,11 @@ EventBits_t uxBits;
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Reset the priority of this task back to its original value. */
|
/* Reset the priority of this task back to its original value. */
|
||||||
vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );
|
vTaskPrioritySet( NULL, ebSET_BIT_TASK_PRIORITY );
|
||||||
|
|
||||||
/* Now all the other tasks should have reblocked on the event bits
|
/* Now all the other tasks should have reblocked on the event bits
|
||||||
to test the behaviour when the event bits are deleted. */
|
* to test the behaviour when the event bits are deleted. */
|
||||||
if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
|
if( eTaskGetState( xTestSlaveTaskHandle ) != eBlocked )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -702,12 +698,13 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError, TaskHandle_t xTestSlaveTaskHandle )
|
static BaseType_t prvBitCombinationTestMasterFunction( BaseType_t xError,
|
||||||
|
TaskHandle_t xTestSlaveTaskHandle )
|
||||||
{
|
{
|
||||||
EventBits_t uxBits;
|
EventBits_t uxBits;
|
||||||
|
|
||||||
/* Resume the other task. It will block, pending a single bit from
|
/* Resume the other task. It will block, pending a single bit from
|
||||||
within ebCOMBINED_BITS. */
|
* within ebCOMBINED_BITS. */
|
||||||
vTaskResume( xTestSlaveTaskHandle );
|
vTaskResume( xTestSlaveTaskHandle );
|
||||||
|
|
||||||
/* Ensure the other task is blocked on the task. */
|
/* Ensure the other task is blocked on the task. */
|
||||||
|
|
@ -717,13 +714,13 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only
|
/* Set all the bits in ebCOMBINED_BITS - the 'test slave' task is only
|
||||||
blocked waiting for one of them. */
|
* blocked waiting for one of them. */
|
||||||
xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS );
|
xEventGroupSetBits( xEventGroup, ebCOMBINED_BITS );
|
||||||
|
|
||||||
/* The 'test slave' task should now have executed, clearing ebBIT_1 (the
|
/* The 'test slave' task should now have executed, clearing ebBIT_1 (the
|
||||||
bit it was blocked on), then re-entered the Blocked state to wait for
|
* bit it was blocked on), then re-entered the Blocked state to wait for
|
||||||
all the other bits in ebCOMBINED_BITS to be set again. First check
|
* all the other bits in ebCOMBINED_BITS to be set again. First check
|
||||||
ebBIT_1 is clear. */
|
* ebBIT_1 is clear. */
|
||||||
uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
|
uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
|
||||||
|
|
||||||
if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )
|
if( uxBits != ( ebCOMBINED_BITS & ~ebBIT_1 ) )
|
||||||
|
|
@ -738,7 +735,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set all the bits other than ebBIT_1 - which is the bit that must be
|
/* Set all the bits other than ebBIT_1 - which is the bit that must be
|
||||||
set before the other task unblocks. */
|
* set before the other task unblocks. */
|
||||||
xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 );
|
xEventGroupSetBits( xEventGroup, ebALL_BITS & ~ebBIT_1 );
|
||||||
|
|
||||||
/* Ensure all the expected bits are still set. */
|
/* Ensure all the expected bits are still set. */
|
||||||
|
|
@ -756,7 +753,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now also set ebBIT_1, which should unblock the other task, which will
|
/* Now also set ebBIT_1, which should unblock the other task, which will
|
||||||
then suspend itself. */
|
* then suspend itself. */
|
||||||
xEventGroupSetBits( xEventGroup, ebBIT_1 );
|
xEventGroupSetBits( xEventGroup, ebBIT_1 );
|
||||||
|
|
||||||
/* Ensure the other task is suspended. */
|
/* Ensure the other task is suspended. */
|
||||||
|
|
@ -766,7 +763,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The other task should not have cleared the bits - so all the bits
|
/* The other task should not have cleared the bits - so all the bits
|
||||||
should still be set. */
|
* should still be set. */
|
||||||
if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS )
|
if( xEventGroupSetBits( xEventGroup, 0x00 ) != ebALL_BITS )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -779,7 +776,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resume the other task - which will wait on all the ebCOMBINED_BITS
|
/* Resume the other task - which will wait on all the ebCOMBINED_BITS
|
||||||
again - this time clearing the bits when it is unblocked. */
|
* again - this time clearing the bits when it is unblocked. */
|
||||||
vTaskResume( xTestSlaveTaskHandle );
|
vTaskResume( xTestSlaveTaskHandle );
|
||||||
|
|
||||||
/* Ensure the other task is blocked once again. */
|
/* Ensure the other task is blocked once again. */
|
||||||
|
|
@ -798,7 +795,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The other task should have cleared the bits in ebCOMBINED_BITS.
|
/* The other task should have cleared the bits in ebCOMBINED_BITS.
|
||||||
Clear the remaining bits. */
|
* Clear the remaining bits. */
|
||||||
uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
|
uxBits = xEventGroupWaitBits( xEventGroup, ebALL_BITS, pdFALSE, pdFALSE, ebDONT_BLOCK );
|
||||||
|
|
||||||
if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
|
if( uxBits != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
|
||||||
|
|
@ -807,7 +804,7 @@ EventBits_t uxBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all bits ready for the sync with the other three tasks. The
|
/* Clear all bits ready for the sync with the other three tasks. The
|
||||||
value returned is the value prior to the bits being cleared. */
|
* value returned is the value prior to the bits being cleared. */
|
||||||
if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
|
if( xEventGroupClearBits( xEventGroup, ebALL_BITS ) != ( ebALL_BITS & ~ebCOMBINED_BITS ) )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -828,12 +825,12 @@ static void prvSelectiveBitsTestSlaveFunction( void )
|
||||||
EventBits_t uxPendBits, uxReturned;
|
EventBits_t uxPendBits, uxReturned;
|
||||||
|
|
||||||
/* Used in a test that blocks two tasks on various different bits within an
|
/* Used in a test that blocks two tasks on various different bits within an
|
||||||
event group - then sets each bit in turn and checks that the correct tasks
|
* event group - then sets each bit in turn and checks that the correct tasks
|
||||||
unblock at the correct times.
|
* unblock at the correct times.
|
||||||
|
*
|
||||||
This function is called by two different tasks - each of which will use a
|
* This function is called by two different tasks - each of which will use a
|
||||||
different bit. Check the task handle to see which task the function was
|
* different bit. Check the task handle to see which task the function was
|
||||||
called by. */
|
* called by. */
|
||||||
if( xTaskGetCurrentTaskHandle() == xSyncTask1 )
|
if( xTaskGetCurrentTaskHandle() == xSyncTask1 )
|
||||||
{
|
{
|
||||||
uxPendBits = ebSELECTIVE_BITS_1;
|
uxPendBits = ebSELECTIVE_BITS_1;
|
||||||
|
|
@ -846,8 +843,8 @@ EventBits_t uxPendBits, uxReturned;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Wait until it is time to perform the next cycle of the test. The
|
/* Wait until it is time to perform the next cycle of the test. The
|
||||||
task is unsuspended by the tests implemented in the
|
* task is unsuspended by the tests implemented in the
|
||||||
prvSelectiveBitsTestMasterFunction() function. */
|
* prvSelectiveBitsTestMasterFunction() function. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );
|
uxReturned = xEventGroupWaitBits( xEventGroup, uxPendBits, pdTRUE, pdFALSE, portMAX_DELAY );
|
||||||
|
|
||||||
|
|
@ -865,12 +862,12 @@ BaseType_t xError = pdFALSE;
|
||||||
EventBits_t uxBit;
|
EventBits_t uxBit;
|
||||||
|
|
||||||
/* Used in a test that blocks two tasks on various different bits within an
|
/* Used in a test that blocks two tasks on various different bits within an
|
||||||
event group - then sets each bit in turn and checks that the correct tasks
|
* event group - then sets each bit in turn and checks that the correct tasks
|
||||||
unblock at the correct times. The two other tasks (xSyncTask1 and
|
* unblock at the correct times. The two other tasks (xSyncTask1 and
|
||||||
xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in
|
* xSyncTask2) call prvSelectiveBitsTestSlaveFunction() to perform their parts in
|
||||||
this test.
|
* this test.
|
||||||
|
*
|
||||||
Both other tasks should start in the suspended state. */
|
* Both other tasks should start in the suspended state. */
|
||||||
if( eTaskGetState( xSyncTask1 ) != eSuspended )
|
if( eTaskGetState( xSyncTask1 ) != eSuspended )
|
||||||
{
|
{
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
@ -903,7 +900,7 @@ EventBits_t uxBit;
|
||||||
xEventGroupSetBits( xEventGroup, uxBit );
|
xEventGroupSetBits( xEventGroup, uxBit );
|
||||||
|
|
||||||
/* Is the bit set in the first set of selective bits? If so the first
|
/* Is the bit set in the first set of selective bits? If so the first
|
||||||
sync task should have unblocked and returned to the suspended state. */
|
* sync task should have unblocked and returned to the suspended state. */
|
||||||
if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )
|
if( ( uxBit & ebSELECTIVE_BITS_1 ) == 0 )
|
||||||
{
|
{
|
||||||
/* Task should not have unblocked. */
|
/* Task should not have unblocked. */
|
||||||
|
|
@ -941,13 +938,13 @@ EventBits_t uxBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure both tasks are blocked on the event group again, then delete the
|
/* Ensure both tasks are blocked on the event group again, then delete the
|
||||||
event group so the other tasks leave this portion of the test. */
|
* event group so the other tasks leave this portion of the test. */
|
||||||
vTaskResume( xSyncTask1 );
|
vTaskResume( xSyncTask1 );
|
||||||
vTaskResume( xSyncTask2 );
|
vTaskResume( xSyncTask2 );
|
||||||
|
|
||||||
/* Deleting the event group is the signal that the two other tasks should
|
/* Deleting the event group is the signal that the two other tasks should
|
||||||
leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main
|
* leave the prvSelectiveBitsTestSlaveFunction() function and continue to the main
|
||||||
part of their functionality. */
|
* part of their functionality. */
|
||||||
vEventGroupDelete( xEventGroup );
|
vEventGroupDelete( xEventGroup );
|
||||||
|
|
||||||
return xError;
|
return xError;
|
||||||
|
|
@ -963,7 +960,7 @@ EventBits_t uxReturned;
|
||||||
BaseType_t xMessagePosted;
|
BaseType_t xMessagePosted;
|
||||||
|
|
||||||
/* Called periodically from the tick hook to exercise the "FromISR"
|
/* Called periodically from the tick hook to exercise the "FromISR"
|
||||||
functions. */
|
* functions. */
|
||||||
|
|
||||||
/* Check the even group tasks were actually created. */
|
/* Check the even group tasks were actually created. */
|
||||||
configASSERT( xISREventGroup );
|
configASSERT( xISREventGroup );
|
||||||
|
|
@ -974,6 +971,7 @@ BaseType_t xMessagePosted;
|
||||||
{
|
{
|
||||||
/* All the event bits should start clear. */
|
/* All the event bits should start clear. */
|
||||||
uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );
|
uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );
|
||||||
|
|
||||||
if( uxReturned != 0x00 )
|
if( uxReturned != 0x00 )
|
||||||
{
|
{
|
||||||
xISRTestError = pdTRUE;
|
xISRTestError = pdTRUE;
|
||||||
|
|
@ -981,9 +979,10 @@ BaseType_t xMessagePosted;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Set the bits. This is called from the tick hook so it is not
|
/* Set the bits. This is called from the tick hook so it is not
|
||||||
necessary to use the last parameter to ensure a context switch
|
* necessary to use the last parameter to ensure a context switch
|
||||||
occurs immediately. */
|
* occurs immediately. */
|
||||||
xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL );
|
xMessagePosted = xEventGroupSetBitsFromISR( xISREventGroup, uxBitsToSet, NULL );
|
||||||
|
|
||||||
if( xMessagePosted != pdPASS )
|
if( xMessagePosted != pdPASS )
|
||||||
{
|
{
|
||||||
xISRTestError = pdTRUE;
|
xISRTestError = pdTRUE;
|
||||||
|
|
@ -994,6 +993,7 @@ BaseType_t xMessagePosted;
|
||||||
{
|
{
|
||||||
/* Check the bits were set as expected. */
|
/* Check the bits were set as expected. */
|
||||||
uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );
|
uxReturned = xEventGroupGetBitsFromISR( xISREventGroup );
|
||||||
|
|
||||||
if( uxReturned != uxBitsToSet )
|
if( uxReturned != uxBitsToSet )
|
||||||
{
|
{
|
||||||
xISRTestError = pdTRUE;
|
xISRTestError = pdTRUE;
|
||||||
|
|
@ -1014,7 +1014,7 @@ BaseType_t xMessagePosted;
|
||||||
xCallCount = 0;
|
xCallCount = 0;
|
||||||
|
|
||||||
/* If no errors have been detected then increment the count of test
|
/* If no errors have been detected then increment the count of test
|
||||||
cycles. */
|
* cycles. */
|
||||||
if( xISRTestError == pdFALSE )
|
if( xISRTestError == pdFALSE )
|
||||||
{
|
{
|
||||||
ulISRCycles++;
|
ulISRCycles++;
|
||||||
|
|
@ -1038,22 +1038,22 @@ BaseType_t xStatus = pdPASS;
|
||||||
{
|
{
|
||||||
xStatus = pdFAIL;
|
xStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulPreviousSetBitCycles = ulTestMasterCycles;
|
ulPreviousSetBitCycles = ulTestMasterCycles;
|
||||||
|
|
||||||
if( ulPreviousWaitBitCycles == ulTestSlaveCycles )
|
if( ulPreviousWaitBitCycles == ulTestSlaveCycles )
|
||||||
{
|
{
|
||||||
xStatus = pdFAIL;
|
xStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulPreviousWaitBitCycles = ulTestSlaveCycles;
|
ulPreviousWaitBitCycles = ulTestSlaveCycles;
|
||||||
|
|
||||||
if( ulPreviousISRCycles == ulISRCycles )
|
if( ulPreviousISRCycles == ulISRCycles )
|
||||||
{
|
{
|
||||||
xStatus = pdFAIL;
|
xStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulPreviousISRCycles = ulISRCycles;
|
ulPreviousISRCycles = ulISRCycles;
|
||||||
|
|
||||||
return xStatus;
|
return xStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,10 @@ static void prvHighPriorityMutexTask( void *pvParameters );
|
||||||
* first the same order as the two mutexes were obtained, and second the
|
* first the same order as the two mutexes were obtained, and second the
|
||||||
* opposite order as the two mutexes were obtained.
|
* opposite order as the two mutexes were obtained.
|
||||||
*/
|
*/
|
||||||
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
|
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex,
|
||||||
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
|
SemaphoreHandle_t xLocalMutex );
|
||||||
|
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex,
|
||||||
|
SemaphoreHandle_t xLocalMutex );
|
||||||
|
|
||||||
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
|
|
||||||
|
|
@ -106,19 +108,19 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Tests the behaviour when a low priority task inherits the priority of a
|
/* Tests the behaviour when a low priority task inherits the priority of a
|
||||||
high priority task only for the high priority task to timeout before
|
* high priority task only for the high priority task to timeout before
|
||||||
obtaining the mutex. */
|
* obtaining the mutex. */
|
||||||
static void prvHighPriorityTimeout( SemaphoreHandle_t xMutex );
|
static void prvHighPriorityTimeout( SemaphoreHandle_t xMutex );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
detected in any of the tasks. */
|
* detected in any of the tasks. */
|
||||||
static volatile BaseType_t xErrorDetected = pdFALSE;
|
static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
/* Counters that are incremented on each cycle of a test. This is used to
|
/* Counters that are incremented on each cycle of a test. This is used to
|
||||||
detect a stalled task - a test that is no longer running. */
|
* detect a stalled task - a test that is no longer running. */
|
||||||
static volatile uint32_t ulLoopCounter = 0;
|
static volatile uint32_t ulLoopCounter = 0;
|
||||||
static volatile uint32_t ulLoopCounter2 = 0;
|
static volatile uint32_t ulLoopCounter2 = 0;
|
||||||
|
|
||||||
|
|
@ -126,18 +128,18 @@ static volatile uint32_t ulLoopCounter2 = 0;
|
||||||
static volatile uint32_t ulGuardedVariable = 0;
|
static volatile uint32_t ulGuardedVariable = 0;
|
||||||
|
|
||||||
/* Handles used in the mutex test to suspend and resume the high and medium
|
/* Handles used in the mutex test to suspend and resume the high and medium
|
||||||
priority mutex test tasks. */
|
* priority mutex test tasks. */
|
||||||
static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
|
static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
|
||||||
|
|
||||||
/* If INCLUDE_xTaskAbortDelay is 1 additional tests are performed, requiring an
|
/* If INCLUDE_xTaskAbortDelay is 1 additional tests are performed, requiring an
|
||||||
additional task. */
|
* additional task. */
|
||||||
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
static TaskHandle_t xSecondMediumPriorityMutexTask;
|
static TaskHandle_t xSecondMediumPriorityMutexTask;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Lets the high priority semaphore task know that its wait for the semaphore
|
/* Lets the high priority semaphore task know that its wait for the semaphore
|
||||||
was aborted, in which case not being able to obtain the semaphore is not to be
|
* was aborted, in which case not being able to obtain the semaphore is not to be
|
||||||
considered an error. */
|
* considered an error. */
|
||||||
static volatile BaseType_t xBlockWasAborted = pdFALSE;
|
static volatile BaseType_t xBlockWasAborted = pdFALSE;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -148,22 +150,22 @@ QueueHandle_t xQueue;
|
||||||
SemaphoreHandle_t xMutex;
|
SemaphoreHandle_t xMutex;
|
||||||
|
|
||||||
/* Create the queue that we are going to use for the
|
/* Create the queue that we are going to use for the
|
||||||
prvSendFrontAndBackTest demo. */
|
* prvSendFrontAndBackTest demo. */
|
||||||
xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );
|
xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );
|
||||||
|
|
||||||
if( xQueue != NULL )
|
if( xQueue != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one
|
||||||
is in use. The queue registry is provided as a means for kernel aware
|
* is in use. The queue registry is provided as a means for kernel aware
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
* debuggers to locate queues and has no purpose if a kernel aware debugger
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
* is not being used. The call to vQueueAddToRegistry() will be removed
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
* by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
||||||
defined to be less than 1. */
|
* defined to be less than 1. */
|
||||||
vQueueAddToRegistry( xQueue, "Gen_Queue_Test" );
|
vQueueAddToRegistry( xQueue, "Gen_Queue_Test" );
|
||||||
|
|
||||||
/* Create the demo task and pass it the queue just created. We are
|
/* Create the demo task and pass it the queue just created. We are
|
||||||
passing the queue handle by value so it does not matter that it is
|
* passing the queue handle by value so it does not matter that it is
|
||||||
declared on the stack here. */
|
* declared on the stack here. */
|
||||||
xTaskCreate( prvSendFrontAndBackTest, "GenQ", genqGENERIC_QUEUE_TEST_TASK_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );
|
xTaskCreate( prvSendFrontAndBackTest, "GenQ", genqGENERIC_QUEUE_TEST_TASK_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,22 +175,22 @@ SemaphoreHandle_t xMutex;
|
||||||
if( xMutex != NULL )
|
if( xMutex != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the mutex to the registry, if one is
|
/* vQueueAddToRegistry() adds the mutex to the registry, if one is
|
||||||
in use. The registry is provided as a means for kernel aware
|
* in use. The registry is provided as a means for kernel aware
|
||||||
debuggers to locate mutexes and has no purpose if a kernel aware
|
* debuggers to locate mutexes and has no purpose if a kernel aware
|
||||||
debugger is not being used. The call to vQueueAddToRegistry() will be
|
* debugger is not being used. The call to vQueueAddToRegistry() will be
|
||||||
removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
* removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
||||||
defined or is defined to be less than 1. */
|
* defined or is defined to be less than 1. */
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" );
|
vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Gen_Queue_Mutex" );
|
||||||
|
|
||||||
/* Create the mutex demo tasks and pass it the mutex just created. We
|
/* Create the mutex demo tasks and pass it the mutex just created. We
|
||||||
are passing the mutex handle by value so it does not matter that it is
|
* are passing the mutex handle by value so it does not matter that it is
|
||||||
declared on the stack here. */
|
* declared on the stack here. */
|
||||||
xTaskCreate( prvLowPriorityMutexTask, "MuLow", genqMUTEX_TEST_TASK_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
|
xTaskCreate( prvLowPriorityMutexTask, "MuLow", genqMUTEX_TEST_TASK_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
|
||||||
xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
|
xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
|
||||||
xTaskCreate( prvHighPriorityMutexTask, "MuHigh", genqMUTEX_TEST_TASK_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
|
xTaskCreate( prvHighPriorityMutexTask, "MuHigh", genqMUTEX_TEST_TASK_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
|
||||||
|
|
||||||
/* If INCLUDE_xTaskAbortDelay is set then additional tests are performed,
|
/* If INCLUDE_xTaskAbortDelay is set then additional tests are performed,
|
||||||
requiring two instances of prvHighPriorityMutexTask(). */
|
* requiring two instances of prvHighPriorityMutexTask(). */
|
||||||
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
{
|
{
|
||||||
xTaskCreate( prvHighPriorityMutexTask, "MuHigh2", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_MEDIUM_PRIORITY, &xSecondMediumPriorityMutexTask );
|
xTaskCreate( prvHighPriorityMutexTask, "MuHigh2", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_MEDIUM_PRIORITY, &xSecondMediumPriorityMutexTask );
|
||||||
|
|
@ -217,9 +219,9 @@ QueueHandle_t xQueue;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The queue is empty, so sending an item to the back of the queue
|
/* The queue is empty, so sending an item to the back of the queue
|
||||||
should have the same effect as sending it to the front of the queue.
|
* should have the same effect as sending it to the front of the queue.
|
||||||
|
*
|
||||||
First send to the front and check everything is as expected. */
|
* First send to the front and check everything is as expected. */
|
||||||
ulLoopCounterSnapshot = ulLoopCounter;
|
ulLoopCounterSnapshot = ulLoopCounter;
|
||||||
xQueueSendToFront( xQueue, ( void * ) &ulLoopCounterSnapshot, intsemNO_BLOCK );
|
xQueueSendToFront( xQueue, ( void * ) &ulLoopCounterSnapshot, intsemNO_BLOCK );
|
||||||
|
|
||||||
|
|
@ -234,14 +236,14 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The data we sent to the queue should equal the data we just received
|
/* The data we sent to the queue should equal the data we just received
|
||||||
from the queue. */
|
* from the queue. */
|
||||||
if( ulLoopCounter != ulData )
|
if( ulLoopCounter != ulData )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then do the same, sending the data to the back, checking everything
|
/* Then do the same, sending the data to the back, checking everything
|
||||||
is as expected. */
|
* is as expected. */
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -266,7 +268,7 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The data sent to the queue should equal the data just received from
|
/* The data sent to the queue should equal the data just received from
|
||||||
the queue. */
|
* the queue. */
|
||||||
if( ulLoopCounter != ulData )
|
if( ulLoopCounter != ulData )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -276,8 +278,6 @@ QueueHandle_t xQueue;
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Place 2, 3, 4 into the queue, adding items to the back of the queue. */
|
/* Place 2, 3, 4 into the queue, adding items to the back of the queue. */
|
||||||
for( ulData = 2; ulData < 5; ulData++ )
|
for( ulData = 2; ulData < 5; ulData++ )
|
||||||
{
|
{
|
||||||
|
|
@ -285,18 +285,19 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the order in the queue should be 2, 3, 4, with 2 being the first
|
/* Now the order in the queue should be 2, 3, 4, with 2 being the first
|
||||||
thing to be read out. Now add 1 then 0 to the front of the queue. */
|
* thing to be read out. Now add 1 then 0 to the front of the queue. */
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 3 )
|
if( uxQueueMessagesWaiting( xQueue ) != 3 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulData = 1;
|
ulData = 1;
|
||||||
xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
|
xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
|
||||||
ulData = 0;
|
ulData = 0;
|
||||||
xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
|
xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK );
|
||||||
|
|
||||||
/* Now the queue should be full, and when we read the data out we
|
/* Now the queue should be full, and when we read the data out we
|
||||||
should receive 0, 1, 2, 3, 4. */
|
* should receive 0, 1, 2, 3, 4. */
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 5 )
|
if( uxQueueMessagesWaiting( xQueue ) != 5 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -330,10 +331,10 @@ QueueHandle_t xQueue;
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Now try receiving the data for real. The value should be the
|
/* Now try receiving the data for real. The value should be the
|
||||||
same. Clobber the value first so we know we really received it. */
|
* same. Clobber the value first so we know we really received it. */
|
||||||
ulData2 = ~ulData2;
|
ulData2 = ~ulData2;
|
||||||
|
|
||||||
if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )
|
if( xQueueReceive( xQueue, &ulData2, intsemNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -358,11 +359,14 @@ QueueHandle_t xQueue;
|
||||||
|
|
||||||
/* Our queue is empty once more, add 10, 11 to the back. */
|
/* Our queue is empty once more, add 10, 11 to the back. */
|
||||||
ulData = 10;
|
ulData = 10;
|
||||||
|
|
||||||
if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )
|
if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulData = 11;
|
ulData = 11;
|
||||||
|
|
||||||
if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )
|
if( xQueueSend( xQueue, &ulData, intsemNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -374,7 +378,7 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the
|
/* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the
|
||||||
front. */
|
* front. */
|
||||||
for( ulData = 9; ulData >= 7; ulData-- )
|
for( ulData = 9; ulData >= 7; ulData-- )
|
||||||
{
|
{
|
||||||
if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )
|
if( xQueueSendToFront( xQueue, ( void * ) &ulData, intsemNO_BLOCK ) != pdPASS )
|
||||||
|
|
@ -384,7 +388,7 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check that the queue is full, and that receiving data provides
|
/* Now check that the queue is full, and that receiving data provides
|
||||||
the expected sequence of 7, 8, 9, 10, 11. */
|
* the expected sequence of 7, 8, 9, 10, 11. */
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 5 )
|
if( uxQueueMessagesWaiting( xQueue ) != 5 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -424,7 +428,7 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the loop counter to indicate these tasks are still
|
/* Increment the loop counter to indicate these tasks are still
|
||||||
executing. */
|
* executing. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -437,115 +441,121 @@ QueueHandle_t xQueue;
|
||||||
static UBaseType_t uxLoopCount = 0;
|
static UBaseType_t uxLoopCount = 0;
|
||||||
|
|
||||||
/* The tests in this function are very similar, the slight variations
|
/* The tests in this function are very similar, the slight variations
|
||||||
are for code coverage purposes. */
|
* are for code coverage purposes. */
|
||||||
|
|
||||||
/* Take the mutex. It should be available now. Check before and after
|
/* Take the mutex. It should be available now. Check before and after
|
||||||
taking that the holder is reported correctly. */
|
* taking that the holder is reported correctly. */
|
||||||
if( xSemaphoreGetMutexHolder( xMutex ) != NULL )
|
if( xSemaphoreGetMutexHolder( xMutex ) != NULL )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xSemaphoreGetMutexHolder( xMutex ) != xTaskGetCurrentTaskHandle() )
|
if( xSemaphoreGetMutexHolder( xMutex ) != xTaskGetCurrentTaskHandle() )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This task's priority should be as per that assigned when the task was
|
/* This task's priority should be as per that assigned when the task was
|
||||||
created. */
|
* created. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now unsuspend the high priority task. This will attempt to take the
|
/* Now unsuspend the high priority task. This will attempt to take the
|
||||||
mutex, and block when it finds it cannot obtain it. */
|
* mutex, and block when it finds it cannot obtain it. */
|
||||||
vTaskResume( xHighPriorityMutexTask );
|
vTaskResume( xHighPriorityMutexTask );
|
||||||
|
|
||||||
/* This task should now have inherited the priority of the high priority
|
/* This task should now have inherited the priority of the high priority
|
||||||
task as by now the high priority task will have attempted to obtain the
|
* task as by now the high priority task will have attempted to obtain the
|
||||||
mutex. */
|
* mutex. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unblock a second medium priority task. It too will attempt to take
|
/* Unblock a second medium priority task. It too will attempt to take
|
||||||
the mutex and enter the Blocked state - it won't run yet though as this
|
* the mutex and enter the Blocked state - it won't run yet though as this
|
||||||
task has inherited a priority above it. */
|
* task has inherited a priority above it. */
|
||||||
vTaskResume( xSecondMediumPriorityMutexTask );
|
vTaskResume( xSecondMediumPriorityMutexTask );
|
||||||
|
|
||||||
/* This task should still have the priority of the high priority task as
|
/* This task should still have the priority of the high priority task as
|
||||||
that had already been inherited as is the highest priority of the three
|
* that had already been inherited as is the highest priority of the three
|
||||||
tasks using the mutex. */
|
* tasks using the mutex. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On some loops, block for a short while to provide additional
|
/* On some loops, block for a short while to provide additional
|
||||||
code coverage. Blocking here will allow the medium priority task to
|
* code coverage. Blocking here will allow the medium priority task to
|
||||||
execute and so also block on the mutex so when the high priority task
|
* execute and so also block on the mutex so when the high priority task
|
||||||
causes this task to disinherit the high priority it is inherited down to
|
* causes this task to disinherit the high priority it is inherited down to
|
||||||
the priority of the medium priority task. When there is no delay the
|
* the priority of the medium priority task. When there is no delay the
|
||||||
medium priority task will not run until after the disinheritance, so
|
* medium priority task will not run until after the disinheritance, so
|
||||||
this task will disinherit back to its base priority, then only up to the
|
* this task will disinherit back to its base priority, then only up to the
|
||||||
medium priority after the medium priority has executed. */
|
* medium priority after the medium priority has executed. */
|
||||||
vTaskDelay( uxLoopCount & ( UBaseType_t ) 0x07 );
|
vTaskDelay( uxLoopCount & ( UBaseType_t ) 0x07 );
|
||||||
|
|
||||||
/* Now force the high priority task to unblock. It will fail to obtain
|
/* Now force the high priority task to unblock. It will fail to obtain
|
||||||
the mutex and go back to the suspended state - allowing this task to
|
* the mutex and go back to the suspended state - allowing this task to
|
||||||
execute again. xBlockWasAborted is set to pdTRUE so the higher priority
|
* execute again. xBlockWasAborted is set to pdTRUE so the higher priority
|
||||||
task knows that its failure to obtain the semaphore is not an error. */
|
* task knows that its failure to obtain the semaphore is not an error. */
|
||||||
xBlockWasAborted = pdTRUE;
|
xBlockWasAborted = pdTRUE;
|
||||||
|
|
||||||
if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )
|
if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This task has inherited the priority of xHighPriorityMutexTask so
|
/* This task has inherited the priority of xHighPriorityMutexTask so
|
||||||
could still be running even though xHighPriorityMutexTask is no longer
|
* could still be running even though xHighPriorityMutexTask is no longer
|
||||||
blocked. Delay for a short while to ensure xHighPriorityMutexTask gets
|
* blocked. Delay for a short while to ensure xHighPriorityMutexTask gets
|
||||||
a chance to run - indicated by this task changing priority. It should
|
* a chance to run - indicated by this task changing priority. It should
|
||||||
disinherit the high priority task, but then inherit the priority of the
|
* disinherit the high priority task, but then inherit the priority of the
|
||||||
medium priority task that is waiting for the same mutex. */
|
* medium priority task that is waiting for the same mutex. */
|
||||||
while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
|
while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
|
||||||
{
|
{
|
||||||
/* If this task gets stuck here then the check variables will stop
|
/* If this task gets stuck here then the check variables will stop
|
||||||
incrementing and the check task will detect the error. */
|
* incrementing and the check task will detect the error. */
|
||||||
vTaskDelay( genqSHORT_BLOCK );
|
vTaskDelay( genqSHORT_BLOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now force the medium priority task to unblock. xBlockWasAborted is
|
/* Now force the medium priority task to unblock. xBlockWasAborted is
|
||||||
set to pdTRUE so the medium priority task knows that its failure to
|
* set to pdTRUE so the medium priority task knows that its failure to
|
||||||
obtain the semaphore is not an error. */
|
* obtain the semaphore is not an error. */
|
||||||
xBlockWasAborted = pdTRUE;
|
xBlockWasAborted = pdTRUE;
|
||||||
|
|
||||||
if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )
|
if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This time no other tasks are waiting for the mutex, so this task
|
/* This time no other tasks are waiting for the mutex, so this task
|
||||||
should return to its base priority. This might not happen straight
|
* should return to its base priority. This might not happen straight
|
||||||
away as it is running at the same priority as the task it just
|
* away as it is running at the same priority as the task it just
|
||||||
unblocked. */
|
* unblocked. */
|
||||||
while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
{
|
{
|
||||||
/* If this task gets stuck here then the check variables will stop
|
/* If this task gets stuck here then the check variables will stop
|
||||||
incrementing and the check task will detect the error. */
|
* incrementing and the check task will detect the error. */
|
||||||
vTaskDelay( genqSHORT_BLOCK );
|
vTaskDelay( genqSHORT_BLOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give the semaphore back ready for the next test. Check the mutex
|
/* Give the semaphore back ready for the next test. Check the mutex
|
||||||
holder before and after using the "FromISR" version for code coverage. */
|
* holder before and after using the "FromISR" version for code coverage. */
|
||||||
if( xSemaphoreGetMutexHolderFromISR( xMutex ) != xTaskGetCurrentTaskHandle() )
|
if( xSemaphoreGetMutexHolderFromISR( xMutex ) != xTaskGetCurrentTaskHandle() )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xSemaphoreGive( xMutex );
|
xSemaphoreGive( xMutex );
|
||||||
|
|
||||||
if( xSemaphoreGetMutexHolderFromISR( xMutex ) != NULL )
|
if( xSemaphoreGetMutexHolderFromISR( xMutex ) != NULL )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -553,15 +563,13 @@ QueueHandle_t xQueue;
|
||||||
|
|
||||||
configASSERT( xErrorDetected == pdFALSE );
|
configASSERT( xErrorDetected == pdFALSE );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Now do the same again, but this time unsuspend the tasks in the
|
/* Now do the same again, but this time unsuspend the tasks in the
|
||||||
opposite order. This takes a different path though the code because
|
* opposite order. This takes a different path though the code because
|
||||||
when the high priority task has its block aborted there is already
|
* when the high priority task has its block aborted there is already
|
||||||
another task in the list of tasks waiting for the mutex, and the
|
* another task in the list of tasks waiting for the mutex, and the
|
||||||
low priority task drops down to that priority, rather than dropping
|
* low priority task drops down to that priority, rather than dropping
|
||||||
down to its base priority before inheriting the priority of the medium
|
* down to its base priority before inheriting the priority of the medium
|
||||||
priority task. */
|
* priority task. */
|
||||||
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -573,11 +581,11 @@ QueueHandle_t xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This time unsuspend the medium priority task first. This will
|
/* This time unsuspend the medium priority task first. This will
|
||||||
attempt to take the mutex, and block when it finds it cannot obtain it. */
|
* attempt to take the mutex, and block when it finds it cannot obtain it. */
|
||||||
vTaskResume( xSecondMediumPriorityMutexTask );
|
vTaskResume( xSecondMediumPriorityMutexTask );
|
||||||
|
|
||||||
/* This time this task should now have inherited the priority of the
|
/* This time this task should now have inherited the priority of the
|
||||||
medium task. */
|
* medium task. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -587,17 +595,18 @@ QueueHandle_t xQueue;
|
||||||
vTaskResume( xHighPriorityMutexTask );
|
vTaskResume( xHighPriorityMutexTask );
|
||||||
|
|
||||||
/* The high priority task should already have run, causing this task to
|
/* The high priority task should already have run, causing this task to
|
||||||
inherit a priority for the second time. */
|
* inherit a priority for the second time. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This time, when the high priority task has its delay aborted and it
|
/* This time, when the high priority task has its delay aborted and it
|
||||||
fails to obtain the mutex this task will immediately have its priority
|
* fails to obtain the mutex this task will immediately have its priority
|
||||||
lowered down to that of the highest priority task waiting on the mutex,
|
* lowered down to that of the highest priority task waiting on the mutex,
|
||||||
which is the medium priority task. */
|
* which is the medium priority task. */
|
||||||
xBlockWasAborted = pdTRUE;
|
xBlockWasAborted = pdTRUE;
|
||||||
|
|
||||||
if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )
|
if( xTaskAbortDelay( xHighPriorityMutexTask ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -606,14 +615,15 @@ QueueHandle_t xQueue;
|
||||||
while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
|
while( uxTaskPriorityGet( NULL ) != genqMUTEX_MEDIUM_PRIORITY )
|
||||||
{
|
{
|
||||||
/* If this task gets stuck here then the check variables will stop
|
/* If this task gets stuck here then the check variables will stop
|
||||||
incrementing and the check task will detect the error. */
|
* incrementing and the check task will detect the error. */
|
||||||
vTaskDelay( genqSHORT_BLOCK );
|
vTaskDelay( genqSHORT_BLOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And finally, when the medium priority task also have its delay
|
/* And finally, when the medium priority task also have its delay
|
||||||
aborted there are no other tasks waiting for the mutex so this task
|
* aborted there are no other tasks waiting for the mutex so this task
|
||||||
returns to its base priority. */
|
* returns to its base priority. */
|
||||||
xBlockWasAborted = pdTRUE;
|
xBlockWasAborted = pdTRUE;
|
||||||
|
|
||||||
if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )
|
if( xTaskAbortDelay( xSecondMediumPriorityMutexTask ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -622,7 +632,7 @@ QueueHandle_t xQueue;
|
||||||
while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
while( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
{
|
{
|
||||||
/* If this task gets stuck here then the check variables will stop
|
/* If this task gets stuck here then the check variables will stop
|
||||||
incrementing and the check task will detect the error. */
|
* incrementing and the check task will detect the error. */
|
||||||
vTaskDelay( genqSHORT_BLOCK );
|
vTaskDelay( genqSHORT_BLOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -632,14 +642,15 @@ QueueHandle_t xQueue;
|
||||||
configASSERT( xErrorDetected == pdFALSE );
|
configASSERT( xErrorDetected == pdFALSE );
|
||||||
|
|
||||||
/* uxLoopCount is used to add a variable delay, and in-so-doing provide
|
/* uxLoopCount is used to add a variable delay, and in-so-doing provide
|
||||||
additional code coverage. */
|
* additional code coverage. */
|
||||||
uxLoopCount++;
|
uxLoopCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* INCLUDE_xTaskAbortDelay == 1 */
|
#endif /* INCLUDE_xTaskAbortDelay == 1 */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
|
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex,
|
||||||
|
SemaphoreHandle_t xLocalMutex )
|
||||||
{
|
{
|
||||||
/* Take the mutex. It should be available now. */
|
/* Take the mutex. It should be available now. */
|
||||||
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
||||||
|
|
@ -651,14 +662,14 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
ulGuardedVariable = 0;
|
ulGuardedVariable = 0;
|
||||||
|
|
||||||
/* This task's priority should be as per that assigned when the task was
|
/* This task's priority should be as per that assigned when the task was
|
||||||
created. */
|
* created. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now unsuspend the high priority task. This will attempt to take the
|
/* Now unsuspend the high priority task. This will attempt to take the
|
||||||
mutex, and block when it finds it cannot obtain it. */
|
* mutex, and block when it finds it cannot obtain it. */
|
||||||
vTaskResume( xHighPriorityMutexTask );
|
vTaskResume( xHighPriorityMutexTask );
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
#if configUSE_PREEMPTION == 0
|
||||||
|
|
@ -666,7 +677,7 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Ensure the task is reporting its priority as blocked and not
|
/* Ensure the task is reporting its priority as blocked and not
|
||||||
suspended (as it would have done in versions up to V7.5.3). */
|
* suspended (as it would have done in versions up to V7.5.3). */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
|
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
|
||||||
|
|
@ -674,29 +685,30 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
/* This task should now have inherited the priority of the high priority
|
/* This task should now have inherited the priority of the high priority
|
||||||
task as by now the high priority task will have attempted to obtain the
|
* task as by now the high priority task will have attempted to obtain the
|
||||||
mutex. */
|
* mutex. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to set the priority of this task to the test priority -
|
/* Attempt to set the priority of this task to the test priority -
|
||||||
between the idle priority and the medium/high test priorities, but the
|
* between the idle priority and the medium/high test priorities, but the
|
||||||
actual priority should remain at the high priority. */
|
* actual priority should remain at the high priority. */
|
||||||
vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
|
vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now unsuspend the medium priority task. This should not run as the
|
/* Now unsuspend the medium priority task. This should not run as the
|
||||||
inherited priority of this task is above that of the medium priority
|
* inherited priority of this task is above that of the medium priority
|
||||||
task. */
|
* task. */
|
||||||
vTaskResume( xMediumPriorityMutexTask );
|
vTaskResume( xMediumPriorityMutexTask );
|
||||||
|
|
||||||
/* If the medium priority task did run then it will have incremented the
|
/* If the medium priority task did run then it will have incremented the
|
||||||
guarded variable. */
|
* guarded variable. */
|
||||||
if( ulGuardedVariable != 0 )
|
if( ulGuardedVariable != 0 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -709,11 +721,11 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the semaphore is given back the priority of this task should not
|
/* When the semaphore is given back the priority of this task should not
|
||||||
yet be disinherited because the local mutex is still held. This is a
|
* yet be disinherited because the local mutex is still held. This is a
|
||||||
simplification to allow FreeRTOS to be integrated with middleware that
|
* simplification to allow FreeRTOS to be integrated with middleware that
|
||||||
attempts to hold multiple mutexes without bloating the code with complex
|
* attempts to hold multiple mutexes without bloating the code with complex
|
||||||
algorithms. It is possible that the high priority mutex task will
|
* algorithms. It is possible that the high priority mutex task will
|
||||||
execute as it shares a priority with this task. */
|
* execute as it shares a priority with this task. */
|
||||||
if( xSemaphoreGive( xMutex ) != pdPASS )
|
if( xSemaphoreGive( xMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -724,8 +736,8 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The guarded variable is only incremented by the medium priority task,
|
/* The guarded variable is only incremented by the medium priority task,
|
||||||
which still should not have executed as this task should remain at the
|
* which still should not have executed as this task should remain at the
|
||||||
higher priority, ensure this is the case. */
|
* higher priority, ensure this is the case. */
|
||||||
if( ulGuardedVariable != 0 )
|
if( ulGuardedVariable != 0 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -737,11 +749,11 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now also give back the local mutex, taking the held count back to 0.
|
/* Now also give back the local mutex, taking the held count back to 0.
|
||||||
This time the priority of this task should be disinherited back to the
|
* This time the priority of this task should be disinherited back to the
|
||||||
priority to which it was set while the mutex was held. This means
|
* priority to which it was set while the mutex was held. This means
|
||||||
the medium priority task should execute and increment the guarded
|
* the medium priority task should execute and increment the guarded
|
||||||
variable. When this task next runs both the high and medium priority
|
* variable. When this task next runs both the high and medium priority
|
||||||
tasks will have been suspended again. */
|
* tasks will have been suspended again. */
|
||||||
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
|
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -758,19 +770,20 @@ static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, S
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ... and that the priority of this task has been disinherited to
|
/* ... and that the priority of this task has been disinherited to
|
||||||
genqMUTEX_TEST_PRIORITY. */
|
* genqMUTEX_TEST_PRIORITY. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the priority of this task back to its original value, ready for
|
/* Set the priority of this task back to its original value, ready for
|
||||||
the next loop around this test. */
|
* the next loop around this test. */
|
||||||
vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
|
vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
|
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex,
|
||||||
|
SemaphoreHandle_t xLocalMutex )
|
||||||
{
|
{
|
||||||
/* Take the mutex. It should be available now. */
|
/* Take the mutex. It should be available now. */
|
||||||
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
if( xSemaphoreTake( xMutex, intsemNO_BLOCK ) != pdPASS )
|
||||||
|
|
@ -782,14 +795,14 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
ulGuardedVariable = 0;
|
ulGuardedVariable = 0;
|
||||||
|
|
||||||
/* This task's priority should be as per that assigned when the task was
|
/* This task's priority should be as per that assigned when the task was
|
||||||
created. */
|
* created. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now unsuspend the high priority task. This will attempt to take the
|
/* Now unsuspend the high priority task. This will attempt to take the
|
||||||
mutex, and block when it finds it cannot obtain it. */
|
* mutex, and block when it finds it cannot obtain it. */
|
||||||
vTaskResume( xHighPriorityMutexTask );
|
vTaskResume( xHighPriorityMutexTask );
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
#if configUSE_PREEMPTION == 0
|
||||||
|
|
@ -797,7 +810,7 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Ensure the task is reporting its priority as blocked and not
|
/* Ensure the task is reporting its priority as blocked and not
|
||||||
suspended (as it would have done in versions up to V7.5.3). */
|
* suspended (as it would have done in versions up to V7.5.3). */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
|
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
|
||||||
|
|
@ -805,20 +818,20 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
/* This task should now have inherited the priority of the high priority
|
/* This task should now have inherited the priority of the high priority
|
||||||
task as by now the high priority task will have attempted to obtain the
|
* task as by now the high priority task will have attempted to obtain the
|
||||||
mutex. */
|
* mutex. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now unsuspend the medium priority task. This should not run as the
|
/* Now unsuspend the medium priority task. This should not run as the
|
||||||
inherited priority of this task is above that of the medium priority
|
* inherited priority of this task is above that of the medium priority
|
||||||
task. */
|
* task. */
|
||||||
vTaskResume( xMediumPriorityMutexTask );
|
vTaskResume( xMediumPriorityMutexTask );
|
||||||
|
|
||||||
/* If the medium priority task did run then it will have incremented the
|
/* If the medium priority task did run then it will have incremented the
|
||||||
guarded variable. */
|
* guarded variable. */
|
||||||
if( ulGuardedVariable != 0 )
|
if( ulGuardedVariable != 0 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -831,11 +844,11 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the local semaphore is given back the priority of this task should
|
/* When the local semaphore is given back the priority of this task should
|
||||||
not yet be disinherited because the shared mutex is still held. This is a
|
* not yet be disinherited because the shared mutex is still held. This is a
|
||||||
simplification to allow FreeRTOS to be integrated with middleware that
|
* simplification to allow FreeRTOS to be integrated with middleware that
|
||||||
attempts to hold multiple mutexes without bloating the code with complex
|
* attempts to hold multiple mutexes without bloating the code with complex
|
||||||
algorithms. It is possible that the high priority mutex task will
|
* algorithms. It is possible that the high priority mutex task will
|
||||||
execute as it shares a priority with this task. */
|
* execute as it shares a priority with this task. */
|
||||||
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
|
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -846,8 +859,8 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The guarded variable is only incremented by the medium priority task,
|
/* The guarded variable is only incremented by the medium priority task,
|
||||||
which still should not have executed as this task should remain at the
|
* which still should not have executed as this task should remain at the
|
||||||
higher priority, ensure this is the case. */
|
* higher priority, ensure this is the case. */
|
||||||
if( ulGuardedVariable != 0 )
|
if( ulGuardedVariable != 0 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -859,10 +872,10 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now also give back the shared mutex, taking the held count back to 0.
|
/* Now also give back the shared mutex, taking the held count back to 0.
|
||||||
This time the priority of this task should be disinherited back to the
|
* This time the priority of this task should be disinherited back to the
|
||||||
priority at which it was created. This means the medium priority task
|
* priority at which it was created. This means the medium priority task
|
||||||
should execute and increment the guarded variable. When this task next runs
|
* should execute and increment the guarded variable. When this task next runs
|
||||||
both the high and medium priority tasks will have been suspended again. */
|
* both the high and medium priority tasks will have been suspended again. */
|
||||||
if( xSemaphoreGive( xMutex ) != pdPASS )
|
if( xSemaphoreGive( xMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -879,7 +892,7 @@ static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, Semaph
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ... and that the priority of this task has been disinherited to
|
/* ... and that the priority of this task has been disinherited to
|
||||||
genqMUTEX_LOW_PRIORITY. */
|
* genqMUTEX_LOW_PRIORITY. */
|
||||||
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -907,8 +920,8 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The first tests exercise the priority inheritance when two mutexes
|
/* The first tests exercise the priority inheritance when two mutexes
|
||||||
are taken then returned in a different order to which they were
|
* are taken then returned in a different order to which they were
|
||||||
taken. */
|
* taken. */
|
||||||
prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex );
|
prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex );
|
||||||
|
|
||||||
/* Just to show this task is still running. */
|
/* Just to show this task is still running. */
|
||||||
|
|
@ -919,7 +932,7 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The second tests exercise the priority inheritance when two mutexes
|
/* The second tests exercise the priority inheritance when two mutexes
|
||||||
are taken then returned in the same order in which they were taken. */
|
* are taken then returned in the same order in which they were taken. */
|
||||||
prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex );
|
prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex );
|
||||||
|
|
||||||
/* Just to show this task is still running. */
|
/* Just to show this task is still running. */
|
||||||
|
|
@ -932,8 +945,8 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
|
||||||
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
#if ( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
{
|
{
|
||||||
/* Tests the behaviour when a low priority task inherits the
|
/* Tests the behaviour when a low priority task inherits the
|
||||||
priority of a high priority task only for the high priority task to
|
* priority of a high priority task only for the high priority task to
|
||||||
timeout before obtaining the mutex. */
|
* timeout before obtaining the mutex. */
|
||||||
prvHighPriorityTimeout( xMutex );
|
prvHighPriorityTimeout( xMutex );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -948,12 +961,12 @@ static void prvMediumPriorityMutexTask( void *pvParameters )
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The medium priority task starts by suspending itself. The low
|
/* The medium priority task starts by suspending itself. The low
|
||||||
priority task will unsuspend this task when required. */
|
* priority task will unsuspend this task when required. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* When this task unsuspends all it does is increment the guarded
|
/* When this task unsuspends all it does is increment the guarded
|
||||||
variable, this is so the low priority task knows that it has
|
* variable, this is so the low priority task knows that it has
|
||||||
executed. */
|
* executed. */
|
||||||
ulGuardedVariable++;
|
ulGuardedVariable++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -966,16 +979,16 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The high priority task starts by suspending itself. The low
|
/* The high priority task starts by suspending itself. The low
|
||||||
priority task will unsuspend this task when required. */
|
* priority task will unsuspend this task when required. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* When this task unsuspends all it does is attempt to obtain the
|
/* When this task unsuspends all it does is attempt to obtain the
|
||||||
mutex. It should find the mutex is not available so a block time is
|
* mutex. It should find the mutex is not available so a block time is
|
||||||
specified. */
|
* specified. */
|
||||||
if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )
|
if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* This task would expect to obtain the mutex unless its wait for
|
/* This task would expect to obtain the mutex unless its wait for
|
||||||
the mutex was aborted. */
|
* the mutex was aborted. */
|
||||||
if( xBlockWasAborted == pdFALSE )
|
if( xBlockWasAborted == pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -988,7 +1001,7 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* When the mutex is eventually obtained it is just given back before
|
/* When the mutex is eventually obtained it is just given back before
|
||||||
returning to suspend ready for the next cycle. */
|
* returning to suspend ready for the next cycle. */
|
||||||
if( xSemaphoreGive( xMutex ) != pdPASS )
|
if( xSemaphoreGive( xMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -1005,7 +1018,7 @@ BaseType_t xAreGenericQueueTasksStillRunning( void )
|
||||||
static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
|
static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
|
||||||
|
|
||||||
/* If the demo task is still running then we expect the loop counters to
|
/* If the demo task is still running then we expect the loop counters to
|
||||||
have incremented since this function was last called. */
|
* have incremented since this function was last called. */
|
||||||
if( ulLastLoopCounter == ulLoopCounter )
|
if( ulLastLoopCounter == ulLoopCounter )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -1020,9 +1033,7 @@ static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
|
||||||
ulLastLoopCounter2 = ulLoopCounter2;
|
ulLastLoopCounter2 = ulLoopCounter2;
|
||||||
|
|
||||||
/* Errors detected in the task itself will have latched xErrorDetected
|
/* Errors detected in the task itself will have latched xErrorDetected
|
||||||
to true. */
|
* to true. */
|
||||||
|
|
||||||
return ( BaseType_t ) !xErrorDetected;
|
return ( BaseType_t ) !xErrorDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,24 +63,24 @@
|
||||||
#define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
#define intqLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
|
|
||||||
/* The number of values to send/receive before checking that all values were
|
/* The number of values to send/receive before checking that all values were
|
||||||
processed as expected. */
|
* processed as expected. */
|
||||||
#define intqNUM_VALUES_TO_LOG ( 200 )
|
#define intqNUM_VALUES_TO_LOG ( 200 )
|
||||||
#define intqSHORT_DELAY ( 140 )
|
#define intqSHORT_DELAY ( 140 )
|
||||||
|
|
||||||
/* The value by which the value being sent to or received from a queue should
|
/* The value by which the value being sent to or received from a queue should
|
||||||
increment past intqNUM_VALUES_TO_LOG before we check that all values have been
|
* increment past intqNUM_VALUES_TO_LOG before we check that all values have been
|
||||||
sent/received correctly. This is done to ensure that all tasks and interrupts
|
* sent/received correctly. This is done to ensure that all tasks and interrupts
|
||||||
accessing the queue have completed their accesses with the
|
* accessing the queue have completed their accesses with the
|
||||||
intqNUM_VALUES_TO_LOG range. */
|
* intqNUM_VALUES_TO_LOG range. */
|
||||||
#define intqVALUE_OVERRUN ( 50 )
|
#define intqVALUE_OVERRUN ( 50 )
|
||||||
|
|
||||||
/* The delay used by the polling task. A short delay is used for code
|
/* The delay used by the polling task. A short delay is used for code
|
||||||
coverage. */
|
* coverage. */
|
||||||
#define intqONE_TICK_DELAY ( 1 )
|
#define intqONE_TICK_DELAY ( 1 )
|
||||||
|
|
||||||
/* Each task and interrupt is given a unique identifier. This value is used to
|
/* 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
|
* 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. */
|
* to distinguish between two tasks that are running the same task function. */
|
||||||
#define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
|
#define intqHIGH_PRIORITY_TASK1 ( ( UBaseType_t ) 1 )
|
||||||
#define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
|
#define intqHIGH_PRIORITY_TASK2 ( ( UBaseType_t ) 2 )
|
||||||
#define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
|
#define intqLOW_PRIORITY_TASK ( ( UBaseType_t ) 3 )
|
||||||
|
|
@ -89,11 +89,11 @@ to distinguish between two tasks that are running the same task function. */
|
||||||
#define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
|
#define intqQUEUE_LENGTH ( ( UBaseType_t ) 10 )
|
||||||
|
|
||||||
/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
|
/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received
|
||||||
from each queue by each task, otherwise an error is detected. */
|
* from each queue by each task, otherwise an error is detected. */
|
||||||
#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
|
#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 )
|
||||||
|
|
||||||
/* Send the next value to the queue that is normally empty. This is called
|
/* Send the next value to the queue that is normally empty. This is called
|
||||||
from within the interrupts. */
|
* from within the interrupts. */
|
||||||
#define timerNORMALLY_EMPTY_TX() \
|
#define timerNORMALLY_EMPTY_TX() \
|
||||||
if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
|
if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -109,8 +109,9 @@ from within the interrupts. */
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
/* Send the next value to the queue that is normally full. This is called
|
/* Send the next value to the queue that is normally full. This is called
|
||||||
from within the interrupts. */
|
* from within the interrupts. */
|
||||||
#define timerNORMALLY_FULL_TX() \
|
#define timerNORMALLY_FULL_TX() \
|
||||||
if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
|
if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -126,8 +127,9 @@ from within the interrupts. */
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
/* Receive a value from the normally empty queue. This is called from within
|
/* Receive a value from the normally empty queue. This is called from within
|
||||||
an interrupt. */
|
* an interrupt. */
|
||||||
#define timerNORMALLY_EMPTY_RX() \
|
#define timerNORMALLY_EMPTY_RX() \
|
||||||
if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
|
if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -139,7 +141,7 @@ an interrupt. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive a value from the normally full queue. This is called from within
|
/* Receive a value from the normally full queue. This is called from within
|
||||||
an interrupt. */
|
* an interrupt. */
|
||||||
#define timerNORMALLY_FULL_RX() \
|
#define timerNORMALLY_FULL_RX() \
|
||||||
if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
|
if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -156,7 +158,7 @@ static QueueHandle_t xNormallyEmptyQueue, xNormallyFullQueue;
|
||||||
static volatile UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
|
static volatile UBaseType_t uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0;
|
||||||
|
|
||||||
/* Any unexpected behaviour sets xErrorStatus to fail and log the line that
|
/* Any unexpected behaviour sets xErrorStatus to fail and log the line that
|
||||||
caused the error in xErrorLine. */
|
* caused the error in xErrorLine. */
|
||||||
static BaseType_t xErrorStatus = pdPASS;
|
static BaseType_t xErrorStatus = pdPASS;
|
||||||
static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
|
static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
|
||||||
|
|
||||||
|
|
@ -164,16 +166,16 @@ static volatile UBaseType_t xErrorLine = ( UBaseType_t ) 0;
|
||||||
static BaseType_t xWasSuspended = pdFALSE;
|
static BaseType_t xWasSuspended = pdFALSE;
|
||||||
|
|
||||||
/* The values that are sent to the queues. An incremented value is sent each
|
/* The values that are sent to the queues. An incremented value is sent each
|
||||||
time to each queue. */
|
* time to each queue. */
|
||||||
static volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
|
static volatile UBaseType_t uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0;
|
||||||
|
|
||||||
/* A handle to some of the tasks is required so they can be suspended/resumed. */
|
/* A handle to some of the tasks is required so they can be suspended/resumed. */
|
||||||
TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
|
TaskHandle_t xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2;
|
||||||
|
|
||||||
/* When a value is received in a queue the value is ticked off in the array
|
/* When a value is received in a queue the value is ticked off in the array
|
||||||
the array position of the value is set to a the identifier of the task or
|
* 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
|
* interrupt that accessed the queue. This way missing or duplicate values can be
|
||||||
detected. */
|
* detected. */
|
||||||
static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
static uint8_t ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
||||||
static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
static uint8_t ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 };
|
||||||
|
|
||||||
|
|
@ -185,9 +187,11 @@ static void prv1stHigherPriorityNormallyFullTask( void *pvParameters );
|
||||||
static void prv2ndHigherPriorityNormallyFullTask( void * pvParameters );
|
static void prv2ndHigherPriorityNormallyFullTask( void * pvParameters );
|
||||||
|
|
||||||
/* Used to mark the positions within the ucNormallyEmptyReceivedValues and
|
/* Used to mark the positions within the ucNormallyEmptyReceivedValues and
|
||||||
ucNormallyFullReceivedValues arrays, while checking for duplicates. */
|
* ucNormallyFullReceivedValues arrays, while checking for duplicates. */
|
||||||
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource );
|
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue,
|
||||||
static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource );
|
UBaseType_t uxSource );
|
||||||
|
static void prvRecordValue_NormallyFull( UBaseType_t uxValue,
|
||||||
|
UBaseType_t uxSource );
|
||||||
|
|
||||||
/* Logs the line on which an error occurred. */
|
/* Logs the line on which an error occurred. */
|
||||||
static void prvQueueAccessLogError( UBaseType_t uxLine );
|
static void prvQueueAccessLogError( UBaseType_t uxLine );
|
||||||
|
|
@ -205,27 +209,28 @@ void vStartInterruptQueueTasks( void )
|
||||||
xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
|
xTaskCreate( prvLowerPriorityNormallyFullTask, "L2QRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL );
|
||||||
|
|
||||||
/* Create the queues that are accessed by multiple tasks and multiple
|
/* Create the queues that are accessed by multiple tasks and multiple
|
||||||
interrupts. */
|
* interrupts. */
|
||||||
xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
|
xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( UBaseType_t ) sizeof( UBaseType_t ) );
|
||||||
xNormallyEmptyQueue = 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
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
* in use. The queue registry is provided as a means for kernel aware
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
* debuggers to locate queues and has no purpose if a kernel aware debugger
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
* is not being used. The call to vQueueAddToRegistry() will be removed
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
* by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
||||||
defined to be less than 1. */
|
* defined to be less than 1. */
|
||||||
vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" );
|
vQueueAddToRegistry( xNormallyFullQueue, "NormallyFull" );
|
||||||
vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
|
vQueueAddToRegistry( xNormallyEmptyQueue, "NormallyEmpty" );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSource )
|
static void prvRecordValue_NormallyFull( UBaseType_t uxValue,
|
||||||
|
UBaseType_t uxSource )
|
||||||
{
|
{
|
||||||
if( uxValue < intqNUM_VALUES_TO_LOG )
|
if( uxValue < intqNUM_VALUES_TO_LOG )
|
||||||
{
|
{
|
||||||
/* We don't expect to receive the same value twice, so if the value
|
/* We don't expect to receive the same value twice, so if the value
|
||||||
has already been marked as received an error has occurred. */
|
* has already been marked as received an error has occurred. */
|
||||||
if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
|
if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 )
|
||||||
{
|
{
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
|
@ -237,12 +242,13 @@ static void prvRecordValue_NormallyFull( UBaseType_t uxValue, UBaseType_t uxSour
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue, UBaseType_t uxSource )
|
static void prvRecordValue_NormallyEmpty( UBaseType_t uxValue,
|
||||||
|
UBaseType_t uxSource )
|
||||||
{
|
{
|
||||||
if( uxValue < intqNUM_VALUES_TO_LOG )
|
if( uxValue < intqNUM_VALUES_TO_LOG )
|
||||||
{
|
{
|
||||||
/* We don't expect to receive the same value twice, so if the value
|
/* We don't expect to receive the same value twice, so if the value
|
||||||
has already been marked as received an error has occurred. */
|
* has already been marked as received an error has occurred. */
|
||||||
if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
|
if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 )
|
||||||
{
|
{
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
|
@ -267,8 +273,8 @@ static void prvHigherPriorityNormallyEmptyTask( void *pvParameters )
|
||||||
UBaseType_t 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.
|
/* 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
|
* More than one task is running this code so we check the parameter value
|
||||||
to determine which task should start the timer. */
|
* to determine which task should start the timer. */
|
||||||
if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
if( ( UBaseType_t ) pvParameters == intqHIGH_PRIORITY_TASK1 )
|
||||||
{
|
{
|
||||||
vInitialiseTimerForIntQueueTest();
|
vInitialiseTimerForIntQueueTest();
|
||||||
|
|
@ -277,7 +283,7 @@ UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErr
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Block waiting to receive a value from the normally empty queue.
|
/* Block waiting to receive a value from the normally empty queue.
|
||||||
Interrupts will write to the queue so we should receive a value. */
|
* Interrupts will write to the queue so we should receive a value. */
|
||||||
if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
|
if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
|
@ -285,7 +291,7 @@ UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErr
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Note which value was received so we can check all expected
|
/* Note which value was received so we can check all expected
|
||||||
values are received and no values are duplicated. */
|
* values are received and no values are duplicated. */
|
||||||
prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
|
prvRecordValue_NormallyEmpty( uxRxed, ( UBaseType_t ) pvParameters );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,8 +310,8 @@ UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErr
|
||||||
uxInterrupts = 0;
|
uxInterrupts = 0;
|
||||||
|
|
||||||
/* Loop through the array, checking that both tasks have
|
/* Loop through the array, checking that both tasks have
|
||||||
placed values into the array, and that no values are missing.
|
* placed values into the array, and that no values are missing.
|
||||||
Start at 1 as we expect position 0 to be unused. */
|
* Start at 1 as we expect position 0 to be unused. */
|
||||||
for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
|
for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ )
|
||||||
{
|
{
|
||||||
if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
|
if( ucNormallyEmptyReceivedValues[ ux ] == 0 )
|
||||||
|
|
@ -336,6 +342,7 @@ UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErr
|
||||||
{
|
{
|
||||||
/* Only task 2 seemed to log any values. */
|
/* Only task 2 seemed to log any values. */
|
||||||
uxErrorCount1++;
|
uxErrorCount1++;
|
||||||
|
|
||||||
if( uxErrorCount1 > 2 )
|
if( uxErrorCount1 > 2 )
|
||||||
{
|
{
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
|
@ -350,6 +357,7 @@ UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErr
|
||||||
{
|
{
|
||||||
/* Only task 1 seemed to log any values. */
|
/* Only task 1 seemed to log any values. */
|
||||||
uxErrorCount2++;
|
uxErrorCount2++;
|
||||||
|
|
||||||
if( uxErrorCount2 > 2 )
|
if( uxErrorCount2 > 2 )
|
||||||
{
|
{
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
|
@ -372,11 +380,11 @@ UBaseType_t uxRxed, ux, uxTask1, uxTask2, uxInterrupts, uxErrorCount1 = 0, uxErr
|
||||||
uxValueForNormallyEmptyQueue = 0;
|
uxValueForNormallyEmptyQueue = 0;
|
||||||
|
|
||||||
/* Suspend ourselves, allowing the lower priority task to
|
/* Suspend ourselves, allowing the lower priority task to
|
||||||
actually receive something from the queue. Until now it
|
* actually receive something from the queue. Until now it
|
||||||
will have been prevented from doing so by the higher
|
* will have been prevented from doing so by the higher
|
||||||
priority tasks. The lower priority task will resume us
|
* priority tasks. The lower priority task will resume us
|
||||||
if it receives something. We will then resume the other
|
* if it receives something. We will then resume the other
|
||||||
higher priority task. */
|
* higher priority task. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
vTaskResume( xHighPriorityNormallyEmptyTask2 );
|
vTaskResume( xHighPriorityNormallyEmptyTask2 );
|
||||||
}
|
}
|
||||||
|
|
@ -397,7 +405,7 @@ UBaseType_t uxValue, uxRxed;
|
||||||
if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
|
if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) != errQUEUE_EMPTY )
|
||||||
{
|
{
|
||||||
/* A value should only be obtained when the high priority task is
|
/* A value should only be obtained when the high priority task is
|
||||||
suspended. */
|
* suspended. */
|
||||||
if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
|
if( eTaskGetState( xHighPriorityNormallyEmptyTask1 ) != eSuspended )
|
||||||
{
|
{
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
|
|
@ -412,7 +420,7 @@ UBaseType_t uxValue, uxRxed;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Raise our priority while we send so we can preempt the higher
|
/* Raise our priority while we send so we can preempt the higher
|
||||||
priority task, and ensure we get the Tx value into the queue. */
|
* priority task, and ensure we get the Tx value into the queue. */
|
||||||
vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
|
vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
|
||||||
|
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
|
|
@ -441,7 +449,7 @@ UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Make sure the queue starts full or near full. >> 1 as there are two
|
/* Make sure the queue starts full or near full. >> 1 as there are two
|
||||||
high priority tasks. */
|
* high priority tasks. */
|
||||||
for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
|
for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
|
||||||
{
|
{
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
|
|
@ -466,7 +474,7 @@ UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
|
if( xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
|
/* intqHIGH_PRIORITY_TASK2 is never suspended so we would not
|
||||||
expect it to ever time out. */
|
* expect it to ever time out. */
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -477,7 +485,7 @@ UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
|
if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) )
|
||||||
{
|
{
|
||||||
/* Make sure the other high priority task completes its send of
|
/* Make sure the other high priority task completes its send of
|
||||||
any values below intqNUM_VALUE_TO_LOG. */
|
* any values below intqNUM_VALUE_TO_LOG. */
|
||||||
vTaskDelay( intqSHORT_DELAY );
|
vTaskDelay( intqSHORT_DELAY );
|
||||||
|
|
||||||
vTaskSuspend( xHighPriorityNormallyFullTask2 );
|
vTaskSuspend( xHighPriorityNormallyFullTask2 );
|
||||||
|
|
@ -485,12 +493,12 @@ UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
if( xWasSuspended == pdTRUE )
|
if( xWasSuspended == pdTRUE )
|
||||||
{
|
{
|
||||||
/* We would have expected the other high priority task to have
|
/* We would have expected the other high priority task to have
|
||||||
set this back to false by now. */
|
* set this back to false by now. */
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the suspended flag so an error is not logged if the other
|
/* Set the suspended flag so an error is not logged if the other
|
||||||
task recognises a time out when it is unsuspended. */
|
* task recognises a time out when it is unsuspended. */
|
||||||
xWasSuspended = pdTRUE;
|
xWasSuspended = pdTRUE;
|
||||||
|
|
||||||
/* Check interrupts are also sending. */
|
/* Check interrupts are also sending. */
|
||||||
|
|
@ -513,7 +521,7 @@ UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
if( uxInterrupts == 0 )
|
if( uxInterrupts == 0 )
|
||||||
{
|
{
|
||||||
/* No writes from interrupts were found. Are interrupts
|
/* No writes from interrupts were found. Are interrupts
|
||||||
actually running? */
|
* actually running? */
|
||||||
prvQueueAccessLogError( __LINE__ );
|
prvQueueAccessLogError( __LINE__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -524,11 +532,11 @@ UBaseType_t uxValueToTx, ux, uxInterrupts;
|
||||||
uxValueForNormallyFullQueue = 0;
|
uxValueForNormallyFullQueue = 0;
|
||||||
|
|
||||||
/* Suspend ourselves, allowing the lower priority task to
|
/* Suspend ourselves, allowing the lower priority task to
|
||||||
actually receive something from the queue. Until now it
|
* actually receive something from the queue. Until now it
|
||||||
will have been prevented from doing so by the higher
|
* will have been prevented from doing so by the higher
|
||||||
priority tasks. The lower priority task will resume us
|
* priority tasks. The lower priority task will resume us
|
||||||
if it receives something. We will then resume the other
|
* if it receives something. We will then resume the other
|
||||||
higher priority task. */
|
* higher priority task. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
vTaskResume( xHighPriorityNormallyFullTask2 );
|
vTaskResume( xHighPriorityNormallyFullTask2 );
|
||||||
}
|
}
|
||||||
|
|
@ -544,7 +552,7 @@ UBaseType_t uxValueToTx, ux;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Make sure the queue starts full or near full. >> 1 as there are two
|
/* Make sure the queue starts full or near full. >> 1 as there are two
|
||||||
high priority tasks. */
|
* high priority tasks. */
|
||||||
for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
|
for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ )
|
||||||
{
|
{
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
|
|
@ -605,7 +613,7 @@ UBaseType_t uxValue, uxTxed = 9999;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Raise our priority while we receive so we can preempt the higher
|
/* Raise our priority while we receive so we can preempt the higher
|
||||||
priority task, and ensure we get the value from the queue. */
|
* priority task, and ensure we get the value from the queue. */
|
||||||
vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
|
vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 );
|
||||||
|
|
||||||
if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
|
if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS )
|
||||||
|
|
@ -630,7 +638,7 @@ UBaseType_t uxRxedValue;
|
||||||
static UBaseType_t uxNextOperation = 0;
|
static UBaseType_t uxNextOperation = 0;
|
||||||
|
|
||||||
/* Called from a timer interrupt. Perform various read and write
|
/* Called from a timer interrupt. Perform various read and write
|
||||||
accesses on the queues. */
|
* accesses on the queues. */
|
||||||
|
|
||||||
uxNextOperation++;
|
uxNextOperation++;
|
||||||
|
|
||||||
|
|
@ -658,7 +666,7 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
static UBaseType_t uxNextOperation = 0;
|
static UBaseType_t uxNextOperation = 0;
|
||||||
|
|
||||||
/* Called from a timer interrupt. Perform various read and write
|
/* Called from a timer interrupt. Perform various read and write
|
||||||
accesses on the queues. */
|
* accesses on the queues. */
|
||||||
|
|
||||||
uxNextOperation++;
|
uxNextOperation++;
|
||||||
|
|
||||||
|
|
@ -688,7 +696,7 @@ BaseType_t xAreIntQueueTasksStillRunning( void )
|
||||||
static UBaseType_t 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
|
/* xErrorStatus can be set outside of this function. This function just
|
||||||
checks that all the tasks are still cycling. */
|
* checks that all the tasks are still cycling. */
|
||||||
|
|
||||||
if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
|
if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 )
|
||||||
{
|
{
|
||||||
|
|
@ -724,4 +732,3 @@ static UBaseType_t uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, u
|
||||||
|
|
||||||
return xErrorStatus;
|
return xErrorStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
#define intsemNO_BLOCK 0
|
#define intsemNO_BLOCK 0
|
||||||
|
|
||||||
/* The maximum count value for the counting semaphore given from an
|
/* The maximum count value for the counting semaphore given from an
|
||||||
interrupt. */
|
* interrupt. */
|
||||||
#define intsemMAX_COUNT 3
|
#define intsemMAX_COUNT 3
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -95,32 +95,32 @@ static void vInterruptCountingSemaphoreTask( void *pvParameters );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
detected in any of the tasks. */
|
* detected in any of the tasks. */
|
||||||
static volatile BaseType_t xErrorDetected = pdFALSE;
|
static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
/* Counters that are incremented on each cycle of a test. This is used to
|
/* Counters that are incremented on each cycle of a test. This is used to
|
||||||
detect a stalled task - a test that is no longer running. */
|
* detect a stalled task - a test that is no longer running. */
|
||||||
static volatile uint32_t ulMasterLoops = 0, ulCountingSemaphoreLoops = 0;
|
static volatile uint32_t ulMasterLoops = 0, ulCountingSemaphoreLoops = 0;
|
||||||
|
|
||||||
/* Handles of the test tasks that must be accessed from other test tasks. */
|
/* Handles of the test tasks that must be accessed from other test tasks. */
|
||||||
static TaskHandle_t xSlaveHandle;
|
static TaskHandle_t xSlaveHandle;
|
||||||
|
|
||||||
/* A mutex which is given from an interrupt - although generally mutexes should
|
/* A mutex which is given from an interrupt - although generally mutexes should
|
||||||
not be used given in interrupts (and definitely never taken in an interrupt)
|
* not be used given in interrupts (and definitely never taken in an interrupt)
|
||||||
there are some circumstances when it may be desirable. */
|
* there are some circumstances when it may be desirable. */
|
||||||
static SemaphoreHandle_t xISRMutex = NULL;
|
static SemaphoreHandle_t xISRMutex = NULL;
|
||||||
|
|
||||||
/* A counting semaphore which is given from an interrupt. */
|
/* A counting semaphore which is given from an interrupt. */
|
||||||
static SemaphoreHandle_t xISRCountingSemaphore = NULL;
|
static SemaphoreHandle_t xISRCountingSemaphore = NULL;
|
||||||
|
|
||||||
/* A mutex which is shared between the master and slave tasks - the master
|
/* A mutex which is shared between the master and slave tasks - the master
|
||||||
does both sharing of this mutex with the slave and receiving a mutex from the
|
* does both sharing of this mutex with the slave and receiving a mutex from the
|
||||||
interrupt. */
|
* interrupt. */
|
||||||
static SemaphoreHandle_t xMasterSlaveMutex = NULL;
|
static SemaphoreHandle_t xMasterSlaveMutex = NULL;
|
||||||
|
|
||||||
/* Flag that allows the master task to control when the interrupt gives or does
|
/* Flag that allows the master task to control when the interrupt gives or does
|
||||||
not give the mutex. There is no mutual exclusion on this variable, but this is
|
* not give the mutex. There is no mutual exclusion on this variable, but this is
|
||||||
only test code and it should be fine in the 32=bit test environment. */
|
* only test code and it should be fine in the 32=bit test environment. */
|
||||||
static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE;
|
static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE;
|
||||||
|
|
||||||
/* Used to coordinate timing between tasks and the interrupt. */
|
/* Used to coordinate timing between tasks and the interrupt. */
|
||||||
|
|
@ -137,8 +137,8 @@ void vStartInterruptSemaphoreTasks( void )
|
||||||
configASSERT( xISRCountingSemaphore );
|
configASSERT( xISRCountingSemaphore );
|
||||||
|
|
||||||
/* Create the mutex that is shared between the master and slave tasks (the
|
/* Create the mutex that is shared between the master and slave tasks (the
|
||||||
master receives a mutex from an interrupt and shares a mutex with the
|
* master receives a mutex from an interrupt and shares a mutex with the
|
||||||
slave. */
|
* slave. */
|
||||||
xMasterSlaveMutex = xSemaphoreCreateMutex();
|
xMasterSlaveMutex = xSemaphoreCreateMutex();
|
||||||
configASSERT( xMasterSlaveMutex );
|
configASSERT( xMasterSlaveMutex );
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ static void vInterruptMutexMasterTask( void *pvParameters )
|
||||||
static void prvTakeAndGiveInTheSameOrder( void )
|
static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
{
|
{
|
||||||
/* Ensure the slave is suspended, and that this task is running at the
|
/* Ensure the slave is suspended, and that this task is running at the
|
||||||
lower priority as expected as the start conditions. */
|
* lower priority as expected as the start conditions. */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
||||||
|
|
@ -195,11 +195,11 @@ static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This task now has the mutex. Unsuspend the slave so it too
|
/* This task now has the mutex. Unsuspend the slave so it too
|
||||||
attempts to take the mutex. */
|
* attempts to take the mutex. */
|
||||||
vTaskResume( xSlaveHandle );
|
vTaskResume( xSlaveHandle );
|
||||||
|
|
||||||
/* The slave has the higher priority so should now have executed and
|
/* The slave has the higher priority so should now have executed and
|
||||||
blocked on the semaphore. */
|
* blocked on the semaphore. */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
||||||
|
|
@ -207,23 +207,25 @@ static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
/* This task should now have inherited the priority of the slave
|
/* This task should now have inherited the priority of the slave
|
||||||
task. */
|
* task. */
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now wait a little longer than the time between ISR gives to also
|
/* Now wait a little longer than the time between ISR gives to also
|
||||||
obtain the ISR mutex. */
|
* obtain the ISR mutex. */
|
||||||
xOkToGiveMutex = pdTRUE;
|
xOkToGiveMutex = pdTRUE;
|
||||||
|
|
||||||
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xOkToGiveMutex = pdFALSE;
|
xOkToGiveMutex = pdFALSE;
|
||||||
|
|
||||||
/* Attempting to take again immediately should fail as the mutex is
|
/* Attempting to take again immediately should fail as the mutex is
|
||||||
already held. */
|
* already held. */
|
||||||
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -236,8 +238,8 @@ static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give back the ISR semaphore to ensure the priority is not
|
/* Give back the ISR semaphore to ensure the priority is not
|
||||||
disinherited as the shared mutex (which the higher priority task is
|
* disinherited as the shared mutex (which the higher priority task is
|
||||||
attempting to obtain) is still held. */
|
* attempting to obtain) is still held. */
|
||||||
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -249,9 +251,9 @@ static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally give back the shared mutex. This time the higher priority
|
/* Finally give back the shared mutex. This time the higher priority
|
||||||
task should run before this task runs again - so this task should have
|
* task should run before this task runs again - so this task should have
|
||||||
disinherited the priority and the higher priority task should be in the
|
* disinherited the priority and the higher priority task should be in the
|
||||||
suspended state again. */
|
* suspended state again. */
|
||||||
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -276,7 +278,7 @@ static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
static void prvTakeAndGiveInTheOppositeOrder( void )
|
static void prvTakeAndGiveInTheOppositeOrder( void )
|
||||||
{
|
{
|
||||||
/* Ensure the slave is suspended, and that this task is running at the
|
/* Ensure the slave is suspended, and that this task is running at the
|
||||||
lower priority as expected as the start conditions. */
|
* lower priority as expected as the start conditions. */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
||||||
|
|
@ -295,11 +297,11 @@ static void prvTakeAndGiveInTheOppositeOrder( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This task now has the mutex. Unsuspend the slave so it too
|
/* This task now has the mutex. Unsuspend the slave so it too
|
||||||
attempts to take the mutex. */
|
* attempts to take the mutex. */
|
||||||
vTaskResume( xSlaveHandle );
|
vTaskResume( xSlaveHandle );
|
||||||
|
|
||||||
/* The slave has the higher priority so should now have executed and
|
/* The slave has the higher priority so should now have executed and
|
||||||
blocked on the semaphore. */
|
* blocked on the semaphore. */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
||||||
|
|
@ -307,23 +309,25 @@ static void prvTakeAndGiveInTheOppositeOrder( void )
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
/* This task should now have inherited the priority of the slave
|
/* This task should now have inherited the priority of the slave
|
||||||
task. */
|
* task. */
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now wait a little longer than the time between ISR gives to also
|
/* Now wait a little longer than the time between ISR gives to also
|
||||||
obtain the ISR mutex. */
|
* obtain the ISR mutex. */
|
||||||
xOkToGiveMutex = pdTRUE;
|
xOkToGiveMutex = pdTRUE;
|
||||||
|
|
||||||
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xOkToGiveMutex = pdFALSE;
|
xOkToGiveMutex = pdFALSE;
|
||||||
|
|
||||||
/* Attempting to take again immediately should fail as the mutex is
|
/* Attempting to take again immediately should fail as the mutex is
|
||||||
already held. */
|
* already held. */
|
||||||
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -336,23 +340,23 @@ static void prvTakeAndGiveInTheOppositeOrder( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give back the shared semaphore to ensure the priority is not disinherited
|
/* Give back the shared semaphore to ensure the priority is not disinherited
|
||||||
as the ISR mutex is still held. The higher priority slave task should run
|
* as the ISR mutex is still held. The higher priority slave task should run
|
||||||
before this task runs again. */
|
* before this task runs again. */
|
||||||
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should still be at the priority of the slave task as this task still
|
/* Should still be at the priority of the slave task as this task still
|
||||||
holds one semaphore (this is a simplification in the priority inheritance
|
* holds one semaphore (this is a simplification in the priority inheritance
|
||||||
mechanism. */
|
* mechanism. */
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give back the ISR semaphore, which should result in the priority being
|
/* Give back the ISR semaphore, which should result in the priority being
|
||||||
disinherited as it was the last mutex held. */
|
* disinherited as it was the last mutex held. */
|
||||||
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -376,12 +380,12 @@ static void vInterruptMutexSlaveTask( void *pvParameters )
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* This task starts by suspending itself so when it executes can be
|
/* This task starts by suspending itself so when it executes can be
|
||||||
controlled by the master task. */
|
* controlled by the master task. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/* This task will execute when the master task already holds the mutex.
|
/* This task will execute when the master task already holds the mutex.
|
||||||
Attempting to take the mutex will place this task in the Blocked
|
* Attempting to take the mutex will place this task in the Blocked
|
||||||
state. */
|
* state. */
|
||||||
if( xSemaphoreTake( xMasterSlaveMutex, portMAX_DELAY ) != pdPASS )
|
if( xSemaphoreTake( xMasterSlaveMutex, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -411,7 +415,7 @@ const TickType_t xDelay = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until it is expected that the interrupt will have filled the
|
/* Wait until it is expected that the interrupt will have filled the
|
||||||
counting semaphore. */
|
* counting semaphore. */
|
||||||
xOkToGiveCountingSemaphore = pdTRUE;
|
xOkToGiveCountingSemaphore = pdTRUE;
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
xOkToGiveCountingSemaphore = pdFALSE;
|
xOkToGiveCountingSemaphore = pdFALSE;
|
||||||
|
|
@ -430,9 +434,10 @@ const TickType_t xDelay = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS )
|
||||||
ulCountingSemaphoreLoops++;
|
ulCountingSemaphoreLoops++;
|
||||||
|
|
||||||
/* Expect to be able to take the counting semaphore intsemMAX_COUNT
|
/* Expect to be able to take the counting semaphore intsemMAX_COUNT
|
||||||
times. A block time of 0 is used as the semaphore should already be
|
* times. A block time of 0 is used as the semaphore should already be
|
||||||
there. */
|
* there. */
|
||||||
xCount = 0;
|
xCount = 0;
|
||||||
|
|
||||||
while( xSemaphoreTake( xISRCountingSemaphore, 0 ) == pdPASS )
|
while( xSemaphoreTake( xISRCountingSemaphore, 0 ) == pdPASS )
|
||||||
{
|
{
|
||||||
xCount++;
|
xCount++;
|
||||||
|
|
@ -444,7 +449,7 @@ const TickType_t xDelay = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now raise the priority of this task so it runs immediately that the
|
/* Now raise the priority of this task so it runs immediately that the
|
||||||
semaphore is given from the interrupt. */
|
* semaphore is given from the interrupt. */
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
|
|
||||||
/* Block to wait for the semaphore to be given from the interrupt. */
|
/* Block to wait for the semaphore to be given from the interrupt. */
|
||||||
|
|
@ -468,15 +473,17 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
TickType_t xTimeNow;
|
TickType_t xTimeNow;
|
||||||
|
|
||||||
/* No mutual exclusion on xOkToGiveMutex, but this is only test code (and
|
/* No mutual exclusion on xOkToGiveMutex, but this is only test code (and
|
||||||
only executed on a 32-bit architecture) so ignore that in this case. */
|
* only executed on a 32-bit architecture) so ignore that in this case. */
|
||||||
xTimeNow = xTaskGetTickCountFromISR();
|
xTimeNow = xTaskGetTickCountFromISR();
|
||||||
|
|
||||||
if( ( ( TickType_t ) ( xTimeNow - xLastGiveTime ) ) >= pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )
|
if( ( ( TickType_t ) ( xTimeNow - xLastGiveTime ) ) >= pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )
|
||||||
{
|
{
|
||||||
configASSERT( xISRMutex );
|
configASSERT( xISRMutex );
|
||||||
|
|
||||||
if( xOkToGiveMutex != pdFALSE )
|
if( xOkToGiveMutex != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Null is used as the second parameter in this give, and non-NULL
|
/* Null is used as the second parameter in this give, and non-NULL
|
||||||
in the other gives for code coverage reasons. */
|
* in the other gives for code coverage reasons. */
|
||||||
xSemaphoreGiveFromISR( xISRMutex, NULL );
|
xSemaphoreGiveFromISR( xISRMutex, NULL );
|
||||||
|
|
||||||
/* Second give attempt should fail. */
|
/* Second give attempt should fail. */
|
||||||
|
|
@ -487,6 +494,7 @@ TickType_t xTimeNow;
|
||||||
{
|
{
|
||||||
xSemaphoreGiveFromISR( xISRCountingSemaphore, &xHigherPriorityTaskWoken );
|
xSemaphoreGiveFromISR( xISRCountingSemaphore, &xHigherPriorityTaskWoken );
|
||||||
}
|
}
|
||||||
|
|
||||||
xLastGiveTime = xTimeNow;
|
xLastGiveTime = xTimeNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,7 +509,7 @@ BaseType_t xAreInterruptSemaphoreTasksStillRunning( void )
|
||||||
static uint32_t ulLastMasterLoopCounter = 0, ulLastCountingSemaphoreLoops = 0;
|
static uint32_t ulLastMasterLoopCounter = 0, ulLastCountingSemaphoreLoops = 0;
|
||||||
|
|
||||||
/* If the demo tasks are running then it is expected that the loop counters
|
/* If the demo tasks are running then it is expected that the loop counters
|
||||||
will have changed since this function was last called. */
|
* will have changed since this function was last called. */
|
||||||
if( ulLastMasterLoopCounter == ulMasterLoops )
|
if( ulLastMasterLoopCounter == ulMasterLoops )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -517,9 +525,7 @@ static uint32_t ulLastMasterLoopCounter = 0, ulLastCountingSemaphoreLoops = 0;
|
||||||
ulLastCountingSemaphoreLoops = ulCountingSemaphoreLoops++;
|
ulLastCountingSemaphoreLoops = ulCountingSemaphoreLoops++;
|
||||||
|
|
||||||
/* Errors detected in the task itself will have latched xErrorDetected
|
/* Errors detected in the task itself will have latched xErrorDetected
|
||||||
to true. */
|
* to true. */
|
||||||
|
|
||||||
return ( BaseType_t ) !xErrorDetected;
|
return ( BaseType_t ) !xErrorDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,11 +68,11 @@
|
||||||
#include "MessageBufferAMP.h"
|
#include "MessageBufferAMP.h"
|
||||||
|
|
||||||
/* Enough for 3 4 byte pointers, including the additional 4 bytes per message
|
/* Enough for 3 4 byte pointers, including the additional 4 bytes per message
|
||||||
overhead of message buffers. */
|
* overhead of message buffers. */
|
||||||
#define mbaCONTROL_MESSAGE_BUFFER_SIZE ( 24 )
|
#define mbaCONTROL_MESSAGE_BUFFER_SIZE ( 24 )
|
||||||
|
|
||||||
/* Enough four 4 8 byte strings, plus the additional 4 bytes per message
|
/* Enough four 4 8 byte strings, plus the additional 4 bytes per message
|
||||||
overhead of message buffers. */
|
* overhead of message buffers. */
|
||||||
#define mbaTASK_MESSAGE_BUFFER_SIZE ( 60 )
|
#define mbaTASK_MESSAGE_BUFFER_SIZE ( 60 )
|
||||||
|
|
||||||
/* The number of instances of prvCoreBTasks that are created. */
|
/* The number of instances of prvCoreBTasks that are created. */
|
||||||
|
|
@ -82,7 +82,7 @@ overhead of message buffers. */
|
||||||
#define mbaDONT_BLOCK 0
|
#define mbaDONT_BLOCK 0
|
||||||
|
|
||||||
/* Macro that mimics an interrupt service routine executing by simply calling
|
/* Macro that mimics an interrupt service routine executing by simply calling
|
||||||
the routine inline. */
|
* the routine inline. */
|
||||||
#define mbaGENERATE_CORE_B_INTERRUPT() prvCoreBInterruptHandler()
|
#define mbaGENERATE_CORE_B_INTERRUPT() prvCoreBInterruptHandler()
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -112,15 +112,15 @@ static void prvCoreBInterruptHandler( void );
|
||||||
static MessageBufferHandle_t xCoreBMessageBuffers[ mbaNUMBER_OF_CORE_B_TASKS ];
|
static MessageBufferHandle_t xCoreBMessageBuffers[ mbaNUMBER_OF_CORE_B_TASKS ];
|
||||||
|
|
||||||
/* The control message buffer. This is used to pass the handle of the message
|
/* The control message buffer. This is used to pass the handle of the message
|
||||||
message buffer that holds application data into the core to core interrupt
|
* message buffer that holds application data into the core to core interrupt
|
||||||
service routine. */
|
* service routine. */
|
||||||
static MessageBufferHandle_t xControlMessageBuffer;
|
static MessageBufferHandle_t xControlMessageBuffer;
|
||||||
|
|
||||||
/* Counters used to indicate to the check that the tasks are still executing. */
|
/* Counters used to indicate to the check that the tasks are still executing. */
|
||||||
static uint32_t ulCycleCounters[ mbaNUMBER_OF_CORE_B_TASKS ];
|
static uint32_t ulCycleCounters[ mbaNUMBER_OF_CORE_B_TASKS ];
|
||||||
|
|
||||||
/* Set to pdFALSE if any errors are detected. Used to inform the check task
|
/* Set to pdFALSE if any errors are detected. Used to inform the check task
|
||||||
that something might be wrong. */
|
* that something might be wrong. */
|
||||||
BaseType_t xDemoStatus = pdPASS;
|
BaseType_t xDemoStatus = pdPASS;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -144,8 +144,8 @@ BaseType_t x;
|
||||||
configASSERT( xCoreBMessageBuffers[ x ] );
|
configASSERT( xCoreBMessageBuffers[ x ] );
|
||||||
|
|
||||||
/* Pass the loop counter into the created task using the task's
|
/* Pass the loop counter into the created task using the task's
|
||||||
parameter. The task then uses the value as an index into the
|
* parameter. The task then uses the value as an index into the
|
||||||
ulCycleCounters and xCoreBMessageBuffers arrays. */
|
* ulCycleCounters and xCoreBMessageBuffers arrays. */
|
||||||
xTaskCreate( prvCoreBTasks,
|
xTaskCreate( prvCoreBTasks,
|
||||||
"AMPCoreB1",
|
"AMPCoreB1",
|
||||||
xStackSize,
|
xStackSize,
|
||||||
|
|
@ -169,15 +169,15 @@ char cString[ 15 ]; /* At least large enough to hold "4294967295\0" (0xffffffff)
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Create the next string to send. The value is incremented on each
|
/* Create the next string to send. The value is incremented on each
|
||||||
loop iteration, and the length of the string changes as the number of
|
* loop iteration, and the length of the string changes as the number of
|
||||||
digits in the value increases. */
|
* digits in the value increases. */
|
||||||
sprintf( cString, "%lu", ( unsigned long ) ulNextValue );
|
sprintf( cString, "%lu", ( unsigned long ) ulNextValue );
|
||||||
|
|
||||||
/* Send the value from this (pseudo) Core A to the tasks on the (pseudo)
|
/* Send the value from this (pseudo) Core A to the tasks on the (pseudo)
|
||||||
Core B via the message buffers. This will result in sbSEND_COMPLETED()
|
* Core B via the message buffers. This will result in sbSEND_COMPLETED()
|
||||||
being executed, which in turn will write the handle of the message
|
* being executed, which in turn will write the handle of the message
|
||||||
buffer written to into xControlMessageBuffer then generate an interrupt
|
* buffer written to into xControlMessageBuffer then generate an interrupt
|
||||||
in core B. */
|
* in core B. */
|
||||||
for( x = 0; x < mbaNUMBER_OF_CORE_B_TASKS; x++ )
|
for( x = 0; x < mbaNUMBER_OF_CORE_B_TASKS; x++ )
|
||||||
{
|
{
|
||||||
xMessageBufferSend( /* The message buffer to write to. */
|
xMessageBufferSend( /* The message buffer to write to. */
|
||||||
|
|
@ -191,7 +191,7 @@ char cString[ 15 ]; /* At least large enough to hold "4294967295\0" (0xffffffff)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delay before repeating with a different and potentially different
|
/* Delay before repeating with a different and potentially different
|
||||||
length string. */
|
* length string. */
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
ulNextValue++;
|
ulNextValue++;
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +207,7 @@ char cExpectedString[ 15 ]; /* At least large enough to hold "4294967295\0" (0xf
|
||||||
char cReceivedString[ 15 ];
|
char cReceivedString[ 15 ];
|
||||||
|
|
||||||
/* The index into the xCoreBMessageBuffers and ulLoopCounter arrays is
|
/* The index into the xCoreBMessageBuffers and ulLoopCounter arrays is
|
||||||
passed into this task using the task's parameter. */
|
* passed into this task using the task's parameter. */
|
||||||
x = ( BaseType_t ) pvParameters;
|
x = ( BaseType_t ) pvParameters;
|
||||||
configASSERT( x < mbaNUMBER_OF_CORE_B_TASKS );
|
configASSERT( x < mbaNUMBER_OF_CORE_B_TASKS );
|
||||||
|
|
||||||
|
|
@ -232,7 +232,7 @@ char cReceivedString[ 15 ];
|
||||||
( void ) xReceivedBytes; /* Incase configASSERT() is not defined. */
|
( void ) xReceivedBytes; /* Incase configASSERT() is not defined. */
|
||||||
|
|
||||||
/* If the received string matches that expected then increment the loop
|
/* If the received string matches that expected then increment the loop
|
||||||
counter so the check task knows this task is still running. */
|
* counter so the check task knows this task is still running. */
|
||||||
if( strcmp( cReceivedString, cExpectedString ) == 0 )
|
if( strcmp( cReceivedString, cExpectedString ) == 0 )
|
||||||
{
|
{
|
||||||
( ulCycleCounters[ x ] )++;
|
( ulCycleCounters[ x ] )++;
|
||||||
|
|
@ -249,7 +249,7 @@ char cReceivedString[ 15 ];
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Called by the reimplementation of sbSEND_COMPLETED(), which can be defined
|
/* Called by the reimplementation of sbSEND_COMPLETED(), which can be defined
|
||||||
as follows in FreeRTOSConfig.h:
|
* as follows in FreeRTOSConfig.h:
|
||||||
#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer )
|
#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreBInterrupt( pxStreamBuffer )
|
||||||
*/
|
*/
|
||||||
void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer )
|
void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer )
|
||||||
|
|
@ -257,50 +257,50 @@ void vGenerateCoreBInterrupt( void * xUpdatedMessageBuffer )
|
||||||
MessageBufferHandle_t xUpdatedBuffer = ( MessageBufferHandle_t ) xUpdatedMessageBuffer;
|
MessageBufferHandle_t xUpdatedBuffer = ( MessageBufferHandle_t ) xUpdatedMessageBuffer;
|
||||||
|
|
||||||
/* If sbSEND_COMPLETED() has been implemented as above, then this function
|
/* If sbSEND_COMPLETED() has been implemented as above, then this function
|
||||||
is called from within xMessageBufferSend(). As this function also calls
|
* is called from within xMessageBufferSend(). As this function also calls
|
||||||
xMessageBufferSend() itself it is necessary to guard against a recursive
|
* xMessageBufferSend() itself it is necessary to guard against a recursive
|
||||||
call. If the message buffer just updated is the message buffer written to
|
* call. If the message buffer just updated is the message buffer written to
|
||||||
by this function, then this is a recursive call, and the function can just
|
* by this function, then this is a recursive call, and the function can just
|
||||||
exit without taking further action. */
|
* exit without taking further action. */
|
||||||
if( xUpdatedBuffer != xControlMessageBuffer )
|
if( xUpdatedBuffer != xControlMessageBuffer )
|
||||||
{
|
{
|
||||||
/* Use xControlMessageBuffer to pass the handle of the message buffer
|
/* Use xControlMessageBuffer to pass the handle of the message buffer
|
||||||
written to by core A to the interrupt handler about to be generated in
|
* written to by core A to the interrupt handler about to be generated in
|
||||||
core B. */
|
* core B. */
|
||||||
xMessageBufferSend( xControlMessageBuffer, &xUpdatedBuffer, sizeof( xUpdatedBuffer ), mbaDONT_BLOCK );
|
xMessageBufferSend( xControlMessageBuffer, &xUpdatedBuffer, sizeof( xUpdatedBuffer ), mbaDONT_BLOCK );
|
||||||
|
|
||||||
/* This is where the interrupt would be generated. In this case it is
|
/* This is where the interrupt would be generated. In this case it is
|
||||||
not a genuine interrupt handler that executes, just a standard function
|
* not a genuine interrupt handler that executes, just a standard function
|
||||||
call. */
|
* call. */
|
||||||
mbaGENERATE_CORE_B_INTERRUPT();
|
mbaGENERATE_CORE_B_INTERRUPT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Handler for the interrupts that are triggered on core A but execute on core
|
/* Handler for the interrupts that are triggered on core A but execute on core
|
||||||
B. */
|
* B. */
|
||||||
static void prvCoreBInterruptHandler( void )
|
static void prvCoreBInterruptHandler( void )
|
||||||
{
|
{
|
||||||
MessageBufferHandle_t xUpdatedMessageBuffer;
|
MessageBufferHandle_t xUpdatedMessageBuffer;
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
/* xControlMessageBuffer contains the handle of the message buffer that
|
/* xControlMessageBuffer contains the handle of the message buffer that
|
||||||
contains data. */
|
* contains data. */
|
||||||
if( xMessageBufferReceive( xControlMessageBuffer,
|
if( xMessageBufferReceive( xControlMessageBuffer,
|
||||||
&xUpdatedMessageBuffer,
|
&xUpdatedMessageBuffer,
|
||||||
sizeof( xUpdatedMessageBuffer ),
|
sizeof( xUpdatedMessageBuffer ),
|
||||||
mbaDONT_BLOCK ) == sizeof( xUpdatedMessageBuffer ) )
|
mbaDONT_BLOCK ) == sizeof( xUpdatedMessageBuffer ) )
|
||||||
{
|
{
|
||||||
/* Call the API function that sends a notification to any task that is
|
/* Call the API function that sends a notification to any task that is
|
||||||
blocked on the xUpdatedMessageBuffer message buffer waiting for data to
|
* blocked on the xUpdatedMessageBuffer message buffer waiting for data to
|
||||||
arrive. */
|
* arrive. */
|
||||||
xMessageBufferSendCompletedFromISR( xUpdatedMessageBuffer, &xHigherPriorityTaskWoken );
|
xMessageBufferSendCompletedFromISR( xUpdatedMessageBuffer, &xHigherPriorityTaskWoken );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normal FreeRTOS yield from interrupt semantics, where
|
/* Normal FreeRTOS yield from interrupt semantics, where
|
||||||
xHigherPriorityTaskWoken is initialized to pdFALSE and will then get set to
|
* xHigherPriorityTaskWoken is initialized to pdFALSE and will then get set to
|
||||||
pdTRUE if the interrupt safe API unblocks a task that has a priority above
|
* pdTRUE if the interrupt safe API unblocks a task that has a priority above
|
||||||
that of the currently executing task. */
|
* that of the currently executing task. */
|
||||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -311,7 +311,7 @@ static uint32_t ulLastCycleCounters[ mbaNUMBER_OF_CORE_B_TASKS ] = { 0 };
|
||||||
BaseType_t x;
|
BaseType_t x;
|
||||||
|
|
||||||
/* Called by the check task to determine the health status of the tasks
|
/* Called by the check task to determine the health status of the tasks
|
||||||
implemented in this demo. */
|
* implemented in this demo. */
|
||||||
for( x = 0; x < mbaNUMBER_OF_CORE_B_TASKS; x++ )
|
for( x = 0; x < mbaNUMBER_OF_CORE_B_TASKS; x++ )
|
||||||
{
|
{
|
||||||
if( ulLastCycleCounters[ x ] == ulCycleCounters[ x ] )
|
if( ulLastCycleCounters[ x ] == ulCycleCounters[ x ] )
|
||||||
|
|
@ -326,4 +326,3 @@ BaseType_t x;
|
||||||
|
|
||||||
return xDemoStatus;
|
return xDemoStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
#define mbNUMBER_OF_SENDER_TASKS ( 2 )
|
#define mbNUMBER_OF_SENDER_TASKS ( 2 )
|
||||||
|
|
||||||
/* Priority of the test tasks. The send and receive go from low to high
|
/* Priority of the test tasks. The send and receive go from low to high
|
||||||
priority tasks, and from high to low priority tasks. */
|
* priority tasks, and from high to low priority tasks. */
|
||||||
#define mbLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
#define mbLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
#define mbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
#define mbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
|
||||||
|
|
@ -87,9 +87,10 @@ static void prvNonBlockingReceiverTask( void *pvParameters );
|
||||||
static void prvNonBlockingSenderTask( void * pvParameters );
|
static void prvNonBlockingSenderTask( void * pvParameters );
|
||||||
|
|
||||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
|
||||||
/* This file tests both statically and dynamically allocated message buffers.
|
/* This file tests both statically and dynamically allocated message buffers.
|
||||||
Allocate the structures and buffers to be used by the statically allocated
|
* Allocate the structures and buffers to be used by the statically allocated
|
||||||
objects, which get used in the echo tests. */
|
* objects, which get used in the echo tests. */
|
||||||
static void prvReceiverTask( void * pvParameters );
|
static void prvReceiverTask( void * pvParameters );
|
||||||
static void prvSenderTask( void * pvParameters );
|
static void prvSenderTask( void * pvParameters );
|
||||||
|
|
||||||
|
|
@ -110,7 +111,7 @@ static void prvNonBlockingSenderTask( void *pvParameters );
|
||||||
static MessageBufferHandle_t xCoherenceTestMessageBuffer = NULL;
|
static MessageBufferHandle_t xCoherenceTestMessageBuffer = NULL;
|
||||||
|
|
||||||
static uint32_t ulSizeCoherencyTestCycles = 0UL;
|
static uint32_t ulSizeCoherencyTestCycles = 0UL;
|
||||||
#endif
|
#endif /* if ( configRUN_ADDITIONAL_TESTS == 1 ) */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -124,17 +125,17 @@ typedef struct ECHO_MESSAGE_BUFFERS
|
||||||
static uint32_t ulEchoLoopCounters[ mbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
|
static uint32_t ulEchoLoopCounters[ mbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
|
||||||
|
|
||||||
/* The non-blocking tasks monitor their operation, and if no errors have been
|
/* The non-blocking tasks monitor their operation, and if no errors have been
|
||||||
found, increment ulNonBlockingRxCounter. xAreMessageBufferTasksStillRunning()
|
* found, increment ulNonBlockingRxCounter. xAreMessageBufferTasksStillRunning()
|
||||||
then checks ulNonBlockingRxCounter and only returns pdPASS if
|
* then checks ulNonBlockingRxCounter and only returns pdPASS if
|
||||||
ulNonBlockingRxCounter is still incrementing. */
|
* ulNonBlockingRxCounter is still incrementing. */
|
||||||
static uint32_t ulNonBlockingRxCounter = 0;
|
static uint32_t ulNonBlockingRxCounter = 0;
|
||||||
|
|
||||||
/* A message that is longer than the buffer, parts of which are written to the
|
/* A message that is longer than the buffer, parts of which are written to the
|
||||||
message buffer to test writing different lengths at different offsets. */
|
* message buffer to test writing different lengths at different offsets. */
|
||||||
static const char * pc55ByteString = "One two three four five six seven eight nine ten eleve";
|
static const char * pc55ByteString = "One two three four five six seven eight nine ten eleve";
|
||||||
|
|
||||||
/* Remember the required stack size so tasks can be created at run time (after
|
/* Remember the required stack size so tasks can be created at run time (after
|
||||||
initialisation time. */
|
* initialisation time. */
|
||||||
static configSTACK_DEPTH_TYPE xBlockingStackSize = 0;
|
static configSTACK_DEPTH_TYPE xBlockingStackSize = 0;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -150,14 +151,14 @@ MessageBufferHandle_t xMessageBuffer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The echo servers sets up the message buffers before creating the echo
|
/* The echo servers sets up the message buffers before creating the echo
|
||||||
client tasks. One set of tasks has the server as the higher priority, and
|
* client tasks. One set of tasks has the server as the higher priority, and
|
||||||
the other has the client as the higher priority. */
|
* the other has the client as the higher priority. */
|
||||||
xTaskCreate( prvEchoServer, "1EchoServer", xBlockingStackSize, NULL, mbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvEchoServer, "1EchoServer", xBlockingStackSize, NULL, mbHIGHER_PRIORITY, NULL );
|
||||||
xTaskCreate( prvEchoServer, "2EchoServer", xBlockingStackSize, NULL, mbLOWER_PRIORITY, NULL );
|
xTaskCreate( prvEchoServer, "2EchoServer", xBlockingStackSize, NULL, mbLOWER_PRIORITY, NULL );
|
||||||
|
|
||||||
/* The non blocking tasks run continuously and will interleave with each
|
/* The non blocking tasks run continuously and will interleave with each
|
||||||
other, so must be created at the lowest priority. The message buffer they
|
* other, so must be created at the lowest priority. The message buffer they
|
||||||
use is created and passed in using the task's parameter. */
|
* use is created and passed in using the task's parameter. */
|
||||||
xMessageBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
xMessageBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
xTaskCreate( prvNonBlockingReceiverTask, "NonBlkRx", xStackSize, ( void * ) xMessageBuffer, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( prvNonBlockingReceiverTask, "NonBlkRx", xStackSize, ( void * ) xMessageBuffer, tskIDLE_PRIORITY, NULL );
|
||||||
xTaskCreate( prvNonBlockingSenderTask, "NonBlkTx", xStackSize, ( void * ) xMessageBuffer, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( prvNonBlockingSenderTask, "NonBlkTx", xStackSize, ( void * ) xMessageBuffer, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
@ -165,8 +166,8 @@ MessageBufferHandle_t xMessageBuffer;
|
||||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
/* The sender tasks set up the message buffers before creating the
|
/* The sender tasks set up the message buffers before creating the
|
||||||
receiver tasks. Priorities must be 0 and 1 as the priority is used to
|
* receiver tasks. Priorities must be 0 and 1 as the priority is used to
|
||||||
index into the xStaticMessageBuffers and ucBufferStorage arrays. */
|
* index into the xStaticMessageBuffers and ucBufferStorage arrays. */
|
||||||
xTaskCreate( prvSenderTask, "1Sender", xBlockingStackSize, NULL, mbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvSenderTask, "1Sender", xBlockingStackSize, NULL, mbHIGHER_PRIORITY, NULL );
|
||||||
xTaskCreate( prvSenderTask, "2Sender", xBlockingStackSize, NULL, mbLOWER_PRIORITY, NULL );
|
xTaskCreate( prvSenderTask, "2Sender", xBlockingStackSize, NULL, mbLOWER_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -198,8 +199,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xAllowableMargin;
|
( void ) xAllowableMargin;
|
||||||
|
|
||||||
/* To minimise stack and heap usage a full size buffer is allocated from
|
/* To minimise stack and heap usage a full size buffer is allocated from
|
||||||
the heap, then buffers which hold smaller amounts of data are overlayed
|
* the heap, then buffers which hold smaller amounts of data are overlayed
|
||||||
with the larger buffer - just make sure not to use both at once!. */
|
* with the larger buffer - just make sure not to use both at once!. */
|
||||||
pucFullBuffer = pvPortMalloc( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
pucFullBuffer = pvPortMalloc( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
configASSERT( pucFullBuffer );
|
configASSERT( pucFullBuffer );
|
||||||
|
|
||||||
|
|
@ -207,7 +208,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
pucReadData = pucData + x17ByteLength;
|
pucReadData = pucData + x17ByteLength;
|
||||||
|
|
||||||
/* Nothing has been added or removed yet, so expect the free space to be
|
/* Nothing has been added or removed yet, so expect the free space to be
|
||||||
exactly as created and the length of the next message to be 0. */
|
* exactly as created and the length of the next message to be 0. */
|
||||||
xExpectedSpace = xMessageBufferSpaceAvailable( xMessageBuffer );
|
xExpectedSpace = xMessageBufferSpaceAvailable( xMessageBuffer );
|
||||||
configASSERT( xExpectedSpace == mbMESSAGE_BUFFER_LENGTH_BYTES );
|
configASSERT( xExpectedSpace == mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
configASSERT( xMessageBufferIsEmpty( xMessageBuffer ) == pdTRUE );
|
configASSERT( xMessageBufferIsEmpty( xMessageBuffer ) == pdTRUE );
|
||||||
|
|
@ -218,7 +219,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xNextLength;
|
( void ) xNextLength;
|
||||||
|
|
||||||
/* Try sending more bytes than possible, first using the FromISR version, then
|
/* Try sending more bytes than possible, first using the FromISR version, then
|
||||||
with an infinite block time to ensure this task does not lock up. */
|
* with an infinite block time to ensure this task does not lock up. */
|
||||||
xReturned = xMessageBufferSendFromISR( xMessageBuffer, ( void * ) pucData, mbMESSAGE_BUFFER_LENGTH_BYTES + sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ), NULL );
|
xReturned = xMessageBufferSendFromISR( xMessageBuffer, ( void * ) pucData, mbMESSAGE_BUFFER_LENGTH_BYTES + sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ), NULL );
|
||||||
configASSERT( xReturned == ( size_t ) 0 );
|
configASSERT( xReturned == ( size_t ) 0 );
|
||||||
/* In case configASSERT() is not defined. */
|
/* In case configASSERT() is not defined. */
|
||||||
|
|
@ -229,22 +230,22 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xReturned;
|
( void ) xReturned;
|
||||||
|
|
||||||
/* The buffer is 50 bytes long. When an item is added to the buffer an
|
/* The buffer is 50 bytes long. When an item is added to the buffer an
|
||||||
additional 4 bytes are added to hold the item's size. That means adding
|
* additional 4 bytes are added to hold the item's size. That means adding
|
||||||
6 bytes to the buffer will actually add 10 bytes to the buffer. Therefore,
|
* 6 bytes to the buffer will actually add 10 bytes to the buffer. Therefore,
|
||||||
with a 50 byte buffer, a maximum of 5 6 bytes items can be added before the
|
* with a 50 byte buffer, a maximum of 5 6 bytes items can be added before the
|
||||||
buffer is completely full. NOTE: The numbers in this paragraph assume
|
* buffer is completely full. NOTE: The numbers in this paragraph assume
|
||||||
sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) == 4. */
|
* sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) == 4. */
|
||||||
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
||||||
{
|
{
|
||||||
configASSERT( xMessageBufferIsFull( xMessageBuffer ) == pdFALSE );
|
configASSERT( xMessageBufferIsFull( xMessageBuffer ) == pdFALSE );
|
||||||
|
|
||||||
/* Generate recognisable data to write to the buffer. This is just
|
/* Generate recognisable data to write to the buffer. This is just
|
||||||
ascii characters that shows which loop iteration the data was written
|
* ascii characters that shows which loop iteration the data was written
|
||||||
in. The 'FromISR' version is used to give it some exercise as a block
|
* in. The 'FromISR' version is used to give it some exercise as a block
|
||||||
time is not used. That requires the call to be in a critical section
|
* time is not used. That requires the call to be in a critical section
|
||||||
so this code can also run on FreeRTOS ports that do not support
|
* so this code can also run on FreeRTOS ports that do not support
|
||||||
interrupt nesting (and so don't have interrupt safe critical
|
* interrupt nesting (and so don't have interrupt safe critical
|
||||||
sections).*/
|
* sections).*/
|
||||||
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
|
|
@ -255,8 +256,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* The space in the buffer will have reduced by the amount of user data
|
/* The space in the buffer will have reduced by the amount of user data
|
||||||
written into the buffer and the amount of space used to store the length
|
* written into the buffer and the amount of space used to store the length
|
||||||
of the data written into the buffer. */
|
* of the data written into the buffer. */
|
||||||
xExpectedSpace -= ( x6ByteLength + mbBYTES_TO_STORE_MESSAGE_LENGTH );
|
xExpectedSpace -= ( x6ByteLength + mbBYTES_TO_STORE_MESSAGE_LENGTH );
|
||||||
xReturned = xMessageBufferSpaceAvailable( xMessageBuffer );
|
xReturned = xMessageBufferSpaceAvailable( xMessageBuffer );
|
||||||
configASSERT( xReturned == xExpectedSpace );
|
configASSERT( xReturned == xExpectedSpace );
|
||||||
|
|
@ -269,15 +270,15 @@ UBaseType_t uxOriginalPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the buffer should be full, and attempting to add anything will should
|
/* Now the buffer should be full, and attempting to add anything will should
|
||||||
fail. */
|
* fail. */
|
||||||
configASSERT( xMessageBufferIsFull( xMessageBuffer ) == pdTRUE );
|
configASSERT( xMessageBufferIsFull( xMessageBuffer ) == pdTRUE );
|
||||||
xReturned = xMessageBufferSend( xMessageBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), mbDONT_BLOCK );
|
xReturned = xMessageBufferSend( xMessageBuffer, ( void * ) pucData, sizeof( pucData[ 0 ] ), mbDONT_BLOCK );
|
||||||
configASSERT( xReturned == 0 );
|
configASSERT( xReturned == 0 );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Adding with a timeout should also fail after the appropriate time. The
|
/* Adding with a timeout should also fail after the appropriate time. The
|
||||||
priority is temporarily boosted in this part of the test to keep the
|
* priority is temporarily boosted in this part of the test to keep the
|
||||||
allowable margin to a minimum. */
|
* allowable margin to a minimum. */
|
||||||
uxOriginalPriority = uxTaskPriorityGet( NULL );
|
uxOriginalPriority = uxTaskPriorityGet( NULL );
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
xTimeBeforeCall = xTaskGetTickCount();
|
xTimeBeforeCall = xTaskGetTickCount();
|
||||||
|
|
@ -291,17 +292,16 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xTimeBeforeCall;
|
( void ) xTimeBeforeCall;
|
||||||
( void ) xTimeAfterCall;
|
( void ) xTimeAfterCall;
|
||||||
|
|
||||||
|
|
||||||
/* The buffer is now full of data in the form "000000", "111111", etc. Make
|
/* The buffer is now full of data in the form "000000", "111111", etc. Make
|
||||||
sure the data is read out as expected. */
|
* sure the data is read out as expected. */
|
||||||
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
||||||
{
|
{
|
||||||
/* Generate the data that is expected to be read out for this loop
|
/* Generate the data that is expected to be read out for this loop
|
||||||
iteration. */
|
* iteration. */
|
||||||
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
||||||
|
|
||||||
/* Try reading the message into a buffer that is too small. The message
|
/* Try reading the message into a buffer that is too small. The message
|
||||||
should remain in the buffer. */
|
* should remain in the buffer. */
|
||||||
xReturned = xMessageBufferReceive( xMessageBuffer, ( void * ) pucReadData, x6ByteLength - 1, mbDONT_BLOCK );
|
xReturned = xMessageBufferReceive( xMessageBuffer, ( void * ) pucReadData, x6ByteLength - 1, mbDONT_BLOCK );
|
||||||
configASSERT( xReturned == 0 );
|
configASSERT( xReturned == 0 );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -312,10 +312,10 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Read the next 6 bytes out. The 'FromISR' version is used to give it
|
/* Read the next 6 bytes out. The 'FromISR' version is used to give it
|
||||||
some exercise as a block time is not used. THa requires the code to be
|
* some exercise as a block time is not used. THa requires the code to be
|
||||||
in a critical section so this test can be run with FreeRTOS ports that
|
* in a critical section so this test can be run with FreeRTOS ports that
|
||||||
do not support interrupt nesting (and therefore don't have interrupt
|
* do not support interrupt nesting (and therefore don't have interrupt
|
||||||
safe critical sections). */
|
* safe critical sections). */
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
xReturned = xMessageBufferReceiveFromISR( xMessageBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
|
xReturned = xMessageBufferReceiveFromISR( xMessageBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
|
||||||
|
|
@ -328,8 +328,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
|
configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
|
||||||
|
|
||||||
/* The space in the buffer will have increased by the amount of user
|
/* The space in the buffer will have increased by the amount of user
|
||||||
data read from into the buffer and the amount of space used to store the
|
* data read from into the buffer and the amount of space used to store the
|
||||||
length of the data read into the buffer. */
|
* length of the data read into the buffer. */
|
||||||
xExpectedSpace += ( x6ByteLength + mbBYTES_TO_STORE_MESSAGE_LENGTH );
|
xExpectedSpace += ( x6ByteLength + mbBYTES_TO_STORE_MESSAGE_LENGTH );
|
||||||
xReturned = xMessageBufferSpaceAvailable( xMessageBuffer );
|
xReturned = xMessageBufferSpaceAvailable( xMessageBuffer );
|
||||||
configASSERT( xReturned == xExpectedSpace );
|
configASSERT( xReturned == xExpectedSpace );
|
||||||
|
|
@ -347,8 +347,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
|
|
||||||
|
|
||||||
/* Reading with a timeout should also fail after the appropriate time. The
|
/* Reading with a timeout should also fail after the appropriate time. The
|
||||||
priority is temporarily boosted in this part of the test to keep the
|
* priority is temporarily boosted in this part of the test to keep the
|
||||||
allowable margin to a minimum. */
|
* allowable margin to a minimum. */
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
xTimeBeforeCall = xTaskGetTickCount();
|
xTimeBeforeCall = xTaskGetTickCount();
|
||||||
xReturned = xMessageBufferReceive( xMessageBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
|
xReturned = xMessageBufferReceive( xMessageBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
|
||||||
|
|
@ -363,19 +363,19 @@ UBaseType_t uxOriginalPriority;
|
||||||
|
|
||||||
|
|
||||||
/* In the next loop 17 bytes are written to then read out on each iteration.
|
/* In the next loop 17 bytes are written to then read out on each iteration.
|
||||||
The expected length variable is always used after 17 bytes have been written
|
* The expected length variable is always used after 17 bytes have been written
|
||||||
into the buffer - the length of the message is also written, making a total
|
* into the buffer - the length of the message is also written, making a total
|
||||||
of 21 bytes consumed for each 17 byte message. */
|
* of 21 bytes consumed for each 17 byte message. */
|
||||||
xExpectedSpace = mbMESSAGE_BUFFER_LENGTH_BYTES - ( x17ByteLength + mbBYTES_TO_STORE_MESSAGE_LENGTH );
|
xExpectedSpace = mbMESSAGE_BUFFER_LENGTH_BYTES - ( x17ByteLength + mbBYTES_TO_STORE_MESSAGE_LENGTH );
|
||||||
|
|
||||||
/* Reading and writing 17 bytes at a time will result in 21 bytes being
|
/* Reading and writing 17 bytes at a time will result in 21 bytes being
|
||||||
written into the buffer, and as 50 is not divisible by 21, writing multiple
|
* written into the buffer, and as 50 is not divisible by 21, writing multiple
|
||||||
times will cause the data to wrap in the buffer.*/
|
* times will cause the data to wrap in the buffer.*/
|
||||||
for( xItem = 0; xItem < 100; xItem++ )
|
for( xItem = 0; xItem < 100; xItem++ )
|
||||||
{
|
{
|
||||||
/* Generate recognisable data to write to the queue. This is just
|
/* Generate recognisable data to write to the queue. This is just
|
||||||
ascii characters that shows which loop iteration the data was written
|
* ascii characters that shows which loop iteration the data was written
|
||||||
in. */
|
* in. */
|
||||||
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
|
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
|
||||||
xReturned = xMessageBufferSend( xMessageBuffer, ( void * ) pucData, x17ByteLength, mbDONT_BLOCK );
|
xReturned = xMessageBufferSend( xMessageBuffer, ( void * ) pucData, x17ByteLength, mbDONT_BLOCK );
|
||||||
configASSERT( xReturned == x17ByteLength );
|
configASSERT( xReturned == x17ByteLength );
|
||||||
|
|
@ -387,8 +387,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* The space in the buffer will have reduced by the amount of user data
|
/* The space in the buffer will have reduced by the amount of user data
|
||||||
written into the buffer and the amount of space used to store the length
|
* written into the buffer and the amount of space used to store the length
|
||||||
of the data written into the buffer. */
|
* of the data written into the buffer. */
|
||||||
xReturned = xMessageBufferSpaceAvailable( xMessageBuffer );
|
xReturned = xMessageBufferSpaceAvailable( xMessageBuffer );
|
||||||
configASSERT( xReturned == xExpectedSpace );
|
configASSERT( xReturned == xExpectedSpace );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -402,7 +402,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x17ByteLength ) == 0 );
|
configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x17ByteLength ) == 0 );
|
||||||
|
|
||||||
/* Don't expect any messages to be available as the data was read out
|
/* Don't expect any messages to be available as the data was read out
|
||||||
again. */
|
* again. */
|
||||||
xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer );
|
xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer );
|
||||||
configASSERT( xNextLength == 0 );
|
configASSERT( xNextLength == 0 );
|
||||||
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -414,15 +414,15 @@ UBaseType_t uxOriginalPriority;
|
||||||
configASSERT( xExpectedSpace == mbMESSAGE_BUFFER_LENGTH_BYTES );
|
configASSERT( xExpectedSpace == mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
|
|
||||||
/* Cannot write within sizeof( size_t ) (assumed to be 4 bytes in this test)
|
/* Cannot write within sizeof( size_t ) (assumed to be 4 bytes in this test)
|
||||||
bytes of the full 50 bytes, as that would not leave space for the four bytes
|
* bytes of the full 50 bytes, as that would not leave space for the four bytes
|
||||||
taken by the data length. */
|
* taken by the data length. */
|
||||||
xReturned = xMessageBufferSend( xMessageBuffer, ( const void * ) pc55ByteString, mbMESSAGE_BUFFER_LENGTH_BYTES, mbDONT_BLOCK );
|
xReturned = xMessageBufferSend( xMessageBuffer, ( const void * ) pc55ByteString, mbMESSAGE_BUFFER_LENGTH_BYTES, mbDONT_BLOCK );
|
||||||
configASSERT( xReturned == 0 );
|
configASSERT( xReturned == 0 );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
#ifndef configMESSAGE_BUFFER_LENGTH_TYPE
|
#ifndef configMESSAGE_BUFFER_LENGTH_TYPE
|
||||||
{
|
{
|
||||||
/* The following will fail if configMESSAGE_BUFFER_LENGTH_TYPE is set
|
/* The following will fail if configMESSAGE_BUFFER_LENGTH_TYPE is set
|
||||||
to a non 32-bit type. */
|
* to a non 32-bit type. */
|
||||||
xReturned = xMessageBufferSend( xMessageBuffer, ( const void * ) pc55ByteString, mbMESSAGE_BUFFER_LENGTH_BYTES - 1, mbDONT_BLOCK );
|
xReturned = xMessageBufferSend( xMessageBuffer, ( const void * ) pc55ByteString, mbMESSAGE_BUFFER_LENGTH_BYTES - 1, mbDONT_BLOCK );
|
||||||
configASSERT( xReturned == 0 );
|
configASSERT( xReturned == 0 );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -433,10 +433,10 @@ UBaseType_t uxOriginalPriority;
|
||||||
configASSERT( xReturned == 0 );
|
configASSERT( xReturned == 0 );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* ifndef configMESSAGE_BUFFER_LENGTH_TYPE */
|
||||||
|
|
||||||
/* Don't expect any messages to be available as the above were too large to
|
/* Don't expect any messages to be available as the above were too large to
|
||||||
get written. */
|
* get written. */
|
||||||
xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer );
|
xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer );
|
||||||
configASSERT( xNextLength == 0 );
|
configASSERT( xNextLength == 0 );
|
||||||
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
( void ) xNextLength; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -468,12 +468,13 @@ const int32_t iMaxValue = 1500;
|
||||||
char cTxString[ 12 ]; /* Large enough to hold a 32 number in ASCII. */
|
char cTxString[ 12 ]; /* Large enough to hold a 32 number in ASCII. */
|
||||||
|
|
||||||
/* In this case the message buffer has already been created and is passed
|
/* In this case the message buffer has already been created and is passed
|
||||||
into the task using the task's parameter. */
|
* into the task using the task's parameter. */
|
||||||
|
|
||||||
xMessageBuffer = ( MessageBufferHandle_t ) pvParameters;
|
xMessageBuffer = ( MessageBufferHandle_t ) pvParameters;
|
||||||
|
|
||||||
/* Create a string from an incrementing number. The length of the
|
/* Create a string from an incrementing number. The length of the
|
||||||
string will increase and decrease as the value of the number increases
|
* string will increase and decrease as the value of the number increases
|
||||||
then overflows. */
|
* then overflows. */
|
||||||
memset( cTxString, 0x00, sizeof( cTxString ) );
|
memset( cTxString, 0x00, sizeof( cTxString ) );
|
||||||
sprintf( cTxString, "%d", ( int ) iDataToSend );
|
sprintf( cTxString, "%d", ( int ) iDataToSend );
|
||||||
xStringLength = strlen( cTxString );
|
xStringLength = strlen( cTxString );
|
||||||
|
|
@ -481,7 +482,7 @@ char cTxString[ 12 ]; /* Large enough to hold a 32 number in ASCII. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Doesn't block so calls can interleave with the non-blocking
|
/* Doesn't block so calls can interleave with the non-blocking
|
||||||
receives performed by prvNonBlockingReceiverTask(). */
|
* receives performed by prvNonBlockingReceiverTask(). */
|
||||||
if( xMessageBufferSend( xMessageBuffer, ( void * ) cTxString, strlen( cTxString ), mbDONT_BLOCK ) == xStringLength )
|
if( xMessageBufferSend( xMessageBuffer, ( void * ) cTxString, strlen( cTxString ), mbDONT_BLOCK ) == xStringLength )
|
||||||
{
|
{
|
||||||
iDataToSend++;
|
iDataToSend++;
|
||||||
|
|
@ -489,7 +490,7 @@ char cTxString[ 12 ]; /* Large enough to hold a 32 number in ASCII. */
|
||||||
if( iDataToSend > iMaxValue )
|
if( iDataToSend > iMaxValue )
|
||||||
{
|
{
|
||||||
/* The value sent is reset back to 0 to ensure the string being sent
|
/* The value sent is reset back to 0 to ensure the string being sent
|
||||||
does not remain at the same length for too long. */
|
* does not remain at the same length for too long. */
|
||||||
iDataToSend = 0;
|
iDataToSend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,13 +514,13 @@ char cExpectedString[ 12 ]; /* Large enough to hold a 32 number in ASCII. */
|
||||||
char cRxString[ 12 ];
|
char cRxString[ 12 ];
|
||||||
|
|
||||||
/* In this case the message buffer has already been created and is passed
|
/* In this case the message buffer has already been created and is passed
|
||||||
into the task using the task's parameter. */
|
* into the task using the task's parameter. */
|
||||||
xMessageBuffer = ( MessageBufferHandle_t ) pvParameters;
|
xMessageBuffer = ( MessageBufferHandle_t ) pvParameters;
|
||||||
|
|
||||||
/* Create a string from an incrementing number. The length of the
|
/* Create a string from an incrementing number. The length of the
|
||||||
string will increase and decrease as the value of the number increases
|
* string will increase and decrease as the value of the number increases
|
||||||
then overflows. This should always match the string sent to the buffer by
|
* then overflows. This should always match the string sent to the buffer by
|
||||||
the non blocking sender task. */
|
* the non blocking sender task. */
|
||||||
memset( cExpectedString, 0x00, sizeof( cExpectedString ) );
|
memset( cExpectedString, 0x00, sizeof( cExpectedString ) );
|
||||||
memset( cRxString, 0x00, sizeof( cRxString ) );
|
memset( cRxString, 0x00, sizeof( cRxString ) );
|
||||||
sprintf( cExpectedString, "%d", ( int ) iDataToSend );
|
sprintf( cExpectedString, "%d", ( int ) iDataToSend );
|
||||||
|
|
@ -528,11 +529,11 @@ char cRxString[ 12 ];
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Doesn't block so calls can interleave with the non-blocking
|
/* Doesn't block so calls can interleave with the non-blocking
|
||||||
receives performed by prvNonBlockingReceiverTask(). */
|
* receives performed by prvNonBlockingReceiverTask(). */
|
||||||
xReceiveLength = xMessageBufferReceive( xMessageBuffer, ( void * ) cRxString, sizeof( cRxString ), mbDONT_BLOCK );
|
xReceiveLength = xMessageBufferReceive( xMessageBuffer, ( void * ) cRxString, sizeof( cRxString ), mbDONT_BLOCK );
|
||||||
|
|
||||||
/* Should only ever receive no data is available, or the expected
|
/* Should only ever receive no data is available, or the expected
|
||||||
length of data is available. */
|
* length of data is available. */
|
||||||
if( ( xReceiveLength != 0 ) && ( xReceiveLength != xStringLength ) )
|
if( ( xReceiveLength != 0 ) && ( xReceiveLength != xStringLength ) )
|
||||||
{
|
{
|
||||||
xNonBlockingReceiveError = pdTRUE;
|
xNonBlockingReceiveError = pdTRUE;
|
||||||
|
|
@ -541,7 +542,7 @@ char cRxString[ 12 ];
|
||||||
if( xReceiveLength == xStringLength )
|
if( xReceiveLength == xStringLength )
|
||||||
{
|
{
|
||||||
/* Ensure the received data was that expected, then generate the
|
/* Ensure the received data was that expected, then generate the
|
||||||
next expected string. */
|
* next expected string. */
|
||||||
if( strcmp( cRxString, cExpectedString ) != 0 )
|
if( strcmp( cRxString, cExpectedString ) != 0 )
|
||||||
{
|
{
|
||||||
xNonBlockingReceiveError = pdTRUE;
|
xNonBlockingReceiveError = pdTRUE;
|
||||||
|
|
@ -552,7 +553,7 @@ char cRxString[ 12 ];
|
||||||
if( iDataToSend > iMaxValue )
|
if( iDataToSend > iMaxValue )
|
||||||
{
|
{
|
||||||
/* The value sent is reset back to 0 to ensure the string being sent
|
/* The value sent is reset back to 0 to ensure the string being sent
|
||||||
does not remain at the same length for too long. */
|
* does not remain at the same length for too long. */
|
||||||
iDataToSend = 0;
|
iDataToSend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -564,7 +565,7 @@ char cRxString[ 12 ];
|
||||||
if( xNonBlockingReceiveError == pdFALSE )
|
if( xNonBlockingReceiveError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* No errors detected so increment the counter that lets the
|
/* No errors detected so increment the counter that lets the
|
||||||
check task know this test is still functioning correctly. */
|
* check task know this test is still functioning correctly. */
|
||||||
ulNonBlockingRxCounter++;
|
ulNonBlockingRxCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -586,11 +587,11 @@ char cRxString[ 12 ];
|
||||||
|
|
||||||
|
|
||||||
/* The task's priority is used as an index into the loop counters used to
|
/* The task's priority is used as an index into the loop counters used to
|
||||||
indicate this task is still running. */
|
* indicate this task is still running. */
|
||||||
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
/* Make sure a change in priority does not inadvertently result in an
|
/* Make sure a change in priority does not inadvertently result in an
|
||||||
invalid array index. */
|
* invalid array index. */
|
||||||
configASSERT( uxIndex < mbNUMBER_OF_ECHO_CLIENTS );
|
configASSERT( uxIndex < mbNUMBER_OF_ECHO_CLIENTS );
|
||||||
|
|
||||||
/* Avoid compiler warnings about unused parameters. */
|
/* Avoid compiler warnings about unused parameters. */
|
||||||
|
|
@ -601,13 +602,13 @@ char cRxString[ 12 ];
|
||||||
&( xStaticMessageBuffers[ uxIndex ] ) ); /* The static message buffer structure to use within the array. */
|
&( xStaticMessageBuffers[ uxIndex ] ) ); /* The static message buffer structure to use within the array. */
|
||||||
|
|
||||||
/* Now the message buffer has been created the receiver task can be created.
|
/* Now the message buffer has been created the receiver task can be created.
|
||||||
If this sender task has the higher priority then the receiver task is
|
* If this sender task has the higher priority then the receiver task is
|
||||||
created at the lower priority - if this sender task has the lower priority
|
* created at the lower priority - if this sender task has the lower priority
|
||||||
then the receiver task is created at the higher priority. */
|
* then the receiver task is created at the higher priority. */
|
||||||
if( uxTaskPriorityGet( NULL ) == mbLOWER_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == mbLOWER_PRIORITY )
|
||||||
{
|
{
|
||||||
/* Here prvSingleTaskTests() performs various tests on a message buffer
|
/* Here prvSingleTaskTests() performs various tests on a message buffer
|
||||||
that was created statically. */
|
* that was created statically. */
|
||||||
prvSingleTaskTests( xMessageBuffer );
|
prvSingleTaskTests( xMessageBuffer );
|
||||||
xTaskCreate( prvReceiverTask, "MsgReceiver", xBlockingStackSize, ( void * ) xMessageBuffer, mbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvReceiverTask, "MsgReceiver", xBlockingStackSize, ( void * ) xMessageBuffer, mbHIGHER_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -619,8 +620,8 @@ char cRxString[ 12 ];
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Create a string from an incrementing number. The length of the
|
/* Create a string from an incrementing number. The length of the
|
||||||
string will increase and decrease as the value of the number increases
|
* string will increase and decrease as the value of the number increases
|
||||||
then overflows. */
|
* then overflows. */
|
||||||
memset( cTxString, 0x00, sizeof( cTxString ) );
|
memset( cTxString, 0x00, sizeof( cTxString ) );
|
||||||
sprintf( cTxString, "%d", ( int ) iDataToSend );
|
sprintf( cTxString, "%d", ( int ) iDataToSend );
|
||||||
|
|
||||||
|
|
@ -634,7 +635,7 @@ char cRxString[ 12 ];
|
||||||
if( ( iDataToSend % iSendsBetweenIncrements ) == 0 )
|
if( ( iDataToSend % iSendsBetweenIncrements ) == 0 )
|
||||||
{
|
{
|
||||||
/* Increment a loop counter so a check task can tell this task is
|
/* Increment a loop counter so a check task can tell this task is
|
||||||
still running as expected. */
|
* still running as expected. */
|
||||||
ulSenderLoopCounters[ uxIndex ]++;
|
ulSenderLoopCounters[ uxIndex ]++;
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) == mbHIGHER_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == mbHIGHER_PRIORITY )
|
||||||
|
|
@ -644,10 +645,10 @@ char cRxString[ 12 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This message buffer is just created and deleted to ensure no
|
/* This message buffer is just created and deleted to ensure no
|
||||||
issues when attempting to delete a message buffer that was
|
* issues when attempting to delete a message buffer that was
|
||||||
created using statically allocated memory. To save stack space
|
* created using statically allocated memory. To save stack space
|
||||||
the buffer is set to point to the cTxString array - this is
|
* the buffer is set to point to the cTxString array - this is
|
||||||
ok because nothing is actually written to the memory. */
|
* ok because nothing is actually written to the memory. */
|
||||||
xTempMessageBuffer = xMessageBufferCreateStatic( sizeof( cTxString ), ( uint8_t * ) cTxString, &xStaticMessageBuffer );
|
xTempMessageBuffer = xMessageBufferCreateStatic( sizeof( cTxString ), ( uint8_t * ) cTxString, &xStaticMessageBuffer );
|
||||||
vMessageBufferDelete( xTempMessageBuffer );
|
vMessageBufferDelete( xTempMessageBuffer );
|
||||||
}
|
}
|
||||||
|
|
@ -680,7 +681,6 @@ char cRxString[ 12 ];
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
xReceivedBytes = xMessageBufferReceive( pxMessageBuffer, ( void * ) cReceivedString, sizeof( cExpectedString ), xTicksToWait );
|
xReceivedBytes = xMessageBufferReceive( pxMessageBuffer, ( void * ) cReceivedString, sizeof( cExpectedString ), xTicksToWait );
|
||||||
|
|
||||||
} while( xReceivedBytes == 0 );
|
} while( xReceivedBytes == 0 );
|
||||||
|
|
||||||
/* Ensure the received string matches the expected string. */
|
/* Ensure the received string matches the expected string. */
|
||||||
|
|
@ -700,19 +700,19 @@ char *pcStringToSend, *pcStringReceived, cNextChar = mbASCII_SPACE;
|
||||||
const TickType_t xTicksToWait = pdMS_TO_TICKS( 50 );
|
const TickType_t xTicksToWait = pdMS_TO_TICKS( 50 );
|
||||||
|
|
||||||
/* The task's priority is used as an index into the loop counters used to
|
/* The task's priority is used as an index into the loop counters used to
|
||||||
indicate this task is still running. */
|
* indicate this task is still running. */
|
||||||
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
/* Pointers to the client and server message buffers are passed into this task
|
/* Pointers to the client and server message buffers are passed into this task
|
||||||
using the task's parameter. */
|
* using the task's parameter. */
|
||||||
EchoMessageBuffers_t * pxMessageBuffers = ( EchoMessageBuffers_t * ) pvParameters;
|
EchoMessageBuffers_t * pxMessageBuffers = ( EchoMessageBuffers_t * ) pvParameters;
|
||||||
|
|
||||||
/* Prevent compiler warnings. */
|
/* Prevent compiler warnings. */
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create the buffer into which strings to send to the server will be
|
/* Create the buffer into which strings to send to the server will be
|
||||||
created, and the buffer into which strings echoed back from the server will
|
* created, and the buffer into which strings echoed back from the server will
|
||||||
be copied. */
|
* be copied. */
|
||||||
pcStringToSend = ( char * ) pvPortMalloc( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
pcStringToSend = ( char * ) pvPortMalloc( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
pcStringReceived = ( char * ) pvPortMalloc( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
pcStringReceived = ( char * ) pvPortMalloc( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
|
|
||||||
|
|
@ -725,18 +725,18 @@ EchoMessageBuffers_t *pxMessageBuffers = ( EchoMessageBuffers_t * ) pvParameters
|
||||||
xSendLength++;
|
xSendLength++;
|
||||||
|
|
||||||
/* The message buffer is being used to hold variable length data, so
|
/* The message buffer is being used to hold variable length data, so
|
||||||
each data item requires sizeof( size_t ) bytes to hold the data's
|
* each data item requires sizeof( size_t ) bytes to hold the data's
|
||||||
length, hence the sizeof() in the if() condition below. */
|
* length, hence the sizeof() in the if() condition below. */
|
||||||
if( xSendLength > ( mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
|
if( xSendLength > ( mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
|
||||||
{
|
{
|
||||||
/* Back to a string length of 1. */
|
/* Back to a string length of 1. */
|
||||||
xSendLength = sizeof( char );
|
xSendLength = sizeof( char );
|
||||||
|
|
||||||
/* Maintain a count of the number of times this code executes so a
|
/* Maintain a count of the number of times this code executes so a
|
||||||
check task can determine if this task is still functioning as
|
* check task can determine if this task is still functioning as
|
||||||
expected or not. As there are two client tasks, and the priorities
|
* expected or not. As there are two client tasks, and the priorities
|
||||||
used are 0 and 1, the task's priority is used as an index into the
|
* used are 0 and 1, the task's priority is used as an index into the
|
||||||
loop count array. */
|
* loop count array. */
|
||||||
ulEchoLoopCounters[ uxIndex ]++;
|
ulEchoLoopCounters[ uxIndex ]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -763,7 +763,6 @@ EchoMessageBuffers_t *pxMessageBuffers = ( EchoMessageBuffers_t * ) pvParameters
|
||||||
{
|
{
|
||||||
mtCOVERAGE_TEST_MARKER();
|
mtCOVERAGE_TEST_MARKER();
|
||||||
}
|
}
|
||||||
|
|
||||||
} while( ux == 0 );
|
} while( ux == 0 );
|
||||||
|
|
||||||
/* Wait for the string to be echoed back. */
|
/* Wait for the string to be echoed back. */
|
||||||
|
|
@ -788,8 +787,8 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create the message buffer used to send data from the client to the server,
|
/* Create the message buffer used to send data from the client to the server,
|
||||||
and the message buffer used to echo the data from the server back to the
|
* and the message buffer used to echo the data from the server back to the
|
||||||
client. */
|
* client. */
|
||||||
xMessageBuffers.xEchoClientBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
xMessageBuffers.xEchoClientBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
xMessageBuffers.xEchoServerBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
xMessageBuffers.xEchoServerBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
configASSERT( xMessageBuffers.xEchoClientBuffer );
|
configASSERT( xMessageBuffers.xEchoClientBuffer );
|
||||||
|
|
@ -807,9 +806,9 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
|
||||||
( void ) xTimeOnEntering; /* In case configASSERT() is not defined. */
|
( void ) xTimeOnEntering; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Now the message buffers have been created the echo client task can be
|
/* Now the message buffers have been created the echo client task can be
|
||||||
created. If this server task has the higher priority then the client task
|
* created. If this server task has the higher priority then the client task
|
||||||
is created at the lower priority - if this server task has the lower
|
* is created at the lower priority - if this server task has the lower
|
||||||
priority then the client task is created at the higher priority. */
|
* priority then the client task is created at the higher priority. */
|
||||||
if( uxTaskPriorityGet( NULL ) == mbLOWER_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == mbLOWER_PRIORITY )
|
||||||
{
|
{
|
||||||
xTaskCreate( prvEchoClient, "EchoClient", configMINIMAL_STACK_SIZE, ( void * ) &xMessageBuffers, mbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvEchoClient, "EchoClient", configMINIMAL_STACK_SIZE, ( void * ) &xMessageBuffers, mbHIGHER_PRIORITY, NULL );
|
||||||
|
|
@ -817,7 +816,7 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Here prvSingleTaskTests() performs various tests on a message buffer
|
/* Here prvSingleTaskTests() performs various tests on a message buffer
|
||||||
that was created dynamically. */
|
* that was created dynamically. */
|
||||||
prvSingleTaskTests( xMessageBuffers.xEchoClientBuffer );
|
prvSingleTaskTests( xMessageBuffers.xEchoClientBuffer );
|
||||||
xTaskCreate( prvEchoClient, "EchoClient", configMINIMAL_STACK_SIZE, ( void * ) &xMessageBuffers, mbLOWER_PRIORITY, NULL );
|
xTaskCreate( prvEchoClient, "EchoClient", configMINIMAL_STACK_SIZE, ( void * ) &xMessageBuffers, mbLOWER_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -836,7 +835,7 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
|
||||||
xMessageBufferSend( xMessageBuffers.xEchoServerBuffer, ( void * ) pcReceivedString, xReceivedLength, portMAX_DELAY );
|
xMessageBufferSend( xMessageBuffers.xEchoServerBuffer, ( void * ) pcReceivedString, xReceivedLength, portMAX_DELAY );
|
||||||
|
|
||||||
/* This message buffer is just created and deleted to ensure no memory
|
/* This message buffer is just created and deleted to ensure no memory
|
||||||
leaks. */
|
* leaks. */
|
||||||
xTempMessageBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
xTempMessageBuffer = xMessageBufferCreate( mbMESSAGE_BUFFER_LENGTH_BYTES );
|
||||||
vMessageBufferDelete( xTempMessageBuffer );
|
vMessageBufferDelete( xTempMessageBuffer );
|
||||||
}
|
}
|
||||||
|
|
@ -859,12 +858,12 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Add bytes to the buffer so the other task should see
|
/* Add bytes to the buffer so the other task should see
|
||||||
mbEXPECTED_FREE_BYTES_AFTER_WRITING_STRING bytes free. */
|
* mbEXPECTED_FREE_BYTES_AFTER_WRITING_STRING bytes free. */
|
||||||
xMessageBufferSend( xCoherenceTestMessageBuffer, ( void * ) cTxString, strlen( cTxString ), 0 );
|
xMessageBufferSend( xCoherenceTestMessageBuffer, ( void * ) cTxString, strlen( cTxString ), 0 );
|
||||||
configASSERT( xMessageBufferSpacesAvailable( xCoherenceTestMessageBuffer ) == mbEXPECTED_FREE_BYTES_AFTER_WRITING_STRING );
|
configASSERT( xMessageBufferSpacesAvailable( xCoherenceTestMessageBuffer ) == mbEXPECTED_FREE_BYTES_AFTER_WRITING_STRING );
|
||||||
|
|
||||||
/* Read out message again so the other task should read the full
|
/* Read out message again so the other task should read the full
|
||||||
mbCOHERENCE_TEST_BUFFER_SIZE bytes free again. */
|
* mbCOHERENCE_TEST_BUFFER_SIZE bytes free again. */
|
||||||
memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) );
|
memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) );
|
||||||
xMessageBufferReceive( xCoherenceTestMessageBuffer, ( void * ) cRxString, mbCOHERENCE_TEST_BYTES_WRITTEN, 0 );
|
xMessageBufferReceive( xCoherenceTestMessageBuffer, ( void * ) cRxString, mbCOHERENCE_TEST_BYTES_WRITTEN, 0 );
|
||||||
configASSERT( strcmp( cTxString, cRxString ) == 0 );
|
configASSERT( strcmp( cTxString, cRxString ) == 0 );
|
||||||
|
|
@ -882,15 +881,15 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 250UL );
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* This message buffer is only ever empty or contains 5 bytes. So all
|
/* This message buffer is only ever empty or contains 5 bytes. So all
|
||||||
queries of its free space should result in one of the two values tested
|
* queries of its free space should result in one of the two values tested
|
||||||
below. */
|
* below. */
|
||||||
xSpaceAvailable = xMessageBufferSpacesAvailable( xCoherenceTestMessageBuffer );
|
xSpaceAvailable = xMessageBufferSpacesAvailable( xCoherenceTestMessageBuffer );
|
||||||
|
|
||||||
if( ( xSpaceAvailable == mbCOHERENCE_TEST_BUFFER_SIZE ) ||
|
if( ( xSpaceAvailable == mbCOHERENCE_TEST_BUFFER_SIZE ) ||
|
||||||
( xSpaceAvailable == mbEXPECTED_FREE_BYTES_AFTER_WRITING_STRING ) )
|
( xSpaceAvailable == mbEXPECTED_FREE_BYTES_AFTER_WRITING_STRING ) )
|
||||||
{
|
{
|
||||||
/* Only continue to increment the variable that shows this task
|
/* Only continue to increment the variable that shows this task
|
||||||
is still executing if no errors have been found. */
|
* is still executing if no errors have been found. */
|
||||||
if( xErrorFound == pdFALSE )
|
if( xErrorFound == pdFALSE )
|
||||||
{
|
{
|
||||||
ulSizeCoherencyTestCycles++;
|
ulSizeCoherencyTestCycles++;
|
||||||
|
|
@ -966,10 +965,8 @@ BaseType_t xReturn = pdPASS, x;
|
||||||
ullastSizeCoherencyTestCycles = ulSizeCoherencyTestCycles;
|
ullastSizeCoherencyTestCycles = ulSizeCoherencyTestCycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configRUN_ADDITIONAL_TESTS == 1 ) */
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Changes from V2.0.0
|
* Changes from V2.0.0
|
||||||
|
*
|
||||||
+ Delay periods are now specified using variables and constants of
|
+ Delay periods are now specified using variables and constants of
|
||||||
TickType_t rather than uint32_t.
|
+ TickType_t rather than uint32_t.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -80,7 +80,7 @@ static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters );
|
static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters );
|
||||||
|
|
||||||
/* Variables that are used to check that the tasks are still running with no
|
/* Variables that are used to check that the tasks are still running with no
|
||||||
errors. */
|
* errors. */
|
||||||
static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE;
|
static volatile BaseType_t xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -95,11 +95,11 @@ static QueueHandle_t xPolledQueue;
|
||||||
if( xPolledQueue != NULL )
|
if( xPolledQueue != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
* in use. The queue registry is provided as a means for kernel aware
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
* debuggers to locate queues and has no purpose if a kernel aware debugger
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
* is not being used. The call to vQueueAddToRegistry() will be removed
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
* by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
||||||
defined to be less than 1. */
|
* defined to be less than 1. */
|
||||||
vQueueAddToRegistry( xPolledQueue, "Poll_Test_Queue" );
|
vQueueAddToRegistry( xPolledQueue, "Poll_Test_Queue" );
|
||||||
|
|
||||||
/* Spawn the producer and consumer. */
|
/* Spawn the producer and consumer. */
|
||||||
|
|
@ -122,7 +122,7 @@ BaseType_t xError = pdFALSE, xLoop;
|
||||||
if( xQueueSend( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS )
|
if( xQueueSend( *( ( QueueHandle_t * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We should never find the queue full so if we get here there
|
/* We should never find the queue full so if we get here there
|
||||||
has been an error. */
|
* has been an error. */
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -130,7 +130,7 @@ BaseType_t xError = pdFALSE, xLoop;
|
||||||
if( xError == pdFALSE )
|
if( xError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If an error has ever been recorded we stop incrementing the
|
/* If an error has ever been recorded we stop incrementing the
|
||||||
check variable. */
|
* check variable. */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
xPollingProducerCount++;
|
xPollingProducerCount++;
|
||||||
portEXIT_CRITICAL();
|
portEXIT_CRITICAL();
|
||||||
|
|
@ -142,7 +142,7 @@ BaseType_t xError = pdFALSE, xLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait before we start posting again to ensure the consumer runs and
|
/* Wait before we start posting again to ensure the consumer runs and
|
||||||
empties the queue. */
|
* empties the queue. */
|
||||||
vTaskDelay( pollqPRODUCER_DELAY );
|
vTaskDelay( pollqPRODUCER_DELAY );
|
||||||
}
|
}
|
||||||
} /*lint !e818 Function prototype must conform to API. */
|
} /*lint !e818 Function prototype must conform to API. */
|
||||||
|
|
@ -163,11 +163,11 @@ BaseType_t xError = pdFALSE;
|
||||||
if( usData != usExpectedValue )
|
if( usData != usExpectedValue )
|
||||||
{
|
{
|
||||||
/* This is not what we expected to receive so an error has
|
/* This is not what we expected to receive so an error has
|
||||||
occurred. */
|
* occurred. */
|
||||||
xError = pdTRUE;
|
xError = pdTRUE;
|
||||||
|
|
||||||
/* Catch-up to the value we received so our next expected
|
/* Catch-up to the value we received so our next expected
|
||||||
value should again be correct. */
|
* value should again be correct. */
|
||||||
usExpectedValue = usData;
|
usExpectedValue = usData;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -175,7 +175,7 @@ BaseType_t xError = pdFALSE;
|
||||||
if( xError == pdFALSE )
|
if( xError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* Only increment the check variable if no errors have
|
/* Only increment the check variable if no errors have
|
||||||
occurred. */
|
* occurred. */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
xPollingConsumerCount++;
|
xPollingConsumerCount++;
|
||||||
portEXIT_CRITICAL();
|
portEXIT_CRITICAL();
|
||||||
|
|
@ -188,7 +188,7 @@ BaseType_t xError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the queue is empty we block, allowing the producer to place more
|
/* Now the queue is empty we block, allowing the producer to place more
|
||||||
items in the queue. */
|
* items in the queue. */
|
||||||
vTaskDelay( pollqCONSUMER_DELAY );
|
vTaskDelay( pollqCONSUMER_DELAY );
|
||||||
}
|
}
|
||||||
} /*lint !e818 Function prototype must conform to API. */
|
} /*lint !e818 Function prototype must conform to API. */
|
||||||
|
|
@ -200,9 +200,9 @@ BaseType_t xArePollingQueuesStillRunning( void )
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
|
|
||||||
/* Check both the consumer and producer poll count to check they have both
|
/* Check both the consumer and producer poll count to check they have both
|
||||||
been changed since out last trip round. We do not need a critical section
|
* been changed since out last trip round. We do not need a critical section
|
||||||
around the check variables as this is called from a higher priority than
|
* around the check variables as this is called from a higher priority than
|
||||||
the other tasks that access the same variables. */
|
* the other tasks that access the same variables. */
|
||||||
if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) ||
|
if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) ||
|
||||||
( xPollingProducerCount == pollqINITIAL_VALUE )
|
( xPollingProducerCount == pollqINITIAL_VALUE )
|
||||||
)
|
)
|
||||||
|
|
@ -215,7 +215,7 @@ BaseType_t xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the check variables back down so we know if they have been
|
/* Set the check variables back down so we know if they have been
|
||||||
incremented the next time around. */
|
* incremented the next time around. */
|
||||||
xPollingConsumerCount = pollqINITIAL_VALUE;
|
xPollingConsumerCount = pollqINITIAL_VALUE;
|
||||||
xPollingProducerCount = pollqINITIAL_VALUE;
|
xPollingProducerCount = pollqINITIAL_VALUE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,11 @@ static void prvHighestPriorityPeekTask( void *pvParameters );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
detected in any of the tasks. */
|
* detected in any of the tasks. */
|
||||||
static volatile BaseType_t xErrorDetected = pdFALSE;
|
static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
/* Counter that is incremented on each cycle of a test. This is used to
|
/* Counter that is incremented on each cycle of a test. This is used to
|
||||||
detect a stalled task - a test that is no longer running. */
|
* detect a stalled task - a test that is no longer running. */
|
||||||
static volatile uint32_t ulLoopCounter = 0;
|
static volatile uint32_t ulLoopCounter = 0;
|
||||||
|
|
||||||
/* Handles to the test tasks. */
|
/* Handles to the test tasks. */
|
||||||
|
|
@ -88,16 +88,16 @@ QueueHandle_t xQueue;
|
||||||
if( xQueue != NULL )
|
if( xQueue != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
* in use. The queue registry is provided as a means for kernel aware
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
* debuggers to locate queues and has no purpose if a kernel aware debugger
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
* is not being used. The call to vQueueAddToRegistry() will be removed
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
* by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
||||||
defined to be less than 1. */
|
* defined to be less than 1. */
|
||||||
vQueueAddToRegistry( xQueue, "QPeek_Test_Queue" );
|
vQueueAddToRegistry( xQueue, "QPeek_Test_Queue" );
|
||||||
|
|
||||||
/* Create the demo tasks and pass it the queue just created. We are
|
/* Create the demo tasks and pass it the queue just created. We are
|
||||||
passing the queue handle by value so it does not matter that it is declared
|
* passing the queue handle by value so it does not matter that it is declared
|
||||||
on the stack here. */
|
* on the stack here. */
|
||||||
xTaskCreate( prvLowPriorityPeekTask, "PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
|
xTaskCreate( prvLowPriorityPeekTask, "PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL );
|
||||||
xTaskCreate( prvMediumPriorityPeekTask, "PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
|
xTaskCreate( prvMediumPriorityPeekTask, "PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask );
|
||||||
xTaskCreate( prvHighPriorityPeekTask, "PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
|
xTaskCreate( prvHighPriorityPeekTask, "PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask );
|
||||||
|
|
@ -125,7 +125,7 @@ uint32_t ulValue;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Try peeking from the queue. The queue should be empty so we will
|
/* Try peeking from the queue. The queue should be empty so we will
|
||||||
block, allowing the high priority task to execute. */
|
* block, allowing the high priority task to execute. */
|
||||||
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We expected to have received something by the time we unblock. */
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
|
@ -133,11 +133,11 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we reach here the high and medium priority tasks should still
|
/* When we reach here the high and medium priority tasks should still
|
||||||
be blocked on the queue. We unblocked because the low priority task
|
* be blocked on the queue. We unblocked because the low priority task
|
||||||
wrote a value to the queue, which we should have peeked. Peeking the
|
* wrote a value to the queue, which we should have peeked. Peeking the
|
||||||
data (rather than receiving it) will leave the data on the queue, so
|
* data (rather than receiving it) will leave the data on the queue, so
|
||||||
the high priority task should then have also been unblocked, but not
|
* the high priority task should then have also been unblocked, but not
|
||||||
yet executed. */
|
* yet executed. */
|
||||||
if( ulValue != 0x11223344 )
|
if( ulValue != 0x11223344 )
|
||||||
{
|
{
|
||||||
/* We did not receive the expected value. */
|
/* We did not receive the expected value. */
|
||||||
|
|
@ -151,9 +151,10 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we are going to actually receive the data, so when the high
|
/* Now we are going to actually receive the data, so when the high
|
||||||
priority task runs it will find the queue empty and return to the
|
* priority task runs it will find the queue empty and return to the
|
||||||
blocked state. */
|
* blocked state. */
|
||||||
ulValue = 0;
|
ulValue = 0;
|
||||||
|
|
||||||
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We expected to receive the value. */
|
/* We expected to receive the value. */
|
||||||
|
|
@ -163,12 +164,12 @@ uint32_t ulValue;
|
||||||
if( ulValue != 0x11223344 )
|
if( ulValue != 0x11223344 )
|
||||||
{
|
{
|
||||||
/* We did not receive the expected value - which should have been
|
/* We did not receive the expected value - which should have been
|
||||||
the same value as was peeked. */
|
* the same value as was peeked. */
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we will block again as the queue is once more empty. The low
|
/* Now we will block again as the queue is once more empty. The low
|
||||||
priority task can then execute again. */
|
* priority task can then execute again. */
|
||||||
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We expected to have received something by the time we unblock. */
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
|
@ -176,7 +177,7 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we get here the low priority task should have again written to the
|
/* When we get here the low priority task should have again written to the
|
||||||
queue. */
|
* queue. */
|
||||||
if( ulValue != 0x01234567 )
|
if( ulValue != 0x01234567 )
|
||||||
{
|
{
|
||||||
/* We did not receive the expected value. */
|
/* We did not receive the expected value. */
|
||||||
|
|
@ -190,16 +191,14 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We only peeked the data, so suspending ourselves now should enable
|
/* We only peeked the data, so suspending ourselves now should enable
|
||||||
the high priority task to also peek the data. The high priority task
|
* the high priority task to also peek the data. The high priority task
|
||||||
will have been unblocked when we peeked the data as we left the data
|
* will have been unblocked when we peeked the data as we left the data
|
||||||
in the queue. */
|
* in the queue. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This time we are going to do the same as the above test, but the
|
/* This time we are going to do the same as the above test, but the
|
||||||
high priority task is going to receive the data, rather than peek it.
|
* high priority task is going to receive the data, rather than peek it.
|
||||||
This means that the medium priority task should never peek the value. */
|
* This means that the medium priority task should never peek the value. */
|
||||||
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -223,8 +222,8 @@ uint32_t ulValue;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Try peeking from the queue. The queue should be empty so we will
|
/* Try peeking from the queue. The queue should be empty so we will
|
||||||
block, allowing the medium priority task to execute. Both the high
|
* block, allowing the medium priority task to execute. Both the high
|
||||||
and highest priority tasks will then be blocked on the queue. */
|
* and highest priority tasks will then be blocked on the queue. */
|
||||||
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We expected to have received something by the time we unblock. */
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
|
@ -232,8 +231,8 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we get here the highest priority task should have peeked the data
|
/* When we get here the highest priority task should have peeked the data
|
||||||
(unblocking this task) then suspended (allowing this task to also peek
|
* (unblocking this task) then suspended (allowing this task to also peek
|
||||||
the data). */
|
* the data). */
|
||||||
if( ulValue != 0x01234567 )
|
if( ulValue != 0x01234567 )
|
||||||
{
|
{
|
||||||
/* We did not receive the expected value. */
|
/* We did not receive the expected value. */
|
||||||
|
|
@ -247,14 +246,13 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We only peeked the data, so suspending ourselves now should enable
|
/* We only peeked the data, so suspending ourselves now should enable
|
||||||
the medium priority task to also peek the data. The medium priority task
|
* the medium priority task to also peek the data. The medium priority task
|
||||||
will have been unblocked when we peeked the data as we left the data
|
* will have been unblocked when we peeked the data as we left the data
|
||||||
in the queue. */
|
* in the queue. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
|
|
||||||
/* This time we are going actually receive the value, so the medium
|
/* This time we are going actually receive the value, so the medium
|
||||||
priority task will never peek the data - we removed it from the queue. */
|
* priority task will never peek the data - we removed it from the queue. */
|
||||||
if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -278,8 +276,8 @@ uint32_t ulValue;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Try peeking from the queue. The queue should be empty so we will
|
/* Try peeking from the queue. The queue should be empty so we will
|
||||||
block, allowing the low priority task to execute. The highest, high
|
* block, allowing the low priority task to execute. The highest, high
|
||||||
and medium priority tasks will then all be blocked on the queue. */
|
* and medium priority tasks will then all be blocked on the queue. */
|
||||||
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We expected to have received something by the time we unblock. */
|
/* We expected to have received something by the time we unblock. */
|
||||||
|
|
@ -287,8 +285,8 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we get here the high priority task should have peeked the data
|
/* When we get here the high priority task should have peeked the data
|
||||||
(unblocking this task) then suspended (allowing this task to also peek
|
* (unblocking this task) then suspended (allowing this task to also peek
|
||||||
the data). */
|
* the data). */
|
||||||
if( ulValue != 0x01234567 )
|
if( ulValue != 0x01234567 )
|
||||||
{
|
{
|
||||||
/* We did not receive the expected value. */
|
/* We did not receive the expected value. */
|
||||||
|
|
@ -305,7 +303,7 @@ uint32_t ulValue;
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
|
|
||||||
/* Now we can suspend ourselves so the low priority task can execute
|
/* Now we can suspend ourselves so the low priority task can execute
|
||||||
again. */
|
* again. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,12 +317,13 @@ uint32_t ulValue;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Write some data to the queue. This should unblock the highest
|
/* Write some data to the queue. This should unblock the highest
|
||||||
priority task that is waiting to peek data from the queue. */
|
* priority task that is waiting to peek data from the queue. */
|
||||||
ulValue = 0x11223344;
|
ulValue = 0x11223344;
|
||||||
|
|
||||||
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We were expecting the queue to be empty so we should not of
|
/* We were expecting the queue to be empty so we should not of
|
||||||
had a problem writing to the queue. */
|
* had a problem writing to the queue. */
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,19 +332,20 @@ uint32_t ulValue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* By the time we get here the data should have been removed from
|
/* By the time we get here the data should have been removed from
|
||||||
the queue. */
|
* the queue. */
|
||||||
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
if( uxQueueMessagesWaiting( xQueue ) != 0 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write another value to the queue, again waking the highest priority
|
/* Write another value to the queue, again waking the highest priority
|
||||||
task that is blocked on the queue. */
|
* task that is blocked on the queue. */
|
||||||
ulValue = 0x01234567;
|
ulValue = 0x01234567;
|
||||||
|
|
||||||
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We were expecting the queue to be empty so we should not of
|
/* We were expecting the queue to be empty so we should not of
|
||||||
had a problem writing to the queue. */
|
* had a problem writing to the queue. */
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,8 +354,9 @@ uint32_t ulValue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* All the other tasks should now have successfully peeked the data.
|
/* All the other tasks should now have successfully peeked the data.
|
||||||
The data is still in the queue so we should be able to receive it. */
|
* The data is still in the queue so we should be able to receive it. */
|
||||||
ulValue = 0;
|
ulValue = 0;
|
||||||
|
|
||||||
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We expected to receive the data. */
|
/* We expected to receive the data. */
|
||||||
|
|
@ -369,14 +370,14 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lets just delay a while as this is an intensive test as we don't
|
/* Lets just delay a while as this is an intensive test as we don't
|
||||||
want to starve other tests of processing time. */
|
* want to starve other tests of processing time. */
|
||||||
vTaskDelay( qpeekSHORT_DELAY );
|
vTaskDelay( qpeekSHORT_DELAY );
|
||||||
|
|
||||||
/* Unsuspend the other tasks so we can repeat the test - this time
|
/* Unsuspend the other tasks so we can repeat the test - this time
|
||||||
however not all the other tasks will peek the data as the high
|
* however not all the other tasks will peek the data as the high
|
||||||
priority task is actually going to remove it from the queue. Send
|
* priority task is actually going to remove it from the queue. Send
|
||||||
to front is used just to be different. As the queue is empty it
|
* to front is used just to be different. As the queue is empty it
|
||||||
makes no difference to the result. */
|
* makes no difference to the result. */
|
||||||
vTaskResume( xMediumPriorityTask );
|
vTaskResume( xMediumPriorityTask );
|
||||||
vTaskResume( xHighPriorityTask );
|
vTaskResume( xHighPriorityTask );
|
||||||
vTaskResume( xHighestPriorityTask );
|
vTaskResume( xHighestPriorityTask );
|
||||||
|
|
@ -386,10 +387,11 @@ uint32_t ulValue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ulValue = 0xaabbaabb;
|
ulValue = 0xaabbaabb;
|
||||||
|
|
||||||
if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* We were expecting the queue to be empty so we should not of
|
/* We were expecting the queue to be empty so we should not of
|
||||||
had a problem writing to the queue. */
|
* had a problem writing to the queue. */
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,7 +400,7 @@ uint32_t ulValue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This time we should find that the queue is empty. The high priority
|
/* This time we should find that the queue is empty. The high priority
|
||||||
task actually removed the data rather than just peeking it. */
|
* task actually removed the data rather than just peeking it. */
|
||||||
if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
|
if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY )
|
||||||
{
|
{
|
||||||
/* We expected to receive the data. */
|
/* We expected to receive the data. */
|
||||||
|
|
@ -406,13 +408,13 @@ uint32_t ulValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unsuspend the highest and high priority tasks so we can go back
|
/* Unsuspend the highest and high priority tasks so we can go back
|
||||||
and repeat the whole thing. The medium priority task should not be
|
* and repeat the whole thing. The medium priority task should not be
|
||||||
suspended as it was not able to peek the data in this last case. */
|
* suspended as it was not able to peek the data in this last case. */
|
||||||
vTaskResume( xHighPriorityTask );
|
vTaskResume( xHighPriorityTask );
|
||||||
vTaskResume( xHighestPriorityTask );
|
vTaskResume( xHighestPriorityTask );
|
||||||
|
|
||||||
/* Lets just delay a while as this is an intensive test as we don't
|
/* Lets just delay a while as this is an intensive test as we don't
|
||||||
want to starve other tests of processing time. */
|
* want to starve other tests of processing time. */
|
||||||
vTaskDelay( qpeekSHORT_DELAY );
|
vTaskDelay( qpeekSHORT_DELAY );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -424,7 +426,7 @@ BaseType_t xAreQueuePeekTasksStillRunning( void )
|
||||||
static uint32_t ulLastLoopCounter = 0;
|
static uint32_t ulLastLoopCounter = 0;
|
||||||
|
|
||||||
/* If the demo task is still running then we expect the loopcounter to
|
/* If the demo task is still running then we expect the loopcounter to
|
||||||
have incremented since this function was last called. */
|
* have incremented since this function was last called. */
|
||||||
if( ulLastLoopCounter == ulLoopCounter )
|
if( ulLastLoopCounter == ulLoopCounter )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -433,8 +435,7 @@ static uint32_t ulLastLoopCounter = 0;
|
||||||
ulLastLoopCounter = ulLoopCounter;
|
ulLastLoopCounter = ulLoopCounter;
|
||||||
|
|
||||||
/* Errors detected in the task itself will have latched xErrorDetected
|
/* Errors detected in the task itself will have latched xErrorDetected
|
||||||
to true. */
|
* to true. */
|
||||||
|
|
||||||
return ( BaseType_t ) !xErrorDetected;
|
return ( BaseType_t ) !xErrorDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,15 +48,15 @@
|
||||||
static void prvQueueOverwriteTask( void * pvParameters );
|
static void prvQueueOverwriteTask( void * pvParameters );
|
||||||
|
|
||||||
/* Variable that is incremented on each loop of prvQueueOverwriteTask() provided
|
/* Variable that is incremented on each loop of prvQueueOverwriteTask() provided
|
||||||
prvQueueOverwriteTask() has not found any errors. */
|
* prvQueueOverwriteTask() has not found any errors. */
|
||||||
static uint32_t ulLoopCounter = 0;
|
static uint32_t ulLoopCounter = 0;
|
||||||
|
|
||||||
/* Set to pdFALSE if an error is discovered by the
|
/* Set to pdFALSE if an error is discovered by the
|
||||||
vQueueOverwritePeriodicISRDemo() function. */
|
* vQueueOverwritePeriodicISRDemo() function. */
|
||||||
static BaseType_t xISRTestStatus = pdPASS;
|
static BaseType_t xISRTestStatus = pdPASS;
|
||||||
|
|
||||||
/* The queue that is accessed from the ISR. The queue accessed by the task is
|
/* The queue that is accessed from the ISR. The queue accessed by the task is
|
||||||
created inside the task itself. */
|
* created inside the task itself. */
|
||||||
static QueueHandle_t xISRQueue = NULL;
|
static QueueHandle_t xISRQueue = NULL;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -66,11 +66,11 @@ void vStartQueueOverwriteTask( UBaseType_t uxPriority )
|
||||||
const UBaseType_t uxQueueLength = 1;
|
const UBaseType_t uxQueueLength = 1;
|
||||||
|
|
||||||
/* Create the queue used by the ISR. xQueueOverwriteFromISR() should only
|
/* Create the queue used by the ISR. xQueueOverwriteFromISR() should only
|
||||||
be used on queues that have a length of 1. */
|
* be used on queues that have a length of 1. */
|
||||||
xISRQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );
|
xISRQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );
|
||||||
|
|
||||||
/* Create the test task. The queue used by the test task is created inside
|
/* Create the test task. The queue used by the test task is created inside
|
||||||
the task itself. */
|
* the task itself. */
|
||||||
xTaskCreate( prvQueueOverwriteTask, "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
xTaskCreate( prvQueueOverwriteTask, "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -85,14 +85,14 @@ uint32_t ulValue, ulStatus = pdPASS, x;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create the queue. xQueueOverwrite() should only be used on queues that
|
/* Create the queue. xQueueOverwrite() should only be used on queues that
|
||||||
have a length of 1. */
|
* have a length of 1. */
|
||||||
xTaskQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );
|
xTaskQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );
|
||||||
configASSERT( xTaskQueue );
|
configASSERT( xTaskQueue );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The queue is empty. Writing to the queue then reading from the queue
|
/* The queue is empty. Writing to the queue then reading from the queue
|
||||||
should return the item written. */
|
* should return the item written. */
|
||||||
ulValue = 10;
|
ulValue = 10;
|
||||||
xQueueOverwrite( xTaskQueue, &ulValue );
|
xQueueOverwrite( xTaskQueue, &ulValue );
|
||||||
|
|
||||||
|
|
@ -105,15 +105,16 @@ uint32_t ulValue, ulStatus = pdPASS, x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now try writing to the queue several times. Each time the value
|
/* Now try writing to the queue several times. Each time the value
|
||||||
in the queue should get overwritten. */
|
* in the queue should get overwritten. */
|
||||||
for( x = 0; x < qoLOOPS; x++ )
|
for( x = 0; x < qoLOOPS; x++ )
|
||||||
{
|
{
|
||||||
/* Write to the queue. */
|
/* Write to the queue. */
|
||||||
xQueueOverwrite( xTaskQueue, &x );
|
xQueueOverwrite( xTaskQueue, &x );
|
||||||
|
|
||||||
/* Check the value in the queue is that written, even though the
|
/* Check the value in the queue is that written, even though the
|
||||||
queue was not necessarily empty. */
|
* queue was not necessarily empty. */
|
||||||
xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK );
|
xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK );
|
||||||
|
|
||||||
if( ulValue != x )
|
if( ulValue != x )
|
||||||
{
|
{
|
||||||
ulStatus = pdFAIL;
|
ulStatus = pdFAIL;
|
||||||
|
|
@ -137,7 +138,7 @@ uint32_t ulValue, ulStatus = pdPASS, x;
|
||||||
if( ulStatus != pdFAIL )
|
if( ulStatus != pdFAIL )
|
||||||
{
|
{
|
||||||
/* Increment a counter to show this task is still running without
|
/* Increment a counter to show this task is still running without
|
||||||
error. */
|
* error. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,46 +180,52 @@ const uint32_t ulTx1 = 10UL, ulTx2 = 20UL, ulNumberOfSwitchCases = 3UL;
|
||||||
uint32_t ulRx;
|
uint32_t ulRx;
|
||||||
|
|
||||||
/* This function should be called from an interrupt, such as the tick hook
|
/* This function should be called from an interrupt, such as the tick hook
|
||||||
function vApplicationTickHook(). */
|
* function vApplicationTickHook(). */
|
||||||
|
|
||||||
configASSERT( xISRQueue );
|
configASSERT( xISRQueue );
|
||||||
|
|
||||||
switch( ulCallCount )
|
switch( ulCallCount )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
|
||||||
/* The queue is empty. Write ulTx1 to the queue. In this demo the
|
/* The queue is empty. Write ulTx1 to the queue. In this demo the
|
||||||
last parameter is not used because there are no tasks blocked on
|
* last parameter is not used because there are no tasks blocked on
|
||||||
this queue. */
|
* this queue. */
|
||||||
xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL );
|
xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL );
|
||||||
|
|
||||||
/* Peek the queue to check it holds the expected value. */
|
/* Peek the queue to check it holds the expected value. */
|
||||||
xQueuePeekFromISR( xISRQueue, &ulRx );
|
xQueuePeekFromISR( xISRQueue, &ulRx );
|
||||||
|
|
||||||
if( ulRx != ulTx1 )
|
if( ulRx != ulTx1 )
|
||||||
{
|
{
|
||||||
xISRTestStatus = pdFAIL;
|
xISRTestStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
|
||||||
/* The queue already holds ulTx1. Overwrite the value in the queue
|
/* The queue already holds ulTx1. Overwrite the value in the queue
|
||||||
with ulTx2. */
|
* with ulTx2. */
|
||||||
xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL );
|
xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
|
||||||
/* Read from the queue to empty the queue again. The value read
|
/* Read from the queue to empty the queue again. The value read
|
||||||
should be ulTx2. */
|
* should be ulTx2. */
|
||||||
xQueueReceiveFromISR( xISRQueue, &ulRx, NULL );
|
xQueueReceiveFromISR( xISRQueue, &ulRx, NULL );
|
||||||
|
|
||||||
if( ulRx != ulTx2 )
|
if( ulRx != ulTx2 )
|
||||||
{
|
{
|
||||||
xISRTestStatus = pdFAIL;
|
xISRTestStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run the next case in the switch statement above next time this function
|
/* Run the next case in the switch statement above next time this function
|
||||||
is called. */
|
* is called. */
|
||||||
ulCallCount++;
|
ulCallCount++;
|
||||||
|
|
||||||
if( ulCallCount >= ulNumberOfSwitchCases )
|
if( ulCallCount >= ulNumberOfSwitchCases )
|
||||||
|
|
@ -227,4 +234,3 @@ uint32_t ulRx;
|
||||||
ulCallCount = 0;
|
ulCallCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@
|
||||||
#define queuesetDONT_BLOCK 0
|
#define queuesetDONT_BLOCK 0
|
||||||
|
|
||||||
/* Messages are sent in incrementing order from both a task and an interrupt.
|
/* Messages are sent in incrementing order from both a task and an interrupt.
|
||||||
The task sends values in the range 0 to 0xfffe, and the interrupt sends values
|
* The task sends values in the range 0 to 0xfffe, and the interrupt sends values
|
||||||
in the range of 0xffff to ULONG_MAX. */
|
* in the range of 0xffff to ULONG_MAX. */
|
||||||
#define queuesetINITIAL_ISR_TX_VALUE 0xffffUL
|
#define queuesetINITIAL_ISR_TX_VALUE 0xffffUL
|
||||||
|
|
||||||
/* The priorities used in this demo. */
|
/* The priorities used in this demo. */
|
||||||
|
|
@ -75,25 +75,25 @@ in the range of 0xffff to ULONG_MAX. */
|
||||||
#define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 )
|
#define queuesetMEDIUM_PRIORITY ( queuesetLOW_PRIORITY + 1 )
|
||||||
|
|
||||||
/* For test purposes the priority of the sending task is changed after every
|
/* For test purposes the priority of the sending task is changed after every
|
||||||
queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */
|
* queuesetPRIORITY_CHANGE_LOOPS number of values are sent to a queue. */
|
||||||
#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 )
|
#define queuesetPRIORITY_CHANGE_LOOPS ( ( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH ) * 2 )
|
||||||
|
|
||||||
/* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */
|
/* The ISR sends to the queue every queuesetISR_TX_PERIOD ticks. */
|
||||||
#define queuesetISR_TX_PERIOD ( 100UL )
|
#define queuesetISR_TX_PERIOD ( 100UL )
|
||||||
|
|
||||||
/* A delay inserted when the Tx task changes its priority to be above the idle
|
/* A delay inserted when the Tx task changes its priority to be above the idle
|
||||||
task priority to ensure the idle priority tasks get some CPU time before the
|
* task priority to ensure the idle priority tasks get some CPU time before the
|
||||||
next iteration of the queue set Tx task. */
|
* next iteration of the queue set Tx task. */
|
||||||
#define queuesetTX_LOOP_DELAY pdMS_TO_TICKS( ( TickType_t ) 200 )
|
#define queuesetTX_LOOP_DELAY pdMS_TO_TICKS( ( TickType_t ) 200 )
|
||||||
|
|
||||||
/* The allowable maximum deviation between a received value and the expected
|
/* The allowable maximum deviation between a received value and the expected
|
||||||
received value. A deviation will occur when data is received from a queue
|
* received value. A deviation will occur when data is received from a queue
|
||||||
inside an ISR in between a task receiving from a queue and the task checking
|
* inside an ISR in between a task receiving from a queue and the task checking
|
||||||
the received value. */
|
* the received value. */
|
||||||
#define queuesetALLOWABLE_RX_DEVIATION 3
|
#define queuesetALLOWABLE_RX_DEVIATION 3
|
||||||
|
|
||||||
/* Ignore values that are at the boundaries of allowable values to make the
|
/* Ignore values that are at the boundaries of allowable values to make the
|
||||||
testing of limits easier (don't have to deal with wrapping values). */
|
* testing of limits easier (don't have to deal with wrapping values). */
|
||||||
#define queuesetIGNORED_BOUNDARY ( queuesetALLOWABLE_RX_DEVIATION * 2 )
|
#define queuesetIGNORED_BOUNDARY ( queuesetALLOWABLE_RX_DEVIATION * 2 )
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|
@ -138,7 +138,8 @@ static void prvSetupTest( void );
|
||||||
* Checks a value received from a queue falls within the range of expected
|
* Checks a value received from a queue falls within the range of expected
|
||||||
* values.
|
* values.
|
||||||
*/
|
*/
|
||||||
static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived );
|
static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
|
||||||
|
uint32_t ulExpectedReceived );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Increase test coverage by occasionally change the priorities of the two tasks
|
* Increase test coverage by occasionally change the priorities of the two tasks
|
||||||
|
|
@ -173,30 +174,30 @@ static void prvSRand( size_t uxSeed );
|
||||||
static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
static QueueHandle_t xQueues[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
||||||
|
|
||||||
/* Counts how many times each queue in the set is used to ensure all the
|
/* Counts how many times each queue in the set is used to ensure all the
|
||||||
queues are used. */
|
* queues are used. */
|
||||||
static uint32_t ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
static uint32_t ulQueueUsedCounter[ queuesetNUM_QUEUES_IN_SET ] = { 0 };
|
||||||
|
|
||||||
/* The handle of the queue set to which the queues are added. */
|
/* The handle of the queue set to which the queues are added. */
|
||||||
static QueueSetHandle_t xQueueSet;
|
static QueueSetHandle_t xQueueSet;
|
||||||
|
|
||||||
/* If the prvQueueSetReceivingTask() task has not detected any errors then
|
/* If the prvQueueSetReceivingTask() task has not detected any errors then
|
||||||
it increments ulCycleCounter on each iteration.
|
* it increments ulCycleCounter on each iteration.
|
||||||
xAreQueueSetTasksStillRunning() returns pdPASS if the value of
|
* xAreQueueSetTasksStillRunning() returns pdPASS if the value of
|
||||||
ulCycleCounter has changed between consecutive calls, and pdFALSE if
|
* ulCycleCounter has changed between consecutive calls, and pdFALSE if
|
||||||
ulCycleCounter has stopped incrementing (indicating an error condition). */
|
* ulCycleCounter has stopped incrementing (indicating an error condition). */
|
||||||
static volatile uint32_t ulCycleCounter = 0UL;
|
static volatile uint32_t ulCycleCounter = 0UL;
|
||||||
|
|
||||||
/* Set to pdFAIL if an error is detected by any queue set task.
|
/* Set to pdFAIL if an error is detected by any queue set task.
|
||||||
ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */
|
* ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */
|
||||||
static volatile BaseType_t xQueueSetTasksStatus = pdPASS;
|
static volatile BaseType_t xQueueSetTasksStatus = pdPASS;
|
||||||
|
|
||||||
/* Just a flag to let the function that writes to a queue from an ISR know that
|
/* Just a flag to let the function that writes to a queue from an ISR know that
|
||||||
the queues are setup and can be used. */
|
* the queues are setup and can be used. */
|
||||||
static volatile BaseType_t xSetupComplete = pdFALSE;
|
static volatile BaseType_t xSetupComplete = pdFALSE;
|
||||||
|
|
||||||
/* The value sent to the queue from the ISR is file scope so the
|
/* The value sent to the queue from the ISR is file scope so the
|
||||||
xAreQueeuSetTasksStillRunning() function can check it is incrementing as
|
* xAreQueeuSetTasksStillRunning() function can check it is incrementing as
|
||||||
expected. */
|
* expected. */
|
||||||
static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
|
static volatile uint32_t ulISRTxValue = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
|
||||||
/* Used by the pseudo random number generator. */
|
/* Used by the pseudo random number generator. */
|
||||||
|
|
@ -217,10 +218,10 @@ void vStartQueueSetTasks( void )
|
||||||
xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask );
|
xTaskCreate( prvQueueSetReceivingTask, "SetRx", configMINIMAL_STACK_SIZE, ( void * ) xQueueSetSendingTask, queuesetMEDIUM_PRIORITY, &xQueueSetReceivingTask );
|
||||||
|
|
||||||
/* It is important that the sending task does not attempt to write to a
|
/* It is important that the sending task does not attempt to write to a
|
||||||
queue before the queue has been created. It is therefore placed into
|
* queue before the queue has been created. It is therefore placed into
|
||||||
the suspended state before the scheduler has started. It is resumed by
|
* the suspended state before the scheduler has started. It is resumed by
|
||||||
the receiving task after the receiving task has created the queues and
|
* the receiving task after the receiving task has created the queues and
|
||||||
added the queues to the queue set. */
|
* added the queues to the queue set. */
|
||||||
vTaskSuspend( xQueueSetSendingTask );
|
vTaskSuspend( xQueueSetSendingTask );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -235,15 +236,15 @@ BaseType_t xReturn = pdPASS, x;
|
||||||
if( ulLastCycleCounter == ulCycleCounter )
|
if( ulLastCycleCounter == ulCycleCounter )
|
||||||
{
|
{
|
||||||
/* The cycle counter is no longer being incremented. Either one of the
|
/* The cycle counter is no longer being incremented. Either one of the
|
||||||
tasks is stalled or an error has been detected. */
|
* tasks is stalled or an error has been detected. */
|
||||||
xReturn = pdFAIL;
|
xReturn = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulLastCycleCounter = ulCycleCounter;
|
ulLastCycleCounter = ulCycleCounter;
|
||||||
|
|
||||||
/* Ensure that all the queues in the set have been used. This ensures the
|
/* Ensure that all the queues in the set have been used. This ensures the
|
||||||
test is working as intended and guards against the rand() in the Tx task
|
* test is working as intended and guards against the rand() in the Tx task
|
||||||
missing some values. */
|
* missing some values. */
|
||||||
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
|
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
|
||||||
{
|
{
|
||||||
if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] )
|
if( ulLastQueueUsedCounter[ x ] == ulQueueUsedCounter[ x ] )
|
||||||
|
|
@ -293,15 +294,15 @@ QueueHandle_t xQueueInUse;
|
||||||
xQueueInUse = xQueues[ uxQueueToWriteTo ];
|
xQueueInUse = xQueues[ uxQueueToWriteTo ];
|
||||||
|
|
||||||
/* Note which index is being written to to ensure all the queues are
|
/* Note which index is being written to to ensure all the queues are
|
||||||
used. */
|
* used. */
|
||||||
( ulQueueUsedCounter[ uxQueueToWriteTo ] )++;
|
( ulQueueUsedCounter[ uxQueueToWriteTo ] )++;
|
||||||
|
|
||||||
/* Send to the queue to unblock the task that is waiting for data to
|
/* Send to the queue to unblock the task that is waiting for data to
|
||||||
arrive on a queue within the queue set to which this queue belongs. */
|
* arrive on a queue within the queue set to which this queue belongs. */
|
||||||
if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS )
|
if( xQueueSendToBack( xQueueInUse, &ulTaskTxValue, portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* The send should always pass as an infinite block time was
|
/* The send should always pass as an infinite block time was
|
||||||
used. */
|
* used. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,14 +313,14 @@ QueueHandle_t xQueueInUse;
|
||||||
ulTaskTxValue++;
|
ulTaskTxValue++;
|
||||||
|
|
||||||
/* If the Tx value has reached the range used by the ISR then set it
|
/* If the Tx value has reached the range used by the ISR then set it
|
||||||
back to 0. */
|
* back to 0. */
|
||||||
if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )
|
if( ulTaskTxValue == queuesetINITIAL_ISR_TX_VALUE )
|
||||||
{
|
{
|
||||||
ulTaskTxValue = 0;
|
ulTaskTxValue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increase test coverage by occasionally change the priorities of the
|
/* Increase test coverage by occasionally change the priorities of the
|
||||||
two tasks relative to each other. */
|
* two tasks relative to each other. */
|
||||||
prvChangeRelativePriorities();
|
prvChangeRelativePriorities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -331,8 +332,9 @@ static UBaseType_t ulLoops = 0;
|
||||||
static eRelativePriorities ePriorities = eEqualPriority;
|
static eRelativePriorities ePriorities = eEqualPriority;
|
||||||
|
|
||||||
/* Occasionally change the task priority relative to the priority of
|
/* Occasionally change the task priority relative to the priority of
|
||||||
the receiving task. */
|
* the receiving task. */
|
||||||
ulLoops++;
|
ulLoops++;
|
||||||
|
|
||||||
if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )
|
if( ulLoops >= queuesetPRIORITY_CHANGE_LOOPS )
|
||||||
{
|
{
|
||||||
ulLoops = 0;
|
ulLoops = 0;
|
||||||
|
|
@ -340,31 +342,34 @@ static eRelativePriorities ePriorities = eEqualPriority;
|
||||||
switch( ePriorities )
|
switch( ePriorities )
|
||||||
{
|
{
|
||||||
case eEqualPriority:
|
case eEqualPriority:
|
||||||
|
|
||||||
/* Both tasks are running with medium priority. Now lower the
|
/* Both tasks are running with medium priority. Now lower the
|
||||||
priority of the receiving task so the Tx task has the higher
|
* priority of the receiving task so the Tx task has the higher
|
||||||
relative priority. */
|
* relative priority. */
|
||||||
vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY );
|
vTaskPrioritySet( xQueueSetReceivingTask, queuesetLOW_PRIORITY );
|
||||||
ePriorities = eTxHigherPriority;
|
ePriorities = eTxHigherPriority;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eTxHigherPriority:
|
case eTxHigherPriority:
|
||||||
|
|
||||||
/* The Tx task is running with a higher priority than the Rx
|
/* The Tx task is running with a higher priority than the Rx
|
||||||
task. Switch the priorities around so the Rx task has the
|
* task. Switch the priorities around so the Rx task has the
|
||||||
higher relative priority. */
|
* higher relative priority. */
|
||||||
vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY );
|
vTaskPrioritySet( xQueueSetReceivingTask, queuesetMEDIUM_PRIORITY );
|
||||||
vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY );
|
vTaskPrioritySet( xQueueSetSendingTask, queuesetLOW_PRIORITY );
|
||||||
ePriorities = eTxLowerPriority;
|
ePriorities = eTxLowerPriority;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eTxLowerPriority:
|
case eTxLowerPriority:
|
||||||
|
|
||||||
/* The Tx task is running with a lower priority than the Rx
|
/* The Tx task is running with a lower priority than the Rx
|
||||||
task. Make the priorities equal again. */
|
* task. Make the priorities equal again. */
|
||||||
vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY );
|
vTaskPrioritySet( xQueueSetSendingTask, queuesetMEDIUM_PRIORITY );
|
||||||
ePriorities = eEqualPriority;
|
ePriorities = eEqualPriority;
|
||||||
|
|
||||||
/* When both tasks are using a non-idle priority the queue set
|
/* When both tasks are using a non-idle priority the queue set
|
||||||
tasks will starve idle priority tasks of execution time - so
|
* tasks will starve idle priority tasks of execution time - so
|
||||||
relax a bit before the next iteration to minimise the impact. */
|
* relax a bit before the next iteration to minimise the impact. */
|
||||||
vTaskDelay( queuesetTX_LOOP_DELAY );
|
vTaskDelay( queuesetTX_LOOP_DELAY );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -383,14 +388,14 @@ TickType_t xBlockTime;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create the queues and add them to the queue set before resuming the Tx
|
/* Create the queues and add them to the queue set before resuming the Tx
|
||||||
task. */
|
* task. */
|
||||||
prvSetupTest();
|
prvSetupTest();
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* For test coverage reasons, the block time is dependent on the
|
/* For test coverage reasons, the block time is dependent on the
|
||||||
priority of this task - which changes during the test. When the task
|
* priority of this task - which changes during the test. When the task
|
||||||
is at the idle priority it polls the queue set. */
|
* is at the idle priority it polls the queue set. */
|
||||||
if( uxTaskPriorityGet( NULL ) == tskIDLE_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == tskIDLE_PRIORITY )
|
||||||
{
|
{
|
||||||
xBlockTime = 0;
|
xBlockTime = 0;
|
||||||
|
|
@ -414,16 +419,16 @@ TickType_t xBlockTime;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Reading from the queue should pass with a zero block time as
|
/* Reading from the queue should pass with a zero block time as
|
||||||
this task will only run when something has been posted to a task
|
* this task will only run when something has been posted to a task
|
||||||
in the queue set. */
|
* in the queue set. */
|
||||||
if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS )
|
if( xQueueReceive( xActivatedQueue, &ulReceived, queuesetDONT_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the value received was the value expected. This function
|
/* Ensure the value received was the value expected. This function
|
||||||
manipulates file scope data and is also called from an ISR, hence
|
* manipulates file scope data and is also called from an ISR, hence
|
||||||
the critical section. */
|
* the critical section. */
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
prvCheckReceivedValue( ulReceived );
|
prvCheckReceivedValue( ulReceived );
|
||||||
|
|
@ -444,12 +449,13 @@ void vQueueSetAccessQueueSetFromISR( void )
|
||||||
static uint32_t ulCallCount = 0;
|
static uint32_t ulCallCount = 0;
|
||||||
|
|
||||||
/* xSetupComplete is set to pdTRUE when the queues have been created and
|
/* xSetupComplete is set to pdTRUE when the queues have been created and
|
||||||
are available for use. */
|
* are available for use. */
|
||||||
if( xSetupComplete == pdTRUE )
|
if( xSetupComplete == pdTRUE )
|
||||||
{
|
{
|
||||||
/* It is intended that this function is called from the tick hook
|
/* It is intended that this function is called from the tick hook
|
||||||
function, so each call is one tick period apart. */
|
* function, so each call is one tick period apart. */
|
||||||
ulCallCount++;
|
ulCallCount++;
|
||||||
|
|
||||||
if( ulCallCount > queuesetISR_TX_PERIOD )
|
if( ulCallCount > queuesetISR_TX_PERIOD )
|
||||||
{
|
{
|
||||||
ulCallCount = 0;
|
ulCallCount = 0;
|
||||||
|
|
@ -469,28 +475,28 @@ static void prvCheckReceivedValue( uint32_t ulReceived )
|
||||||
static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
|
static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
|
||||||
/* Values are received in tasks and interrupts. It is likely that the
|
/* Values are received in tasks and interrupts. It is likely that the
|
||||||
receiving task will sometimes get preempted by the receiving interrupt
|
* receiving task will sometimes get preempted by the receiving interrupt
|
||||||
between reading a value from the queue and calling this function. When
|
* between reading a value from the queue and calling this function. When
|
||||||
that happens, if the receiving interrupt calls this function the values
|
* that happens, if the receiving interrupt calls this function the values
|
||||||
will get passed into this function slightly out of order. For that
|
* will get passed into this function slightly out of order. For that
|
||||||
reason the value passed in is tested against a small range of expected
|
* reason the value passed in is tested against a small range of expected
|
||||||
values, rather than a single absolute value. To make the range testing
|
* values, rather than a single absolute value. To make the range testing
|
||||||
easier values in the range limits are ignored. */
|
* easier values in the range limits are ignored. */
|
||||||
|
|
||||||
/* If the received value is equal to or greater than
|
/* If the received value is equal to or greater than
|
||||||
queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */
|
* queuesetINITIAL_ISR_TX_VALUE then it was sent by an ISR. */
|
||||||
if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE )
|
if( ulReceived >= queuesetINITIAL_ISR_TX_VALUE )
|
||||||
{
|
{
|
||||||
/* The value was sent from the ISR. */
|
/* The value was sent from the ISR. */
|
||||||
if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY )
|
if( ( ulReceived - queuesetINITIAL_ISR_TX_VALUE ) < queuesetIGNORED_BOUNDARY )
|
||||||
{
|
{
|
||||||
/* The value received is at the lower limit of the expected range.
|
/* The value received is at the lower limit of the expected range.
|
||||||
Don't test it and expect to receive one higher next time. */
|
* Don't test it and expect to receive one higher next time. */
|
||||||
}
|
}
|
||||||
else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY )
|
else if( ( ULONG_MAX - ulReceived ) <= queuesetIGNORED_BOUNDARY )
|
||||||
{
|
{
|
||||||
/* The value received is at the higher limit of the expected range.
|
/* The value received is at the higher limit of the expected range.
|
||||||
Don't test it and expect to wrap soon. */
|
* Don't test it and expect to wrap soon. */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -505,6 +511,7 @@ static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queu
|
||||||
|
|
||||||
/* It is expected to receive an incrementing number. */
|
/* It is expected to receive an incrementing number. */
|
||||||
ulExpectedReceivedFromISR++;
|
ulExpectedReceivedFromISR++;
|
||||||
|
|
||||||
if( ulExpectedReceivedFromISR == 0 )
|
if( ulExpectedReceivedFromISR == 0 )
|
||||||
{
|
{
|
||||||
ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
|
ulExpectedReceivedFromISR = queuesetINITIAL_ISR_TX_VALUE;
|
||||||
|
|
@ -516,12 +523,12 @@ static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queu
|
||||||
if( ulReceived < queuesetIGNORED_BOUNDARY )
|
if( ulReceived < queuesetIGNORED_BOUNDARY )
|
||||||
{
|
{
|
||||||
/* The value received is at the lower limit of the expected range.
|
/* The value received is at the lower limit of the expected range.
|
||||||
Don't test it, and expect to receive one higher next time. */
|
* Don't test it, and expect to receive one higher next time. */
|
||||||
}
|
}
|
||||||
else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY )
|
else if( ( ( queuesetINITIAL_ISR_TX_VALUE - 1 ) - ulReceived ) <= queuesetIGNORED_BOUNDARY )
|
||||||
{
|
{
|
||||||
/* The value received is at the higher limit of the expected range.
|
/* The value received is at the higher limit of the expected range.
|
||||||
Don't test it and expect to wrap soon. */
|
* Don't test it and expect to wrap soon. */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -536,6 +543,7 @@ static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queu
|
||||||
|
|
||||||
/* It is expected to receive an incrementing number. */
|
/* It is expected to receive an incrementing number. */
|
||||||
ulExpectedReceivedFromTask++;
|
ulExpectedReceivedFromTask++;
|
||||||
|
|
||||||
if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )
|
if( ulExpectedReceivedFromTask >= queuesetINITIAL_ISR_TX_VALUE )
|
||||||
{
|
{
|
||||||
ulExpectedReceivedFromTask = 0;
|
ulExpectedReceivedFromTask = 0;
|
||||||
|
|
@ -544,13 +552,15 @@ static uint32_t ulExpectedReceivedFromTask = 0, ulExpectedReceivedFromISR = queu
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived, uint32_t ulExpectedReceived )
|
static BaseType_t prvCheckReceivedValueWithinExpectedRange( uint32_t ulReceived,
|
||||||
|
uint32_t ulExpectedReceived )
|
||||||
{
|
{
|
||||||
BaseType_t xReturn = pdPASS;
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
if( ulReceived > ulExpectedReceived )
|
if( ulReceived > ulExpectedReceived )
|
||||||
{
|
{
|
||||||
configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
|
configASSERT( ( ulReceived - ulExpectedReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
|
||||||
|
|
||||||
if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION )
|
if( ( ulReceived - ulExpectedReceived ) > queuesetALLOWABLE_RX_DEVIATION )
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
|
|
@ -559,6 +569,7 @@ BaseType_t xReturn = pdPASS;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
|
configASSERT( ( ulExpectedReceived - ulReceived ) <= queuesetALLOWABLE_RX_DEVIATION );
|
||||||
|
|
||||||
if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION )
|
if( ( ulExpectedReceived - ulReceived ) > queuesetALLOWABLE_RX_DEVIATION )
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
|
|
@ -583,7 +594,7 @@ uint32_t ulReceived;
|
||||||
if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS )
|
if( xQueueReceiveFromISR( xActivatedQueue, &ulReceived, NULL ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* Data should have been available as the handle was returned from
|
/* Data should have been available as the handle was returned from
|
||||||
xQueueSelectFromSetFromISR(). */
|
* xQueueSelectFromSetFromISR(). */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -610,6 +621,7 @@ uint32_t ulTxValueSnapshot = ulISRTxValue;
|
||||||
|
|
||||||
/* Use a different queue next time. */
|
/* Use a different queue next time. */
|
||||||
xQueueToWriteTo++;
|
xQueueToWriteTo++;
|
||||||
|
|
||||||
if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET )
|
if( xQueueToWriteTo >= queuesetNUM_QUEUES_IN_SET )
|
||||||
{
|
{
|
||||||
xQueueToWriteTo = 0;
|
xQueueToWriteTo = 0;
|
||||||
|
|
@ -625,7 +637,7 @@ QueueHandle_t xQueueHandle = NULL, xReceivedHandle = NULL;
|
||||||
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
|
|
||||||
/* Create a queue that has a length of one - a requirement in order to call
|
/* Create a queue that has a length of one - a requirement in order to call
|
||||||
xQueueOverwrite. This will get deleted again when this test completes. */
|
* xQueueOverwrite. This will get deleted again when this test completes. */
|
||||||
xQueueHandle = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
xQueueHandle = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
||||||
configASSERT( xQueueHandle );
|
configASSERT( xQueueHandle );
|
||||||
|
|
||||||
|
|
@ -634,43 +646,50 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
xQueueAddToSet( xQueueHandle, xQueueSet );
|
xQueueAddToSet( xQueueHandle, xQueueSet );
|
||||||
|
|
||||||
/* Add an item to the queue then ensure the queue set correctly
|
/* Add an item to the queue then ensure the queue set correctly
|
||||||
indicates that one item is available, and that item is indeed the
|
* indicates that one item is available, and that item is indeed the
|
||||||
queue written to. */
|
* queue written to. */
|
||||||
xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
|
xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
||||||
{
|
{
|
||||||
/* Expected one item in the queue set. */
|
/* Expected one item in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle )
|
if( xReceivedHandle != xQueueHandle )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
||||||
held in the queue set. */
|
* held in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now overwrite the value in the queue and ensure the queue set state
|
/* Now overwrite the value in the queue and ensure the queue set state
|
||||||
doesn't change as the number of items in the queues within the set have
|
* doesn't change as the number of items in the queues within the set have
|
||||||
not changed. */
|
* not changed. */
|
||||||
ulValueToSend++;
|
ulValueToSend++;
|
||||||
xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
|
xQueueOverwrite( xQueueHandle, ( void * ) &ulValueToSend );
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
||||||
{
|
{
|
||||||
/* Still expected one item in the queue set. */
|
/* Still expected one item in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle )
|
if( xReceivedHandle != xQueueHandle )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
||||||
held in the queue set. */
|
* held in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Also ensure the value received from the queue is the overwritten
|
/* Also ensure the value received from the queue is the overwritten
|
||||||
value, not the value originally written. */
|
* value, not the value originally written. */
|
||||||
xQueueReceive( xQueueHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
xQueueReceive( xQueueHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( ulValueReceived != ulValueToSend )
|
if( ulValueReceived != ulValueToSend )
|
||||||
{
|
{
|
||||||
/* Unexpected value received from the queue. */
|
/* Unexpected value received from the queue. */
|
||||||
|
|
@ -682,7 +701,9 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != NULL )
|
if( xReceivedHandle != NULL )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
|
@ -702,7 +723,7 @@ QueueHandle_t xQueueHandle1 = NULL, xQueueHandle2 = NULL, xReceivedHandle = NULL
|
||||||
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
|
|
||||||
/* Create two queues that have a length of one - a requirement in order to call
|
/* Create two queues that have a length of one - a requirement in order to call
|
||||||
xQueueOverwrite. These will get deleted again when this test completes. */
|
* xQueueOverwrite. These will get deleted again when this test completes. */
|
||||||
xQueueHandle1 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
xQueueHandle1 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
||||||
configASSERT( xQueueHandle1 );
|
configASSERT( xQueueHandle1 );
|
||||||
xQueueHandle2 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
xQueueHandle2 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
||||||
|
|
@ -716,6 +737,7 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
|
|
||||||
/* Add an item using the first queue. */
|
/* Add an item using the first queue. */
|
||||||
xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend1 );
|
xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend1 );
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
||||||
{
|
{
|
||||||
/* Expected one item in the queue set. */
|
/* Expected one item in the queue set. */
|
||||||
|
|
@ -723,16 +745,17 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle1 )
|
if( xReceivedHandle != xQueueHandle1 )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
||||||
held in the queue set. */
|
* held in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Next add an item to the second queue. */
|
/* Next add an item to the second queue. */
|
||||||
xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend2 );
|
xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend2 );
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
{
|
{
|
||||||
/* Expected two items in the queue set. */
|
/* Expected two items in the queue set. */
|
||||||
|
|
@ -741,100 +764,108 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
|
|
||||||
/* The head of the queue set should not have changed though. */
|
/* The head of the queue set should not have changed though. */
|
||||||
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle1 )
|
if( xReceivedHandle != xQueueHandle1 )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
||||||
held in the queue set. */
|
* held in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Now overwrite the value in the queue and ensure the queue set state
|
/* Now overwrite the value in the queue and ensure the queue set state
|
||||||
doesn't change as the number of items in the queues within the set have
|
* doesn't change as the number of items in the queues within the set have
|
||||||
not changed. NOTE: after this queue 1 should hold ulValueToSend2 and queue
|
* not changed. NOTE: after this queue 1 should hold ulValueToSend2 and queue
|
||||||
2 should hold the value ulValueToSend1. */
|
* 2 should hold the value ulValueToSend1. */
|
||||||
xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
|
xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
|
||||||
{
|
|
||||||
/* Still expected two items in the queue set. */
|
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
|
||||||
}
|
|
||||||
xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
{
|
{
|
||||||
/* Still expected two items in the queue set. */
|
/* Still expected two items in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
|
{
|
||||||
|
/* Still expected two items in the queue set. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Repeat the above to ensure the queue set state doesn't change. */
|
/* Repeat the above to ensure the queue set state doesn't change. */
|
||||||
xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
|
xQueueOverwrite( xQueueHandle1, ( void * ) &ulValueToSend2 );
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
|
||||||
{
|
|
||||||
/* Still expected two items in the queue set. */
|
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
|
||||||
}
|
|
||||||
xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
{
|
{
|
||||||
/* Still expected two items in the queue set. */
|
/* Still expected two items in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xQueueOverwrite( xQueueHandle2, ( void * ) &ulValueToSend1 );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
|
{
|
||||||
|
/* Still expected two items in the queue set. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now when reading from the queue set we expect the handle to the first
|
/* Now when reading from the queue set we expect the handle to the first
|
||||||
queue to be received first, and for that queue to hold ulValueToSend2 as the
|
* queue to be received first, and for that queue to hold ulValueToSend2 as the
|
||||||
originally written value was overwritten. Likewise the second handle received
|
* originally written value was overwritten. Likewise the second handle received
|
||||||
from the set should be that of the second queue, and that queue should hold
|
* from the set should be that of the second queue, and that queue should hold
|
||||||
ulValueToSend1 as the originally written value was overwritten. */
|
* ulValueToSend1 as the originally written value was overwritten. */
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle1 )
|
if( xReceivedHandle != xQueueHandle1 )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle1 first so expected that handle to be read from
|
/* Wrote to xQueueHandle1 first so expected that handle to be read from
|
||||||
the set first. */
|
* the set first. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
||||||
{
|
{
|
||||||
/* One value was read from the set, so now only expect a single value
|
/* One value was read from the set, so now only expect a single value
|
||||||
in the set. */
|
* in the set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( ulValueReceived != ulValueToSend2 )
|
if( ulValueReceived != ulValueToSend2 )
|
||||||
{
|
{
|
||||||
/* Unexpected value received from the queue. ulValueToSend1 was written
|
/* Unexpected value received from the queue. ulValueToSend1 was written
|
||||||
first, but then overwritten with ulValueToSend2; */
|
* first, but then overwritten with ulValueToSend2; */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle2 )
|
if( xReceivedHandle != xQueueHandle2 )
|
||||||
{
|
{
|
||||||
/* xQueueHandle1 has already been removed from the set so expect only
|
/* xQueueHandle1 has already been removed from the set so expect only
|
||||||
xQueueHandle2 to be left. */
|
* xQueueHandle2 to be left. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
/* The last value was read from the set so don't expect any more. */
|
/* The last value was read from the set so don't expect any more. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( ulValueReceived != ulValueToSend1 )
|
if( ulValueReceived != ulValueToSend1 )
|
||||||
{
|
{
|
||||||
/* Unexpected value received from the queue. ulValueToSend2 was written
|
/* Unexpected value received from the queue. ulValueToSend2 was written
|
||||||
first, but then overwritten with ulValueToSend1. */
|
* first, but then overwritten with ulValueToSend1. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Should be anything in the queue set now. */
|
/* Should be anything in the queue set now. */
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != NULL )
|
if( xReceivedHandle != NULL )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
|
@ -856,7 +887,7 @@ QueueHandle_t xQueueHandle1 = NULL, xQueueHandle2 = NULL, xReceivedHandle = NULL
|
||||||
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
|
|
||||||
/* Create two queues that have a length of one - a requirement in order to call
|
/* Create two queues that have a length of one - a requirement in order to call
|
||||||
xQueueOverwrite. These will get deleted again when this test completes. */
|
* xQueueOverwrite. These will get deleted again when this test completes. */
|
||||||
xQueueHandle1 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
xQueueHandle1 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
||||||
configASSERT( xQueueHandle1 );
|
configASSERT( xQueueHandle1 );
|
||||||
xQueueHandle2 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
xQueueHandle2 = xQueueCreate( xLengthOfOne, sizeof( uint32_t ) );
|
||||||
|
|
@ -869,8 +900,9 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
xQueueAddToSet( xQueueHandle2, xQueueSet );
|
xQueueAddToSet( xQueueHandle2, xQueueSet );
|
||||||
|
|
||||||
/* Add an item using the first queue using the 'FromISR' version of the
|
/* Add an item using the first queue using the 'FromISR' version of the
|
||||||
overwrite function. */
|
* overwrite function. */
|
||||||
xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend1, NULL );
|
xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend1, NULL );
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
||||||
{
|
{
|
||||||
/* Expected one item in the queue set. */
|
/* Expected one item in the queue set. */
|
||||||
|
|
@ -878,17 +910,18 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle1 )
|
if( xReceivedHandle != xQueueHandle1 )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
||||||
held in the queue set. */
|
* held in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Next add an item to the second queue using the 'FromISR' version of the
|
/* Next add an item to the second queue using the 'FromISR' version of the
|
||||||
overwrite function. */
|
* overwrite function. */
|
||||||
xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend2, NULL );
|
xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend2, NULL );
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
{
|
{
|
||||||
/* Expected two items in the queue set. */
|
/* Expected two items in the queue set. */
|
||||||
|
|
@ -897,100 +930,108 @@ const UBaseType_t xLengthOfOne = ( UBaseType_t ) 1;
|
||||||
|
|
||||||
/* The head of the queue set should not have changed though. */
|
/* The head of the queue set should not have changed though. */
|
||||||
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
xQueuePeek( xQueueSet, &xReceivedHandle, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle1 )
|
if( xReceivedHandle != xQueueHandle1 )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
/* Wrote to xQueueHandle so expected xQueueHandle to be the handle
|
||||||
held in the queue set. */
|
* held in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Now overwrite the value in the queue and ensure the queue set state
|
/* Now overwrite the value in the queue and ensure the queue set state
|
||||||
doesn't change as the number of items in the queues within the set have
|
* doesn't change as the number of items in the queues within the set have
|
||||||
not changed. NOTE: after this queue 1 should hold ulValueToSend2 and queue
|
* not changed. NOTE: after this queue 1 should hold ulValueToSend2 and queue
|
||||||
2 should hold the value ulValueToSend1. */
|
* 2 should hold the value ulValueToSend1. */
|
||||||
xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
|
xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
|
||||||
{
|
|
||||||
/* Still expected two items in the queue set. */
|
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
|
||||||
}
|
|
||||||
xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
{
|
{
|
||||||
/* Still expected two items in the queue set. */
|
/* Still expected two items in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
|
{
|
||||||
|
/* Still expected two items in the queue set. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Repeat the above to ensure the queue set state doesn't change. */
|
/* Repeat the above to ensure the queue set state doesn't change. */
|
||||||
xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
|
xQueueOverwriteFromISR( xQueueHandle1, ( void * ) &ulValueToSend2, NULL );
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
|
||||||
{
|
|
||||||
/* Still expected two items in the queue set. */
|
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
|
||||||
}
|
|
||||||
xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
{
|
{
|
||||||
/* Still expected two items in the queue set. */
|
/* Still expected two items in the queue set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xQueueOverwriteFromISR( xQueueHandle2, ( void * ) &ulValueToSend1, NULL );
|
||||||
|
|
||||||
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 2 )
|
||||||
|
{
|
||||||
|
/* Still expected two items in the queue set. */
|
||||||
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now when reading from the queue set we expect the handle to the first
|
/* Now when reading from the queue set we expect the handle to the first
|
||||||
queue to be received first, and for that queue to hold ulValueToSend2 as the
|
* queue to be received first, and for that queue to hold ulValueToSend2 as the
|
||||||
originally written value was overwritten. Likewise the second handle received
|
* originally written value was overwritten. Likewise the second handle received
|
||||||
from the set should be that of the second queue, and that queue should hold
|
* from the set should be that of the second queue, and that queue should hold
|
||||||
ulValueToSend1 as the originally written value was overwritten. */
|
* ulValueToSend1 as the originally written value was overwritten. */
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle1 )
|
if( xReceivedHandle != xQueueHandle1 )
|
||||||
{
|
{
|
||||||
/* Wrote to xQueueHandle1 first so expected that handle to be read from
|
/* Wrote to xQueueHandle1 first so expected that handle to be read from
|
||||||
the set first. */
|
* the set first. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 1 )
|
||||||
{
|
{
|
||||||
/* One value was read from the set, so now only expect a single value
|
/* One value was read from the set, so now only expect a single value
|
||||||
in the set. */
|
* in the set. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( ulValueReceived != ulValueToSend2 )
|
if( ulValueReceived != ulValueToSend2 )
|
||||||
{
|
{
|
||||||
/* Unexpected value received from the queue. ulValueToSend1 was written
|
/* Unexpected value received from the queue. ulValueToSend1 was written
|
||||||
first, but then overwritten with ulValueToSend2; */
|
* first, but then overwritten with ulValueToSend2; */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != xQueueHandle2 )
|
if( xReceivedHandle != xQueueHandle2 )
|
||||||
{
|
{
|
||||||
/* xQueueHandle1 has already been removed from the set so expect only
|
/* xQueueHandle1 has already been removed from the set so expect only
|
||||||
xQueueHandle2 to be left. */
|
* xQueueHandle2 to be left. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
|
if( uxQueueMessagesWaiting( xQueueSet ) != ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
/* The last value was read from the set so don't expect any more. */
|
/* The last value was read from the set so don't expect any more. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
xQueueReceive( xReceivedHandle, &ulValueReceived, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( ulValueReceived != ulValueToSend1 )
|
if( ulValueReceived != ulValueToSend1 )
|
||||||
{
|
{
|
||||||
/* Unexpected value received from the queue. ulValueToSend2 was written
|
/* Unexpected value received from the queue. ulValueToSend2 was written
|
||||||
first, but then overwritten with ulValueToSend1. */
|
* first, but then overwritten with ulValueToSend1. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Should be anything in the queue set now. */
|
/* Should be anything in the queue set now. */
|
||||||
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
xReceivedHandle = xQueueSelectFromSet( xQueueSet, queuesetDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceivedHandle != NULL )
|
if( xReceivedHandle != NULL )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
|
@ -1011,18 +1052,19 @@ BaseType_t x;
|
||||||
uint32_t ulValueToSend = 0;
|
uint32_t ulValueToSend = 0;
|
||||||
|
|
||||||
/* Ensure the queues are created and the queue set configured before the
|
/* Ensure the queues are created and the queue set configured before the
|
||||||
sending task is unsuspended.
|
* sending task is unsuspended.
|
||||||
|
*
|
||||||
First Create the queue set such that it will be able to hold a message for
|
* First Create the queue set such that it will be able to hold a message for
|
||||||
every space in every queue in the set. */
|
* every space in every queue in the set. */
|
||||||
xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );
|
xQueueSet = xQueueCreateSet( queuesetNUM_QUEUES_IN_SET * queuesetQUEUE_LENGTH );
|
||||||
|
|
||||||
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
|
for( x = 0; x < queuesetNUM_QUEUES_IN_SET; x++ )
|
||||||
{
|
{
|
||||||
/* Create the queue and add it to the set. The queue is just holding
|
/* Create the queue and add it to the set. The queue is just holding
|
||||||
uint32_t value. */
|
* uint32_t value. */
|
||||||
xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) );
|
xQueues[ x ] = xQueueCreate( queuesetQUEUE_LENGTH, sizeof( uint32_t ) );
|
||||||
configASSERT( xQueues[ x ] );
|
configASSERT( xQueues[ x ] );
|
||||||
|
|
||||||
if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )
|
if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdPASS )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
|
@ -1030,7 +1072,7 @@ uint32_t ulValueToSend = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The queue has now been added to the queue set and cannot be added to
|
/* The queue has now been added to the queue set and cannot be added to
|
||||||
another. */
|
* another. */
|
||||||
if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL )
|
if( xQueueAddToSet( xQueues[ x ], xQueueSet ) != pdFAIL )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
|
|
@ -1039,11 +1081,11 @@ uint32_t ulValueToSend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to remove a queue from a queue set it does not belong
|
/* Attempt to remove a queue from a queue set it does not belong
|
||||||
to (NULL being passed as the queue set in this case). */
|
* to (NULL being passed as the queue set in this case). */
|
||||||
if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL )
|
if( xQueueRemoveFromSet( xQueues[ 0 ], NULL ) != pdFAIL )
|
||||||
{
|
{
|
||||||
/* It is not possible to successfully remove a queue from a queue
|
/* It is not possible to successfully remove a queue from a queue
|
||||||
set it does not belong to. */
|
* set it does not belong to. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1051,13 +1093,14 @@ uint32_t ulValueToSend = 0;
|
||||||
if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
|
if( xQueueRemoveFromSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* It should be possible to remove the queue from the queue set it
|
/* It should be possible to remove the queue from the queue set it
|
||||||
does belong to. */
|
* does belong to. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an item to the queue before attempting to add it back into the
|
/* Add an item to the queue before attempting to add it back into the
|
||||||
set. */
|
* set. */
|
||||||
xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 );
|
xQueueSend( xQueues[ 0 ], ( void * ) &ulValueToSend, 0 );
|
||||||
|
|
||||||
if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL )
|
if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdFAIL )
|
||||||
{
|
{
|
||||||
/* Should not be able to add a non-empty queue to a set. */
|
/* Should not be able to add a non-empty queue to a set. */
|
||||||
|
|
@ -1065,29 +1108,30 @@ uint32_t ulValueToSend = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the item from the queue before adding the queue back into the
|
/* Remove the item from the queue before adding the queue back into the
|
||||||
set so the dynamic tests can begin. */
|
* set so the dynamic tests can begin. */
|
||||||
xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 );
|
xQueueReceive( xQueues[ 0 ], &ulValueToSend, 0 );
|
||||||
|
|
||||||
if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
|
if( xQueueAddToSet( xQueues[ 0 ], xQueueSet ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* If the queue was successfully removed from the queue set then it
|
/* If the queue was successfully removed from the queue set then it
|
||||||
should be possible to add it back in again. */
|
* should be possible to add it back in again. */
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The task that sends to the queues is not running yet, so attempting to
|
/* The task that sends to the queues is not running yet, so attempting to
|
||||||
read from the queue set should fail. */
|
* read from the queue set should fail. */
|
||||||
if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL )
|
if( xQueueSelectFromSet( xQueueSet, queuesetSHORT_DELAY ) != NULL )
|
||||||
{
|
{
|
||||||
xQueueSetTasksStatus = pdFAIL;
|
xQueueSetTasksStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Testing the behaviour of queue sets when a queue overwrite operation is
|
/* Testing the behaviour of queue sets when a queue overwrite operation is
|
||||||
performed on a set member requires a special test as overwrites can only
|
* performed on a set member requires a special test as overwrites can only
|
||||||
be performed on queues that have a length of 1. */
|
* be performed on queues that have a length of 1. */
|
||||||
prvTestQueueOverwriteWithQueueSet();
|
prvTestQueueOverwriteWithQueueSet();
|
||||||
|
|
||||||
/* Test the case where two queues within a set are written to with
|
/* Test the case where two queues within a set are written to with
|
||||||
xQueueOverwrite(). */
|
* xQueueOverwrite(). */
|
||||||
prvTestQueueOverwriteOnTwoQueusInQueueSet();
|
prvTestQueueOverwriteOnTwoQueusInQueueSet();
|
||||||
prvTestQueueOverwriteFromISROnTwoQueusInQueueSet();
|
prvTestQueueOverwriteFromISROnTwoQueusInQueueSet();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ static QueueHandle_t xQueue = NULL;
|
||||||
static QueueSetHandle_t xQueueSet = NULL;
|
static QueueSetHandle_t xQueueSet = NULL;
|
||||||
|
|
||||||
/* Set to pdFAIL if an error is detected by any queue set task.
|
/* Set to pdFAIL if an error is detected by any queue set task.
|
||||||
ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */
|
* ulCycleCounter will only be incremented if xQueueSetTasksSatus equals pdPASS. */
|
||||||
static volatile BaseType_t xQueueSetPollStatus = pdPASS;
|
static volatile BaseType_t xQueueSetPollStatus = pdPASS;
|
||||||
|
|
||||||
/* Counter used to ensure the task is still running. */
|
/* Counter used to ensure the task is still running. */
|
||||||
|
|
@ -87,7 +87,7 @@ static uint32_t ulCycleCounter = 0;
|
||||||
void vStartQueueSetPollingTask( void )
|
void vStartQueueSetPollingTask( void )
|
||||||
{
|
{
|
||||||
/* Create the queue that is added to the set, the set, and add the queue to
|
/* Create the queue that is added to the set, the set, and add the queue to
|
||||||
the set. */
|
* the set. */
|
||||||
xQueue = xQueueCreate( setpollQUEUE_LENGTH, sizeof( uint32_t ) );
|
xQueue = xQueueCreate( setpollQUEUE_LENGTH, sizeof( uint32_t ) );
|
||||||
xQueueSet = xQueueCreateSet( setpollQUEUE_LENGTH );
|
xQueueSet = xQueueCreateSet( setpollQUEUE_LENGTH );
|
||||||
|
|
||||||
|
|
@ -112,14 +112,14 @@ QueueHandle_t xActivatedQueue;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Is a message waiting? A block time is not used to ensure the queue
|
/* Is a message waiting? A block time is not used to ensure the queue
|
||||||
set is polled while it is being written to from an interrupt. */
|
* set is polled while it is being written to from an interrupt. */
|
||||||
xActivatedQueue = xQueueSelectFromSet( xQueueSet, setpollDONT_BLOCK );
|
xActivatedQueue = xQueueSelectFromSet( xQueueSet, setpollDONT_BLOCK );
|
||||||
|
|
||||||
if( xActivatedQueue != NULL )
|
if( xActivatedQueue != NULL )
|
||||||
{
|
{
|
||||||
/* Reading from the queue should pass with a zero block time as
|
/* Reading from the queue should pass with a zero block time as
|
||||||
this task will only run when something has been posted to a task
|
* this task will only run when something has been posted to a task
|
||||||
in the queue set. */
|
* in the queue set. */
|
||||||
if( xQueueReceive( xActivatedQueue, &ulReceived, setpollDONT_BLOCK ) != pdPASS )
|
if( xQueueReceive( xActivatedQueue, &ulReceived, setpollDONT_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xQueueSetPollStatus = pdFAIL;
|
xQueueSetPollStatus = pdFAIL;
|
||||||
|
|
@ -148,8 +148,9 @@ void vQueueSetPollingInterruptAccess( void )
|
||||||
static uint32_t ulCallCount = 0, ulValueToSend = 0;
|
static uint32_t ulCallCount = 0, ulValueToSend = 0;
|
||||||
|
|
||||||
/* It is intended that this function is called from the tick hook
|
/* It is intended that this function is called from the tick hook
|
||||||
function, so each call is one tick period apart. */
|
* function, so each call is one tick period apart. */
|
||||||
ulCallCount++;
|
ulCallCount++;
|
||||||
|
|
||||||
if( ulCallCount > queuesetISR_TX_PERIOD )
|
if( ulCallCount > queuesetISR_TX_PERIOD )
|
||||||
{
|
{
|
||||||
ulCallCount = 0;
|
ulCallCount = 0;
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
#define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
#define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
|
|
||||||
/* The length of the queue, in items, not bytes, used in the queue static
|
/* The length of the queue, in items, not bytes, used in the queue static
|
||||||
allocation tests. */
|
* allocation tests. */
|
||||||
#define staticQUEUE_LENGTH_IN_ITEMS ( 5 )
|
#define staticQUEUE_LENGTH_IN_ITEMS ( 5 )
|
||||||
|
|
||||||
/* A block time of 0 simply means "don't block". */
|
/* A block time of 0 simply means "don't block". */
|
||||||
|
|
@ -164,7 +164,8 @@ static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore );
|
||||||
/*
|
/*
|
||||||
* Checks the basic operation of a binary semaphore after it has been created.
|
* Checks the basic operation of a binary semaphore after it has been created.
|
||||||
*/
|
*/
|
||||||
static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount );
|
static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore,
|
||||||
|
UBaseType_t uxMaxCount );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks the basic operation of an event group after it has been created.
|
* Checks the basic operation of an event group after it has been created.
|
||||||
|
|
@ -174,25 +175,25 @@ static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* StaticTask_t is a publicly accessible structure that has the same size and
|
/* StaticTask_t is a publicly accessible structure that has the same size and
|
||||||
alignment requirements as the real TCB structure. It is provided as a mechanism
|
* alignment requirements as the real TCB structure. It is provided as a mechanism
|
||||||
for applications to know the size of the TCB (which is dependent on the
|
* for applications to know the size of the TCB (which is dependent on the
|
||||||
architecture and configuration file settings) without breaking the strict data
|
* architecture and configuration file settings) without breaking the strict data
|
||||||
hiding policy by exposing the real TCB. This StaticTask_t variable is passed
|
* hiding policy by exposing the real TCB. This StaticTask_t variable is passed
|
||||||
into the xTaskCreateStatic() function that creates the
|
* into the xTaskCreateStatic() function that creates the
|
||||||
prvStaticallyAllocatedCreator() task, and will hold the TCB of the created
|
* prvStaticallyAllocatedCreator() task, and will hold the TCB of the created
|
||||||
tasks. */
|
* tasks. */
|
||||||
static StaticTask_t xCreatorTaskTCBBuffer;
|
static StaticTask_t xCreatorTaskTCBBuffer;
|
||||||
|
|
||||||
/* This is the stack that will be used by the prvStaticallyAllocatedCreator()
|
/* This is the stack that will be used by the prvStaticallyAllocatedCreator()
|
||||||
task, which is itself created using statically allocated buffers (so without any
|
* task, which is itself created using statically allocated buffers (so without any
|
||||||
dynamic memory allocation). */
|
* dynamic memory allocation). */
|
||||||
static StackType_t uxCreatorTaskStackBuffer[ staticCREATOR_TASK_STACK_SIZE ];
|
static StackType_t uxCreatorTaskStackBuffer[ staticCREATOR_TASK_STACK_SIZE ];
|
||||||
|
|
||||||
/* Used by the pseudo random number generating function. */
|
/* Used by the pseudo random number generating function. */
|
||||||
static uint32_t ulNextRand = 0;
|
static uint32_t ulNextRand = 0;
|
||||||
|
|
||||||
/* Used so a check task can ensure this test is still executing, and not
|
/* Used so a check task can ensure this test is still executing, and not
|
||||||
stalled. */
|
* stalled. */
|
||||||
static volatile UBaseType_t uxCycleCounter = 0;
|
static volatile UBaseType_t uxCycleCounter = 0;
|
||||||
|
|
||||||
/* A variable that gets set to pdTRUE if an error is detected. */
|
/* A variable that gets set to pdTRUE if an error is detected. */
|
||||||
|
|
@ -203,7 +204,7 @@ static volatile BaseType_t xErrorOccurred = pdFALSE;
|
||||||
void vStartStaticallyAllocatedTasks( void )
|
void vStartStaticallyAllocatedTasks( void )
|
||||||
{
|
{
|
||||||
/* Create a single task, which then repeatedly creates and deletes the other
|
/* Create a single task, which then repeatedly creates and deletes the other
|
||||||
RTOS objects using both statically and dynamically allocated RAM. */
|
* RTOS objects using both statically and dynamically allocated RAM. */
|
||||||
xTaskCreateStatic( prvStaticallyAllocatedCreator, /* The function that implements the task being created. */
|
xTaskCreateStatic( prvStaticallyAllocatedCreator, /* The function that implements the task being created. */
|
||||||
"StatCreate", /* Text name for the task - not used by the RTOS, its just to assist debugging. */
|
"StatCreate", /* Text name for the task - not used by the RTOS, its just to assist debugging. */
|
||||||
staticCREATOR_TASK_STACK_SIZE, /* Size of the buffer passed in as the stack - in words, not bytes! */
|
staticCREATOR_TASK_STACK_SIZE, /* Size of the buffer passed in as the stack - in words, not bytes! */
|
||||||
|
|
@ -222,14 +223,14 @@ static void prvStaticallyAllocatedCreator( void *pvParameters )
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Loop, running functions that create and delete the various RTOS
|
/* Loop, running functions that create and delete the various RTOS
|
||||||
objects that can be optionally created using either static or dynamic
|
* objects that can be optionally created using either static or dynamic
|
||||||
memory allocation. */
|
* memory allocation. */
|
||||||
prvCreateAndDeleteStaticallyAllocatedTasks();
|
prvCreateAndDeleteStaticallyAllocatedTasks();
|
||||||
prvCreateAndDeleteStaticallyAllocatedQueues();
|
prvCreateAndDeleteStaticallyAllocatedQueues();
|
||||||
|
|
||||||
/* Delay to ensure lower priority tasks get CPU time, and increment the
|
/* Delay to ensure lower priority tasks get CPU time, and increment the
|
||||||
cycle counter so a 'check' task can determine that this task is still
|
* cycle counter so a 'check' task can determine that this task is still
|
||||||
executing. */
|
* executing. */
|
||||||
vTaskDelay( prvGetNextDelayTime() );
|
vTaskDelay( prvGetNextDelayTime() );
|
||||||
uxCycleCounter++;
|
uxCycleCounter++;
|
||||||
|
|
||||||
|
|
@ -257,26 +258,26 @@ SemaphoreHandle_t xSemaphore;
|
||||||
const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;
|
const UBaseType_t uxMaxCount = ( UBaseType_t ) 10;
|
||||||
|
|
||||||
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
||||||
and alignment requirements as the real semaphore structure. It is provided as a
|
* and alignment requirements as the real semaphore structure. It is provided as a
|
||||||
mechanism for applications to know the size of the semaphore (which is dependent
|
* mechanism for applications to know the size of the semaphore (which is dependent
|
||||||
on the architecture and configuration file settings) without breaking the strict
|
* on the architecture and configuration file settings) without breaking the strict
|
||||||
data hiding policy by exposing the real semaphore internals. This
|
* data hiding policy by exposing the real semaphore internals. This
|
||||||
StaticSemaphore_t variable is passed into the xSemaphoreCreateCountingStatic()
|
* StaticSemaphore_t variable is passed into the xSemaphoreCreateCountingStatic()
|
||||||
function calls within this function. NOTE: In most usage scenarios now it is
|
* function calls within this function. NOTE: In most usage scenarios now it is
|
||||||
faster and more memory efficient to use a direct to task notification instead of
|
* faster and more memory efficient to use a direct to task notification instead of
|
||||||
a counting semaphore. http://www.freertos.org/RTOS-task-notifications.html */
|
* a counting semaphore. http://www.freertos.org/RTOS-task-notifications.html */
|
||||||
StaticSemaphore_t xSemaphoreBuffer;
|
StaticSemaphore_t xSemaphoreBuffer;
|
||||||
|
|
||||||
/* Create the semaphore. xSemaphoreCreateCountingStatic() has one more
|
/* Create the semaphore. xSemaphoreCreateCountingStatic() has one more
|
||||||
parameter than the usual xSemaphoreCreateCounting() function. The parameter
|
* parameter than the usual xSemaphoreCreateCounting() function. The parameter
|
||||||
is a pointer to the pre-allocated StaticSemaphore_t structure, which will
|
* is a pointer to the pre-allocated StaticSemaphore_t structure, which will
|
||||||
hold information on the semaphore in an anonymous way. If the pointer is
|
* hold information on the semaphore in an anonymous way. If the pointer is
|
||||||
passed as NULL then the structure will be allocated dynamically, just as
|
* passed as NULL then the structure will be allocated dynamically, just as
|
||||||
when xSemaphoreCreateCounting() is called. */
|
* when xSemaphoreCreateCounting() is called. */
|
||||||
xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, &xSemaphoreBuffer );
|
xSemaphore = xSemaphoreCreateCountingStatic( uxMaxCount, 0, &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* The semaphore handle should equal the static semaphore structure passed
|
/* The semaphore handle should equal the static semaphore structure passed
|
||||||
into the xSemaphoreCreateBinaryStatic() function. */
|
* into the xSemaphoreCreateBinaryStatic() function. */
|
||||||
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
|
/* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
|
||||||
|
|
@ -288,8 +289,8 @@ StaticSemaphore_t xSemaphoreBuffer;
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
/* Now do the same but using dynamically allocated buffers to ensure the
|
/* Now do the same but using dynamically allocated buffers to ensure the
|
||||||
delete functions are working correctly in both the static and dynamic
|
* delete functions are working correctly in both the static and dynamic
|
||||||
allocation cases. */
|
* allocation cases. */
|
||||||
xSemaphore = xSemaphoreCreateCounting( uxMaxCount, 0 );
|
xSemaphore = xSemaphoreCreateCounting( uxMaxCount, 0 );
|
||||||
configASSERT( xSemaphore != NULL );
|
configASSERT( xSemaphore != NULL );
|
||||||
prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );
|
prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );
|
||||||
|
|
@ -304,36 +305,36 @@ static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void )
|
||||||
SemaphoreHandle_t xSemaphore;
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
||||||
and alignment requirements as the real semaphore structure. It is provided as a
|
* and alignment requirements as the real semaphore structure. It is provided as a
|
||||||
mechanism for applications to know the size of the semaphore (which is dependent
|
* mechanism for applications to know the size of the semaphore (which is dependent
|
||||||
on the architecture and configuration file settings) without breaking the strict
|
* on the architecture and configuration file settings) without breaking the strict
|
||||||
data hiding policy by exposing the real semaphore internals. This
|
* data hiding policy by exposing the real semaphore internals. This
|
||||||
StaticSemaphore_t variable is passed into the
|
* StaticSemaphore_t variable is passed into the
|
||||||
xSemaphoreCreateRecursiveMutexStatic() function calls within this function. */
|
* xSemaphoreCreateRecursiveMutexStatic() function calls within this function. */
|
||||||
StaticSemaphore_t xSemaphoreBuffer;
|
StaticSemaphore_t xSemaphoreBuffer;
|
||||||
|
|
||||||
/* Create the semaphore. xSemaphoreCreateRecursiveMutexStatic() has one
|
/* Create the semaphore. xSemaphoreCreateRecursiveMutexStatic() has one
|
||||||
more parameter than the usual xSemaphoreCreateRecursiveMutex() function.
|
* more parameter than the usual xSemaphoreCreateRecursiveMutex() function.
|
||||||
The parameter is a pointer to the pre-allocated StaticSemaphore_t structure,
|
* The parameter is a pointer to the pre-allocated StaticSemaphore_t structure,
|
||||||
which will hold information on the semaphore in an anonymous way. If the
|
* which will hold information on the semaphore in an anonymous way. If the
|
||||||
pointer is passed as NULL then the structure will be allocated dynamically,
|
* pointer is passed as NULL then the structure will be allocated dynamically,
|
||||||
just as when xSemaphoreCreateRecursiveMutex() is called. */
|
* just as when xSemaphoreCreateRecursiveMutex() is called. */
|
||||||
xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );
|
xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* The semaphore handle should equal the static semaphore structure passed
|
/* The semaphore handle should equal the static semaphore structure passed
|
||||||
into the xSemaphoreCreateBinaryStatic() function. */
|
* into the xSemaphoreCreateBinaryStatic() function. */
|
||||||
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* Ensure the semaphore passes a few sanity checks as a valid
|
/* Ensure the semaphore passes a few sanity checks as a valid
|
||||||
recursive semaphore. */
|
* recursive semaphore. */
|
||||||
prvSanityCheckCreatedRecursiveMutex( xSemaphore );
|
prvSanityCheckCreatedRecursiveMutex( xSemaphore );
|
||||||
|
|
||||||
/* Delete the semaphore again so the buffers can be reused. */
|
/* Delete the semaphore again so the buffers can be reused. */
|
||||||
vSemaphoreDelete( xSemaphore );
|
vSemaphoreDelete( xSemaphore );
|
||||||
|
|
||||||
/* Now do the same using dynamically allocated buffers to ensure the delete
|
/* Now do the same using dynamically allocated buffers to ensure the delete
|
||||||
functions are working correctly in both the static and dynamic memory
|
* functions are working correctly in both the static and dynamic memory
|
||||||
allocation cases. */
|
* allocation cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
xSemaphore = xSemaphoreCreateRecursiveMutex();
|
xSemaphore = xSemaphoreCreateRecursiveMutex();
|
||||||
|
|
@ -350,34 +351,34 @@ static void prvCreateAndDeleteStaticallyAllocatedQueues( void )
|
||||||
QueueHandle_t xQueue;
|
QueueHandle_t xQueue;
|
||||||
|
|
||||||
/* StaticQueue_t is a publicly accessible structure that has the same size and
|
/* StaticQueue_t is a publicly accessible structure that has the same size and
|
||||||
alignment requirements as the real queue structure. It is provided as a
|
* alignment requirements as the real queue structure. It is provided as a
|
||||||
mechanism for applications to know the size of the queue (which is dependent on
|
* mechanism for applications to know the size of the queue (which is dependent on
|
||||||
the architecture and configuration file settings) without breaking the strict
|
* the architecture and configuration file settings) without breaking the strict
|
||||||
data hiding policy by exposing the real queue internals. This StaticQueue_t
|
* data hiding policy by exposing the real queue internals. This StaticQueue_t
|
||||||
variable is passed into the xQueueCreateStatic() function calls within this
|
* variable is passed into the xQueueCreateStatic() function calls within this
|
||||||
function. */
|
* function. */
|
||||||
static StaticQueue_t xStaticQueue;
|
static StaticQueue_t xStaticQueue;
|
||||||
|
|
||||||
/* The queue storage area must be large enough to hold the maximum number of
|
/* The queue storage area must be large enough to hold the maximum number of
|
||||||
items it is possible for the queue to hold at any one time, which equals the
|
* items it is possible for the queue to hold at any one time, which equals the
|
||||||
queue length (in items, not bytes) multiplied by the size of each item. In this
|
* queue length (in items, not bytes) multiplied by the size of each item. In this
|
||||||
case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items. See
|
* case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items. See
|
||||||
http://www.freertos.org/Embedded-RTOS-Queues.html */
|
* http://www.freertos.org/Embedded-RTOS-Queues.html */
|
||||||
static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];
|
static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ];
|
||||||
|
|
||||||
/* Create the queue. xQueueCreateStatic() has two more parameters than the
|
/* Create the queue. xQueueCreateStatic() has two more parameters than the
|
||||||
usual xQueueCreate() function. The first new parameter is a pointer to the
|
* usual xQueueCreate() function. The first new parameter is a pointer to the
|
||||||
pre-allocated queue storage area. The second new parameter is a pointer to
|
* pre-allocated queue storage area. The second new parameter is a pointer to
|
||||||
the StaticQueue_t structure that will hold the queue state information in
|
* the StaticQueue_t structure that will hold the queue state information in
|
||||||
an anonymous way. If the two pointers are passed as NULL then the data
|
* an anonymous way. If the two pointers are passed as NULL then the data
|
||||||
will be allocated dynamically as if xQueueCreate() had been called. */
|
* will be allocated dynamically as if xQueueCreate() had been called. */
|
||||||
xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */
|
xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */
|
||||||
sizeof( uint64_t ), /* The size of each item. */
|
sizeof( uint64_t ), /* The size of each item. */
|
||||||
ucQueueStorageArea, /* The buffer used to hold items within the queue. */
|
ucQueueStorageArea, /* The buffer used to hold items within the queue. */
|
||||||
&xStaticQueue ); /* The static queue structure that will hold the state of the queue. */
|
&xStaticQueue ); /* The static queue structure that will hold the state of the queue. */
|
||||||
|
|
||||||
/* The queue handle should equal the static queue structure passed into the
|
/* The queue handle should equal the static queue structure passed into the
|
||||||
xQueueCreateStatic() function. */
|
* xQueueCreateStatic() function. */
|
||||||
configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );
|
configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue );
|
||||||
|
|
||||||
/* Ensure the queue passes a few sanity checks as a valid queue. */
|
/* Ensure the queue passes a few sanity checks as a valid queue. */
|
||||||
|
|
@ -387,15 +388,15 @@ static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_
|
||||||
vQueueDelete( xQueue );
|
vQueueDelete( xQueue );
|
||||||
|
|
||||||
/* Now do the same using a dynamically allocated queue to ensure the delete
|
/* Now do the same using a dynamically allocated queue to ensure the delete
|
||||||
function is working correctly in both the static and dynamic memory
|
* function is working correctly in both the static and dynamic memory
|
||||||
allocation cases. */
|
* allocation cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
xQueue = xQueueCreate( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */
|
xQueue = xQueueCreate( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */
|
||||||
sizeof( uint64_t ) ); /* The size of each item. */
|
sizeof( uint64_t ) ); /* The size of each item. */
|
||||||
|
|
||||||
/* The queue handle should equal the static queue structure passed into the
|
/* The queue handle should equal the static queue structure passed into the
|
||||||
xQueueCreateStatic() function. */
|
* xQueueCreateStatic() function. */
|
||||||
configASSERT( xQueue != NULL );
|
configASSERT( xQueue != NULL );
|
||||||
|
|
||||||
/* Ensure the queue passes a few sanity checks as a valid queue. */
|
/* Ensure the queue passes a few sanity checks as a valid queue. */
|
||||||
|
|
@ -404,7 +405,7 @@ static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_
|
||||||
/* Delete the queue again so the buffers can be reused. */
|
/* Delete the queue again so the buffers can be reused. */
|
||||||
vQueueDelete( xQueue );
|
vQueueDelete( xQueue );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -414,28 +415,28 @@ SemaphoreHandle_t xSemaphore;
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
|
|
||||||
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
||||||
and alignment requirements as the real semaphore structure. It is provided as a
|
* and alignment requirements as the real semaphore structure. It is provided as a
|
||||||
mechanism for applications to know the size of the semaphore (which is dependent
|
* mechanism for applications to know the size of the semaphore (which is dependent
|
||||||
on the architecture and configuration file settings) without breaking the strict
|
* on the architecture and configuration file settings) without breaking the strict
|
||||||
data hiding policy by exposing the real semaphore internals. This
|
* data hiding policy by exposing the real semaphore internals. This
|
||||||
StaticSemaphore_t variable is passed into the xSemaphoreCreateMutexStatic()
|
* StaticSemaphore_t variable is passed into the xSemaphoreCreateMutexStatic()
|
||||||
function calls within this function. */
|
* function calls within this function. */
|
||||||
StaticSemaphore_t xSemaphoreBuffer;
|
StaticSemaphore_t xSemaphoreBuffer;
|
||||||
|
|
||||||
/* Create the semaphore. xSemaphoreCreateMutexStatic() has one more
|
/* Create the semaphore. xSemaphoreCreateMutexStatic() has one more
|
||||||
parameter than the usual xSemaphoreCreateMutex() function. The parameter
|
* parameter than the usual xSemaphoreCreateMutex() function. The parameter
|
||||||
is a pointer to the pre-allocated StaticSemaphore_t structure, which will
|
* is a pointer to the pre-allocated StaticSemaphore_t structure, which will
|
||||||
hold information on the semaphore in an anonymous way. If the pointer is
|
* hold information on the semaphore in an anonymous way. If the pointer is
|
||||||
passed as NULL then the structure will be allocated dynamically, just as
|
* passed as NULL then the structure will be allocated dynamically, just as
|
||||||
when xSemaphoreCreateMutex() is called. */
|
* when xSemaphoreCreateMutex() is called. */
|
||||||
xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );
|
xSemaphore = xSemaphoreCreateMutexStatic( &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* The semaphore handle should equal the static semaphore structure passed
|
/* The semaphore handle should equal the static semaphore structure passed
|
||||||
into the xSemaphoreCreateMutexStatic() function. */
|
* into the xSemaphoreCreateMutexStatic() function. */
|
||||||
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* Take the mutex so the mutex is in the state expected by the
|
/* Take the mutex so the mutex is in the state expected by the
|
||||||
prvSanityCheckCreatedSemaphore() function. */
|
* prvSanityCheckCreatedSemaphore() function. */
|
||||||
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != pdPASS )
|
if( xReturned != pdPASS )
|
||||||
|
|
@ -450,18 +451,18 @@ StaticSemaphore_t xSemaphoreBuffer;
|
||||||
vSemaphoreDelete( xSemaphore );
|
vSemaphoreDelete( xSemaphore );
|
||||||
|
|
||||||
/* Now do the same using a dynamically allocated mutex to ensure the delete
|
/* Now do the same using a dynamically allocated mutex to ensure the delete
|
||||||
function is working correctly in both the static and dynamic allocation
|
* function is working correctly in both the static and dynamic allocation
|
||||||
cases. */
|
* cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
xSemaphore = xSemaphoreCreateMutex();
|
xSemaphore = xSemaphoreCreateMutex();
|
||||||
|
|
||||||
/* The semaphore handle should equal the static semaphore structure
|
/* The semaphore handle should equal the static semaphore structure
|
||||||
passed into the xSemaphoreCreateMutexStatic() function. */
|
* passed into the xSemaphoreCreateMutexStatic() function. */
|
||||||
configASSERT( xSemaphore != NULL );
|
configASSERT( xSemaphore != NULL );
|
||||||
|
|
||||||
/* Take the mutex so the mutex is in the state expected by the
|
/* Take the mutex so the mutex is in the state expected by the
|
||||||
prvSanityCheckCreatedSemaphore() function. */
|
* prvSanityCheckCreatedSemaphore() function. */
|
||||||
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != pdPASS )
|
if( xReturned != pdPASS )
|
||||||
|
|
@ -475,7 +476,7 @@ StaticSemaphore_t xSemaphoreBuffer;
|
||||||
/* Delete the semaphore again so the buffers can be reused. */
|
/* Delete the semaphore again so the buffers can be reused. */
|
||||||
vSemaphoreDelete( xSemaphore );
|
vSemaphoreDelete( xSemaphore );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -484,26 +485,26 @@ static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void )
|
||||||
SemaphoreHandle_t xSemaphore;
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
||||||
and alignment requirements as the real semaphore structure. It is provided as a
|
* and alignment requirements as the real semaphore structure. It is provided as a
|
||||||
mechanism for applications to know the size of the semaphore (which is dependent
|
* mechanism for applications to know the size of the semaphore (which is dependent
|
||||||
on the architecture and configuration file settings) without breaking the strict
|
* on the architecture and configuration file settings) without breaking the strict
|
||||||
data hiding policy by exposing the real semaphore internals. This
|
* data hiding policy by exposing the real semaphore internals. This
|
||||||
StaticSemaphore_t variable is passed into the xSemaphoreCreateBinaryStatic()
|
* StaticSemaphore_t variable is passed into the xSemaphoreCreateBinaryStatic()
|
||||||
function calls within this function. NOTE: In most usage scenarios now it is
|
* function calls within this function. NOTE: In most usage scenarios now it is
|
||||||
faster and more memory efficient to use a direct to task notification instead of
|
* faster and more memory efficient to use a direct to task notification instead of
|
||||||
a binary semaphore. http://www.freertos.org/RTOS-task-notifications.html */
|
* a binary semaphore. http://www.freertos.org/RTOS-task-notifications.html */
|
||||||
StaticSemaphore_t xSemaphoreBuffer;
|
StaticSemaphore_t xSemaphoreBuffer;
|
||||||
|
|
||||||
/* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more
|
/* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more
|
||||||
parameter than the usual xSemaphoreCreateBinary() function. The parameter
|
* parameter than the usual xSemaphoreCreateBinary() function. The parameter
|
||||||
is a pointer to the pre-allocated StaticSemaphore_t structure, which will
|
* is a pointer to the pre-allocated StaticSemaphore_t structure, which will
|
||||||
hold information on the semaphore in an anonymous way. If the pointer is
|
* hold information on the semaphore in an anonymous way. If the pointer is
|
||||||
passed as NULL then the structure will be allocated dynamically, just as
|
* passed as NULL then the structure will be allocated dynamically, just as
|
||||||
when xSemaphoreCreateBinary() is called. */
|
* when xSemaphoreCreateBinary() is called. */
|
||||||
xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
|
xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* The semaphore handle should equal the static semaphore structure passed
|
/* The semaphore handle should equal the static semaphore structure passed
|
||||||
into the xSemaphoreCreateBinaryStatic() function. */
|
* into the xSemaphoreCreateBinaryStatic() function. */
|
||||||
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer );
|
||||||
|
|
||||||
/* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
|
/* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
|
||||||
|
|
@ -513,8 +514,8 @@ StaticSemaphore_t xSemaphoreBuffer;
|
||||||
vSemaphoreDelete( xSemaphore );
|
vSemaphoreDelete( xSemaphore );
|
||||||
|
|
||||||
/* Now do the same using a dynamically allocated semaphore to check the
|
/* Now do the same using a dynamically allocated semaphore to check the
|
||||||
delete function is working correctly in both the static and dynamic
|
* delete function is working correctly in both the static and dynamic
|
||||||
allocation cases. */
|
* allocation cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
xSemaphore = xSemaphoreCreateBinary();
|
xSemaphore = xSemaphoreCreateBinary();
|
||||||
|
|
@ -525,14 +526,14 @@ StaticSemaphore_t xSemaphoreBuffer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* There isn't a static version of the old and deprecated
|
/* There isn't a static version of the old and deprecated
|
||||||
vSemaphoreCreateBinary() macro (because its deprecated!), but check it is
|
* vSemaphoreCreateBinary() macro (because its deprecated!), but check it is
|
||||||
still functioning correctly. */
|
* still functioning correctly. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
vSemaphoreCreateBinary( xSemaphore );
|
vSemaphoreCreateBinary( xSemaphore );
|
||||||
|
|
||||||
/* The macro starts with the binary semaphore available, but the test
|
/* The macro starts with the binary semaphore available, but the test
|
||||||
function expects it to be unavailable. */
|
* function expects it to be unavailable. */
|
||||||
if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )
|
if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -541,7 +542,7 @@ StaticSemaphore_t xSemaphoreBuffer;
|
||||||
prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
|
prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
|
||||||
vSemaphoreDelete( xSemaphore );
|
vSemaphoreDelete( xSemaphore );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -551,19 +552,19 @@ UBaseType_t *puxVariableToIncrement;
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
|
|
||||||
/* The timer callback just demonstrates it is executing by incrementing a
|
/* The timer callback just demonstrates it is executing by incrementing a
|
||||||
variable - the address of which is passed into the timer as its ID. Obtain
|
* variable - the address of which is passed into the timer as its ID. Obtain
|
||||||
the address of the variable to increment. */
|
* the address of the variable to increment. */
|
||||||
puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );
|
puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );
|
||||||
|
|
||||||
/* Increment the variable to show the timer callback has executed. */
|
/* Increment the variable to show the timer callback has executed. */
|
||||||
( *puxVariableToIncrement )++;
|
( *puxVariableToIncrement )++;
|
||||||
|
|
||||||
/* If this callback has executed the required number of times, stop the
|
/* If this callback has executed the required number of times, stop the
|
||||||
timer. */
|
* timer. */
|
||||||
if( *puxVariableToIncrement == staticMAX_TIMER_CALLBACK_EXECUTIONS )
|
if( *puxVariableToIncrement == staticMAX_TIMER_CALLBACK_EXECUTIONS )
|
||||||
{
|
{
|
||||||
/* This is called from a timer callback so must not block. See
|
/* This is called from a timer callback so must not block. See
|
||||||
http://www.FreeRTOS.org/FreeRTOS-timers-xTimerStop.html */
|
* http://www.FreeRTOS.org/FreeRTOS-timers-xTimerStop.html */
|
||||||
xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );
|
xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != pdPASS )
|
if( xReturned != pdPASS )
|
||||||
|
|
@ -582,19 +583,19 @@ const TickType_t xTimerPeriod = pdMS_TO_TICKS( 20 );
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
|
|
||||||
/* StaticTimer_t is a publicly accessible structure that has the same size
|
/* StaticTimer_t is a publicly accessible structure that has the same size
|
||||||
and alignment requirements as the real timer structure. It is provided as a
|
* and alignment requirements as the real timer structure. It is provided as a
|
||||||
mechanism for applications to know the size of the timer structure (which is
|
* mechanism for applications to know the size of the timer structure (which is
|
||||||
dependent on the architecture and configuration file settings) without breaking
|
* dependent on the architecture and configuration file settings) without breaking
|
||||||
the strict data hiding policy by exposing the real timer internals. This
|
* the strict data hiding policy by exposing the real timer internals. This
|
||||||
StaticTimer_t variable is passed into the xTimerCreateStatic() function calls
|
* StaticTimer_t variable is passed into the xTimerCreateStatic() function calls
|
||||||
within this function. */
|
* within this function. */
|
||||||
StaticTimer_t xTimerBuffer;
|
StaticTimer_t xTimerBuffer;
|
||||||
|
|
||||||
/* Create the software time. xTimerCreateStatic() has an extra parameter
|
/* Create the software time. xTimerCreateStatic() has an extra parameter
|
||||||
than the normal xTimerCreate() API function. The parameter is a pointer to
|
* than the normal xTimerCreate() API function. The parameter is a pointer to
|
||||||
the StaticTimer_t structure that will hold the software timer structure. If
|
* the StaticTimer_t structure that will hold the software timer structure. If
|
||||||
the parameter is passed as NULL then the structure will be allocated
|
* the parameter is passed as NULL then the structure will be allocated
|
||||||
dynamically, just as if xTimerCreate() had been called. */
|
* dynamically, just as if xTimerCreate() had been called. */
|
||||||
xTimer = xTimerCreateStatic( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */
|
xTimer = xTimerCreateStatic( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */
|
||||||
xTimerPeriod, /* The period of the timer in ticks. */
|
xTimerPeriod, /* The period of the timer in ticks. */
|
||||||
pdTRUE, /* This is an auto-reload timer. */
|
pdTRUE, /* This is an auto-reload timer. */
|
||||||
|
|
@ -603,11 +604,11 @@ StaticTimer_t xTimerBuffer;
|
||||||
&xTimerBuffer ); /* The buffer that will hold the software timer structure. */
|
&xTimerBuffer ); /* The buffer that will hold the software timer structure. */
|
||||||
|
|
||||||
/* The timer handle should equal the static timer structure passed into the
|
/* The timer handle should equal the static timer structure passed into the
|
||||||
xTimerCreateStatic() function. */
|
* xTimerCreateStatic() function. */
|
||||||
configASSERT( xTimer == ( TimerHandle_t ) &xTimerBuffer );
|
configASSERT( xTimer == ( TimerHandle_t ) &xTimerBuffer );
|
||||||
|
|
||||||
/* Set the variable to 0, wait for a few timer periods to expire, then check
|
/* Set the variable to 0, wait for a few timer periods to expire, then check
|
||||||
the timer callback has incremented the variable to the expected value. */
|
* the timer callback has incremented the variable to the expected value. */
|
||||||
uxVariableToIncrement = 0;
|
uxVariableToIncrement = 0;
|
||||||
|
|
||||||
/* This is a low priority so a block time should not be needed. */
|
/* This is a low priority so a block time should not be needed. */
|
||||||
|
|
@ -621,7 +622,7 @@ StaticTimer_t xTimerBuffer;
|
||||||
vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );
|
vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );
|
||||||
|
|
||||||
/* By now the timer should have expired staticMAX_TIMER_CALLBACK_EXECUTIONS
|
/* By now the timer should have expired staticMAX_TIMER_CALLBACK_EXECUTIONS
|
||||||
times, and then stopped itself. */
|
* times, and then stopped itself. */
|
||||||
if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )
|
if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -631,7 +632,7 @@ StaticTimer_t xTimerBuffer;
|
||||||
xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );
|
xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );
|
||||||
|
|
||||||
/* Again, as this is a low priority task it is expected that the timer
|
/* Again, as this is a low priority task it is expected that the timer
|
||||||
command will have been sent even without a block time being used. */
|
* command will have been sent even without a block time being used. */
|
||||||
if( xReturned != pdPASS )
|
if( xReturned != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -641,8 +642,8 @@ StaticTimer_t xTimerBuffer;
|
||||||
uxCycleCounter++;
|
uxCycleCounter++;
|
||||||
|
|
||||||
/* Now do the same using a dynamically allocated software timer to ensure
|
/* Now do the same using a dynamically allocated software timer to ensure
|
||||||
the delete function is working correctly in both the static and dynamic
|
* the delete function is working correctly in both the static and dynamic
|
||||||
allocation cases. */
|
* allocation cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
xTimer = xTimerCreate( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */
|
xTimer = xTimerCreate( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */
|
||||||
|
|
@ -675,7 +676,7 @@ StaticTimer_t xTimerBuffer;
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -684,34 +685,34 @@ static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void )
|
||||||
EventGroupHandle_t xEventGroup;
|
EventGroupHandle_t xEventGroup;
|
||||||
|
|
||||||
/* StaticEventGroup_t is a publicly accessible structure that has the same size
|
/* StaticEventGroup_t is a publicly accessible structure that has the same size
|
||||||
and alignment requirements as the real event group structure. It is provided as
|
* and alignment requirements as the real event group structure. It is provided as
|
||||||
a mechanism for applications to know the size of the event group (which is
|
* a mechanism for applications to know the size of the event group (which is
|
||||||
dependent on the architecture and configuration file settings) without breaking
|
* dependent on the architecture and configuration file settings) without breaking
|
||||||
the strict data hiding policy by exposing the real event group internals. This
|
* the strict data hiding policy by exposing the real event group internals. This
|
||||||
StaticEventGroup_t variable is passed into the xSemaphoreCreateEventGroupStatic()
|
* StaticEventGroup_t variable is passed into the xSemaphoreCreateEventGroupStatic()
|
||||||
function calls within this function. */
|
* function calls within this function. */
|
||||||
StaticEventGroup_t xEventGroupBuffer;
|
StaticEventGroup_t xEventGroupBuffer;
|
||||||
|
|
||||||
/* Create the event group. xEventGroupCreateStatic() has an extra parameter
|
/* Create the event group. xEventGroupCreateStatic() has an extra parameter
|
||||||
than the normal xEventGroupCreate() API function. The parameter is a
|
* than the normal xEventGroupCreate() API function. The parameter is a
|
||||||
pointer to the StaticEventGroup_t structure that will hold the event group
|
* pointer to the StaticEventGroup_t structure that will hold the event group
|
||||||
structure. */
|
* structure. */
|
||||||
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||||
|
|
||||||
/* The event group handle should equal the static event group structure
|
/* The event group handle should equal the static event group structure
|
||||||
passed into the xEventGroupCreateStatic() function. */
|
* passed into the xEventGroupCreateStatic() function. */
|
||||||
configASSERT( xEventGroup == ( EventGroupHandle_t ) &xEventGroupBuffer );
|
configASSERT( xEventGroup == ( EventGroupHandle_t ) &xEventGroupBuffer );
|
||||||
|
|
||||||
/* Ensure the event group passes a few sanity checks as a valid event
|
/* Ensure the event group passes a few sanity checks as a valid event
|
||||||
group. */
|
* group. */
|
||||||
prvSanityCheckCreatedEventGroup( xEventGroup );
|
prvSanityCheckCreatedEventGroup( xEventGroup );
|
||||||
|
|
||||||
/* Delete the event group again so the buffers can be reused. */
|
/* Delete the event group again so the buffers can be reused. */
|
||||||
vEventGroupDelete( xEventGroup );
|
vEventGroupDelete( xEventGroup );
|
||||||
|
|
||||||
/* Now do the same using a dynamically allocated event group to ensure the
|
/* Now do the same using a dynamically allocated event group to ensure the
|
||||||
delete function is working correctly in both the static and dynamic
|
* delete function is working correctly in both the static and dynamic
|
||||||
allocation cases. */
|
* allocation cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
xEventGroup = xEventGroupCreate();
|
xEventGroup = xEventGroupCreate();
|
||||||
|
|
@ -728,23 +729,23 @@ static void prvCreateAndDeleteStaticallyAllocatedTasks( void )
|
||||||
TaskHandle_t xCreatedTask;
|
TaskHandle_t xCreatedTask;
|
||||||
|
|
||||||
/* The variable that will hold the TCB of tasks created by this function. See
|
/* The variable that will hold the TCB of tasks created by this function. See
|
||||||
the comments above the declaration of the xCreatorTaskTCBBuffer variable for
|
* the comments above the declaration of the xCreatorTaskTCBBuffer variable for
|
||||||
more information. NOTE: This is not static so relies on the tasks that use it
|
* more information. NOTE: This is not static so relies on the tasks that use it
|
||||||
being deleted before this function returns and deallocates its stack. That will
|
* being deleted before this function returns and deallocates its stack. That will
|
||||||
only be the case if configUSE_PREEMPTION is set to 1. */
|
* only be the case if configUSE_PREEMPTION is set to 1. */
|
||||||
StaticTask_t xTCBBuffer;
|
StaticTask_t xTCBBuffer;
|
||||||
|
|
||||||
/* This buffer that will be used as the stack of tasks created by this function.
|
/* This buffer that will be used as the stack of tasks created by this function.
|
||||||
See the comments above the declaration of the uxCreatorTaskStackBuffer[] array
|
* See the comments above the declaration of the uxCreatorTaskStackBuffer[] array
|
||||||
above for more information. */
|
* above for more information. */
|
||||||
static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
||||||
|
|
||||||
/* Create the task. xTaskCreateStatic() has two more parameters than
|
/* Create the task. xTaskCreateStatic() has two more parameters than
|
||||||
the usual xTaskCreate() function. The first new parameter is a pointer to
|
* the usual xTaskCreate() function. The first new parameter is a pointer to
|
||||||
the pre-allocated stack. The second new parameter is a pointer to the
|
* the pre-allocated stack. The second new parameter is a pointer to the
|
||||||
StaticTask_t structure that will hold the task's TCB. If both pointers are
|
* StaticTask_t structure that will hold the task's TCB. If both pointers are
|
||||||
passed as NULL then the respective object will be allocated dynamically as
|
* passed as NULL then the respective object will be allocated dynamically as
|
||||||
if xTaskCreate() had been called. */
|
* if xTaskCreate() had been called. */
|
||||||
xCreatedTask = xTaskCreateStatic(
|
xCreatedTask = xTaskCreateStatic(
|
||||||
prvStaticallyAllocatedTask, /* Function that implements the task. */
|
prvStaticallyAllocatedTask, /* Function that implements the task. */
|
||||||
"Static", /* Human readable name for the task. */
|
"Static", /* Human readable name for the task. */
|
||||||
|
|
@ -762,7 +763,7 @@ static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
||||||
else if( eTaskGetState( xCreatedTask ) != eSuspended )
|
else if( eTaskGetState( xCreatedTask ) != eSuspended )
|
||||||
{
|
{
|
||||||
/* The created task had a higher priority so should have executed and
|
/* The created task had a higher priority so should have executed and
|
||||||
suspended itself by now. */
|
* suspended itself by now. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -771,8 +772,8 @@ static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now do the same using a dynamically allocated task to ensure the delete
|
/* Now do the same using a dynamically allocated task to ensure the delete
|
||||||
function is working correctly in both the static and dynamic allocation
|
* function is working correctly in both the static and dynamic allocation
|
||||||
cases. */
|
* cases. */
|
||||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
|
|
@ -791,13 +792,15 @@ static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
||||||
}
|
}
|
||||||
|
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
|
|
||||||
if( xReturned != pdPASS )
|
if( xReturned != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelete( xCreatedTask );
|
vTaskDelete( xCreatedTask );
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -806,8 +809,8 @@ static void prvStaticallyAllocatedTask( void *pvParameters )
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* The created task just suspends itself to wait to get deleted. The task
|
/* The created task just suspends itself to wait to get deleted. The task
|
||||||
that creates this task checks this task is in the expected Suspended state
|
* that creates this task checks this task is in the expected Suspended state
|
||||||
before deleting it. */
|
* before deleting it. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -830,15 +833,14 @@ const TickType_t xMinDelay = pdMS_TO_TICKS( ( TickType_t ) 75 );
|
||||||
const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );
|
const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );
|
||||||
|
|
||||||
/* Generate the next delay time. This is kept within a narrow band so as
|
/* Generate the next delay time. This is kept within a narrow band so as
|
||||||
not to disturb the timing of other tests - but does add in some pseudo
|
* not to disturb the timing of other tests - but does add in some pseudo
|
||||||
randomisation into the tests. */
|
* randomisation into the tests. */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
xNextDelay = prvRand() % xMaxDelay;
|
xNextDelay = prvRand() % xMaxDelay;
|
||||||
|
|
||||||
/* Just in case this loop is executed lots of times. */
|
/* Just in case this loop is executed lots of times. */
|
||||||
vTaskDelay( xTinyDelay );
|
vTaskDelay( xTinyDelay );
|
||||||
|
|
||||||
} while( xNextDelay < xMinDelay );
|
} while( xNextDelay < xMinDelay );
|
||||||
|
|
||||||
return xNextDelay;
|
return xNextDelay;
|
||||||
|
|
@ -878,7 +880,7 @@ const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( Eve
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally try clearing some bits too and check that operation proceeds as
|
/* Finally try clearing some bits too and check that operation proceeds as
|
||||||
expected. */
|
* expected. */
|
||||||
xEventGroupClearBits( xEventGroup, xFirstTestBits );
|
xEventGroupClearBits( xEventGroup, xFirstTestBits );
|
||||||
|
|
||||||
xEventBits = xEventGroupGetBits( xEventGroup );
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
||||||
|
|
@ -890,7 +892,8 @@ const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( Eve
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )
|
static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore,
|
||||||
|
UBaseType_t uxMaxCount )
|
||||||
{
|
{
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
UBaseType_t x;
|
UBaseType_t x;
|
||||||
|
|
@ -898,7 +901,7 @@ const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );
|
||||||
TickType_t xTickCount;
|
TickType_t xTickCount;
|
||||||
|
|
||||||
/* The binary semaphore should start 'empty', so a call to xSemaphoreTake()
|
/* The binary semaphore should start 'empty', so a call to xSemaphoreTake()
|
||||||
should fail. */
|
* should fail. */
|
||||||
xTickCount = xTaskGetTickCount();
|
xTickCount = xTaskGetTickCount();
|
||||||
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
||||||
|
|
||||||
|
|
@ -914,7 +917,7 @@ TickType_t xTickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount
|
/* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount
|
||||||
times. */
|
* times. */
|
||||||
for( x = 0; x < uxMaxCount; x++ )
|
for( x = 0; x < uxMaxCount; x++ )
|
||||||
{
|
{
|
||||||
xReturned = xSemaphoreGive( xSemaphore );
|
xReturned = xSemaphoreGive( xSemaphore );
|
||||||
|
|
@ -936,7 +939,7 @@ TickType_t xTickCount;
|
||||||
configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );
|
configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );
|
||||||
|
|
||||||
/* Should now be possible to 'take' the semaphore up to a maximum of
|
/* Should now be possible to 'take' the semaphore up to a maximum of
|
||||||
uxMaxCount times without blocking. */
|
* uxMaxCount times without blocking. */
|
||||||
for( x = 0; x < uxMaxCount; x++ )
|
for( x = 0; x < uxMaxCount; x++ )
|
||||||
{
|
{
|
||||||
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
||||||
|
|
@ -948,7 +951,7 @@ TickType_t xTickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Back to the starting condition, where the semaphore should not be
|
/* Back to the starting condition, where the semaphore should not be
|
||||||
available. */
|
* available. */
|
||||||
xTickCount = xTaskGetTickCount();
|
xTickCount = xTaskGetTickCount();
|
||||||
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
||||||
|
|
||||||
|
|
@ -976,18 +979,20 @@ BaseType_t xReturned, xLoop;
|
||||||
for( xLoop = 0; xLoop < 2; xLoop++ )
|
for( xLoop = 0; xLoop < 2; xLoop++ )
|
||||||
{
|
{
|
||||||
/* A very basic test that the queue can be written to and read from as
|
/* A very basic test that the queue can be written to and read from as
|
||||||
expected. First the queue should be empty. */
|
* expected. First the queue should be empty. */
|
||||||
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != errQUEUE_EMPTY )
|
if( xReturned != errQUEUE_EMPTY )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS
|
/* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS
|
||||||
times. */
|
* times. */
|
||||||
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
||||||
{
|
{
|
||||||
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != pdPASS )
|
if( xReturned != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -996,13 +1001,14 @@ BaseType_t xReturned, xLoop;
|
||||||
|
|
||||||
/* Should not now be possible to write to the queue again. */
|
/* Should not now be possible to write to the queue again. */
|
||||||
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != errQUEUE_FULL )
|
if( xReturned != errQUEUE_FULL )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now read back from the queue to ensure the data read back matches that
|
/* Now read back from the queue to ensure the data read back matches that
|
||||||
written. */
|
* written. */
|
||||||
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
||||||
{
|
{
|
||||||
xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );
|
xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );
|
||||||
|
|
@ -1020,6 +1026,7 @@ BaseType_t xReturned, xLoop;
|
||||||
|
|
||||||
/* The queue should be empty again. */
|
/* The queue should be empty again. */
|
||||||
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
||||||
|
|
||||||
if( xReturned != errQUEUE_EMPTY )
|
if( xReturned != errQUEUE_EMPTY )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -1034,8 +1041,8 @@ const BaseType_t xLoops = 5;
|
||||||
BaseType_t x, xReturned;
|
BaseType_t x, xReturned;
|
||||||
|
|
||||||
/* A very basic test that the recursive semaphore behaved like a recursive
|
/* A very basic test that the recursive semaphore behaved like a recursive
|
||||||
semaphore. First the semaphore should not be able to be given, as it has not
|
* semaphore. First the semaphore should not be able to be given, as it has not
|
||||||
yet been taken. */
|
* yet been taken. */
|
||||||
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
||||||
|
|
||||||
if( xReturned != pdFAIL )
|
if( xReturned != pdFAIL )
|
||||||
|
|
@ -1055,7 +1062,7 @@ BaseType_t x, xReturned;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should be possible to give the semaphore the same number of times as it
|
/* Should be possible to give the semaphore the same number of times as it
|
||||||
was given in the loop above. */
|
* was given in the loop above. */
|
||||||
for( x = 0; x < xLoops; x++ )
|
for( x = 0; x < xLoops; x++ )
|
||||||
{
|
{
|
||||||
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
#define sbNUMBER_OF_SENDER_TASKS ( 2 )
|
#define sbNUMBER_OF_SENDER_TASKS ( 2 )
|
||||||
|
|
||||||
/* Priority of the test tasks. The send and receive go from low to high
|
/* Priority of the test tasks. The send and receive go from low to high
|
||||||
priority tasks, and from high to low priority tasks. */
|
* priority tasks, and from high to low priority tasks. */
|
||||||
#define sbLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
#define sbLOWER_PRIORITY ( tskIDLE_PRIORITY )
|
||||||
#define sbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
#define sbHIGHER_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
|
||||||
|
|
@ -62,12 +62,12 @@ priority tasks, and from high to low priority tasks. */
|
||||||
#define sbDONT_BLOCK ( 0 )
|
#define sbDONT_BLOCK ( 0 )
|
||||||
|
|
||||||
/* The trigger level sets the number of bytes that must be present in the
|
/* The trigger level sets the number of bytes that must be present in the
|
||||||
stream buffer before a task that is blocked on the stream buffer is moved out of
|
* stream buffer before a task that is blocked on the stream buffer is moved out of
|
||||||
the Blocked state so it can read the bytes. */
|
* the Blocked state so it can read the bytes. */
|
||||||
#define sbTRIGGER_LEVEL_1 ( 1 )
|
#define sbTRIGGER_LEVEL_1 ( 1 )
|
||||||
|
|
||||||
/* The size of the stack allocated to the tasks that run as part of this demo/
|
/* The size of the stack allocated to the tasks that run as part of this demo/
|
||||||
test. The stack size is over generous in most cases. */
|
* test. The stack size is over generous in most cases. */
|
||||||
#ifndef configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
|
#ifndef configSTREAM_BUFFER_SENDER_TASK_STACK_SIZE
|
||||||
#define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
|
#define sbSTACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) )
|
||||||
#else
|
#else
|
||||||
|
|
@ -105,7 +105,7 @@ static void prvNonBlockingReceiverTask( void *pvParameters );
|
||||||
static void prvNonBlockingSenderTask( void * pvParameters );
|
static void prvNonBlockingSenderTask( void * pvParameters );
|
||||||
|
|
||||||
/* Performs an assert() like check in a way that won't get removed when
|
/* Performs an assert() like check in a way that won't get removed when
|
||||||
performing a code coverage analysis. */
|
* performing a code coverage analysis. */
|
||||||
static void prvCheckExpectedState( BaseType_t xState );
|
static void prvCheckExpectedState( BaseType_t xState );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -116,9 +116,10 @@ static void prvCheckExpectedState( BaseType_t xState );
|
||||||
static void prvInterruptTriggerLevelTest( void * pvParameters );
|
static void prvInterruptTriggerLevelTest( void * pvParameters );
|
||||||
|
|
||||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
|
|
||||||
/* This file tests both statically and dynamically allocated stream buffers.
|
/* This file tests both statically and dynamically allocated stream buffers.
|
||||||
Allocate the structures and buffers to be used by the statically allocated
|
* Allocate the structures and buffers to be used by the statically allocated
|
||||||
objects, which get used in the echo tests. */
|
* objects, which get used in the echo tests. */
|
||||||
static void prvReceiverTask( void * pvParameters );
|
static void prvReceiverTask( void * pvParameters );
|
||||||
static void prvSenderTask( void * pvParameters );
|
static void prvSenderTask( void * pvParameters );
|
||||||
|
|
||||||
|
|
@ -127,10 +128,10 @@ static void prvInterruptTriggerLevelTest( void *pvParameters );
|
||||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||||
|
|
||||||
/* The +1 is to make the test logic easier as the function that calculates the
|
/* The +1 is to make the test logic easier as the function that calculates the
|
||||||
free space will return one less than the actual free space - adding a 1 to the
|
* free space will return one less than the actual free space - adding a 1 to the
|
||||||
actual length makes it appear to the tests as if the free space is returned as
|
* actual length makes it appear to the tests as if the free space is returned as
|
||||||
it might logically be expected. Returning 1 less than the actual free space is
|
* it might logically be expected. Returning 1 less than the actual free space is
|
||||||
fine as it can never result in an overrun. */
|
* fine as it can never result in an overrun. */
|
||||||
static uint8_t ucBufferStorage[ sbNUMBER_OF_SENDER_TASKS ][ sbSTREAM_BUFFER_LENGTH_BYTES + 1 ];
|
static uint8_t ucBufferStorage[ sbNUMBER_OF_SENDER_TASKS ][ sbSTREAM_BUFFER_LENGTH_BYTES + 1 ];
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -145,36 +146,36 @@ typedef struct ECHO_STREAM_BUFFERS
|
||||||
static volatile uint32_t ulEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
|
static volatile uint32_t ulEchoLoopCounters[ sbNUMBER_OF_ECHO_CLIENTS ] = { 0 };
|
||||||
|
|
||||||
/* The non-blocking tasks monitor their operation, and if no errors have been
|
/* The non-blocking tasks monitor their operation, and if no errors have been
|
||||||
found, increment ulNonBlockingRxCounter. xAreStreamBufferTasksStillRunning()
|
* found, increment ulNonBlockingRxCounter. xAreStreamBufferTasksStillRunning()
|
||||||
then checks ulNonBlockingRxCounter and only returns pdPASS if
|
* then checks ulNonBlockingRxCounter and only returns pdPASS if
|
||||||
ulNonBlockingRxCounter is still incrementing. */
|
* ulNonBlockingRxCounter is still incrementing. */
|
||||||
static volatile uint32_t ulNonBlockingRxCounter = 0;
|
static volatile uint32_t ulNonBlockingRxCounter = 0;
|
||||||
|
|
||||||
/* The task that receives characters from the tick interrupt in order to test
|
/* The task that receives characters from the tick interrupt in order to test
|
||||||
different trigger levels monitors its own behaviour. If it has not detected any
|
* different trigger levels monitors its own behaviour. If it has not detected any
|
||||||
error then it increments ulInterruptTriggerCounter to indicate to the check task
|
* error then it increments ulInterruptTriggerCounter to indicate to the check task
|
||||||
that it is still operating correctly. */
|
* that it is still operating correctly. */
|
||||||
static volatile uint32_t ulInterruptTriggerCounter = 0UL;
|
static volatile uint32_t ulInterruptTriggerCounter = 0UL;
|
||||||
|
|
||||||
/* The stream buffer used from the tick interrupt. This sends one byte at a time
|
/* The stream buffer used from the tick interrupt. This sends one byte at a time
|
||||||
to a test task to test the trigger level operation. The variable is set to NULL
|
* to a test task to test the trigger level operation. The variable is set to NULL
|
||||||
in between test runs. */
|
* in between test runs. */
|
||||||
static volatile StreamBufferHandle_t xInterruptStreamBuffer = NULL;
|
static volatile StreamBufferHandle_t xInterruptStreamBuffer = NULL;
|
||||||
|
|
||||||
/* The data sent from the tick interrupt to the task that tests the trigger
|
/* The data sent from the tick interrupt to the task that tests the trigger
|
||||||
level functionality. */
|
* level functionality. */
|
||||||
static const char * pcDataSentFromInterrupt = "0123456789";
|
static const char * pcDataSentFromInterrupt = "0123456789";
|
||||||
|
|
||||||
/* Data that is longer than the buffer that is sent to the buffers as a stream
|
/* Data that is longer than the buffer that is sent to the buffers as a stream
|
||||||
of bytes. Parts of which are written to the stream buffer to test writing
|
* of bytes. Parts of which are written to the stream buffer to test writing
|
||||||
different lengths at different offsets, to many bytes, part streams, streams
|
* different lengths at different offsets, to many bytes, part streams, streams
|
||||||
that wrap, etc.. Two messages are defined to ensure left over data is not
|
* that wrap, etc.. Two messages are defined to ensure left over data is not
|
||||||
accidentally read out of the buffer. */
|
* accidentally read out of the buffer. */
|
||||||
static const char * pc55ByteString = "One two three four five six seven eight nine ten eleven";
|
static const char * pc55ByteString = "One two three four five six seven eight nine ten eleven";
|
||||||
static const char * pc54ByteString = "01234567891abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ";
|
static const char * pc54ByteString = "01234567891abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ";
|
||||||
|
|
||||||
/* Used to log the status of the tests contained within this file for reporting
|
/* Used to log the status of the tests contained within this file for reporting
|
||||||
to a monitoring task ('check' task). */
|
* to a monitoring task ('check' task). */
|
||||||
static BaseType_t xErrorStatus = pdPASS;
|
static BaseType_t xErrorStatus = pdPASS;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -184,29 +185,29 @@ void vStartStreamBufferTasks( void )
|
||||||
StreamBufferHandle_t xStreamBuffer;
|
StreamBufferHandle_t xStreamBuffer;
|
||||||
|
|
||||||
/* The echo servers sets up the stream buffers before creating the echo
|
/* The echo servers sets up the stream buffers before creating the echo
|
||||||
client tasks. One set of tasks has the server as the higher priority, and
|
* client tasks. One set of tasks has the server as the higher priority, and
|
||||||
the other has the client as the higher priority. */
|
* the other has the client as the higher priority. */
|
||||||
xTaskCreate( prvEchoServer, "1StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvEchoServer, "1StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
||||||
xTaskCreate( prvEchoServer, "2StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
xTaskCreate( prvEchoServer, "2StrEchoServer", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
||||||
|
|
||||||
/* The non blocking tasks run continuously and will interleave with each
|
/* The non blocking tasks run continuously and will interleave with each
|
||||||
other, so must be created at the lowest priority. The stream buffer they
|
* other, so must be created at the lowest priority. The stream buffer they
|
||||||
use is created and passed in using the task's parameter. */
|
* use is created and passed in using the task's parameter. */
|
||||||
xStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
xStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
||||||
xTaskCreate( prvNonBlockingReceiverTask, "StrNonBlkRx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( prvNonBlockingReceiverTask, "StrNonBlkRx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
|
||||||
xTaskCreate( prvNonBlockingSenderTask, "StrNonBlkTx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
|
xTaskCreate( prvNonBlockingSenderTask, "StrNonBlkTx", configMINIMAL_STACK_SIZE, ( void * ) xStreamBuffer, tskIDLE_PRIORITY, NULL );
|
||||||
|
|
||||||
/* The task that receives bytes from an interrupt to test that it unblocks
|
/* The task that receives bytes from an interrupt to test that it unblocks
|
||||||
at a specific trigger level must run at a high priority to minimise the risk
|
* at a specific trigger level must run at a high priority to minimise the risk
|
||||||
of it receiving more characters before it can execute again after being
|
* of it receiving more characters before it can execute again after being
|
||||||
unblocked. */
|
* unblocked. */
|
||||||
xTaskCreate( prvInterruptTriggerLevelTest, "StrTrig", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
|
xTaskCreate( prvInterruptTriggerLevelTest, "StrTrig", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
|
||||||
|
|
||||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||||
{
|
{
|
||||||
/* The sender tasks set up the stream buffers before creating the
|
/* The sender tasks set up the stream buffers before creating the
|
||||||
receiver tasks. Priorities must be 0 and 1 as the priority is used to
|
* receiver tasks. Priorities must be 0 and 1 as the priority is used to
|
||||||
index into the xStaticStreamBuffers and ucBufferStorage arrays. */
|
* index into the xStaticStreamBuffers and ucBufferStorage arrays. */
|
||||||
xTaskCreate( prvSenderTask, "Str1Sender", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvSenderTask, "Str1Sender", sbSMALLER_STACK_SIZE, NULL, sbHIGHER_PRIORITY, NULL );
|
||||||
xTaskCreate( prvSenderTask, "Str2Sender", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
xTaskCreate( prvSenderTask, "Str2Sender", sbSMALLER_STACK_SIZE, NULL, sbLOWER_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +218,7 @@ StreamBufferHandle_t xStreamBuffer;
|
||||||
static void prvCheckExpectedState( BaseType_t xState )
|
static void prvCheckExpectedState( BaseType_t xState )
|
||||||
{
|
{
|
||||||
configASSERT( xState );
|
configASSERT( xState );
|
||||||
|
|
||||||
if( xState == pdFAIL )
|
if( xState == pdFAIL )
|
||||||
{
|
{
|
||||||
xErrorStatus = pdFAIL;
|
xErrorStatus = pdFAIL;
|
||||||
|
|
@ -239,8 +241,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
( void ) xAllowableMargin;
|
( void ) xAllowableMargin;
|
||||||
|
|
||||||
/* To minimise stack and heap usage a full size buffer is allocated from the
|
/* To minimise stack and heap usage a full size buffer is allocated from the
|
||||||
heap, then buffers which hold smaller amounts of data are overlayed with the
|
* heap, then buffers which hold smaller amounts of data are overlayed with the
|
||||||
larger buffer - just make sure not to use both at once! */
|
* larger buffer - just make sure not to use both at once! */
|
||||||
pucFullBuffer = pvPortMalloc( xFullBufferSize );
|
pucFullBuffer = pvPortMalloc( xFullBufferSize );
|
||||||
configASSERT( pucFullBuffer );
|
configASSERT( pucFullBuffer );
|
||||||
|
|
||||||
|
|
@ -248,7 +250,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
pucReadData = pucData + x17ByteLength;
|
pucReadData = pucData + x17ByteLength;
|
||||||
|
|
||||||
/* Nothing has been added or removed yet, so expect the free space to be
|
/* Nothing has been added or removed yet, so expect the free space to be
|
||||||
exactly as created. Head and tail are both at 0. */
|
* exactly as created. Head and tail are both at 0. */
|
||||||
xExpectedSpaces = sbSTREAM_BUFFER_LENGTH_BYTES;
|
xExpectedSpaces = sbSTREAM_BUFFER_LENGTH_BYTES;
|
||||||
xExpectedBytes = 0;
|
xExpectedBytes = 0;
|
||||||
xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
|
xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
|
||||||
|
|
@ -259,7 +261,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
||||||
|
|
||||||
/* Add a single item - number of bytes available should go up by one and spaces
|
/* Add a single item - number of bytes available should go up by one and spaces
|
||||||
available down by one. Head is in front of tail. */
|
* available down by one. Head is in front of tail. */
|
||||||
xExpectedSpaces--;
|
xExpectedSpaces--;
|
||||||
xExpectedBytes++;
|
xExpectedBytes++;
|
||||||
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
|
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
|
||||||
|
|
@ -288,7 +290,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xReturned == ( size_t ) 0 );
|
prvCheckExpectedState( xReturned == ( size_t ) 0 );
|
||||||
|
|
||||||
/* Remove a byte so the tail pointer moves off 0. Head pointer remains at the
|
/* Remove a byte so the tail pointer moves off 0. Head pointer remains at the
|
||||||
end of the buffer. */
|
* end of the buffer. */
|
||||||
xExpectedSpaces += 1;
|
xExpectedSpaces += 1;
|
||||||
xExpectedBytes -= 1;
|
xExpectedBytes -= 1;
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
|
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
|
||||||
|
|
@ -313,7 +315,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
|
||||||
|
|
||||||
/* Now the head pointer is behind the tail pointer. Read another 29 bytes so
|
/* Now the head pointer is behind the tail pointer. Read another 29 bytes so
|
||||||
the tail pointer moves to the end of the buffer. */
|
* the tail pointer moves to the end of the buffer. */
|
||||||
xExpectedSpaces += 29;
|
xExpectedSpaces += 29;
|
||||||
xExpectedBytes -= 29;
|
xExpectedBytes -= 29;
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, ( size_t ) 29, ( TickType_t ) 0 );
|
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, ( size_t ) 29, ( TickType_t ) 0 );
|
||||||
|
|
@ -326,7 +328,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
||||||
|
|
||||||
/* Read out one more byte to wrap the tail back around to the start, to get back
|
/* Read out one more byte to wrap the tail back around to the start, to get back
|
||||||
to where we started. */
|
* to where we started. */
|
||||||
xExpectedSpaces += 1;
|
xExpectedSpaces += 1;
|
||||||
xExpectedBytes -= 1;
|
xExpectedBytes -= 1;
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
|
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, sizeof( *pucData ), ( TickType_t ) 0 );
|
||||||
|
|
@ -339,7 +341,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
||||||
|
|
||||||
/* Try filling the message buffer in one write, blocking indefinitely. Expect to
|
/* Try filling the message buffer in one write, blocking indefinitely. Expect to
|
||||||
have written one byte less. */
|
* have written one byte less. */
|
||||||
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
|
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
|
||||||
xExpectedSpaces = ( size_t ) 0;
|
xExpectedSpaces = ( size_t ) 0;
|
||||||
prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
|
prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
|
||||||
|
|
@ -349,8 +351,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
|
||||||
|
|
||||||
/* Empty the buffer again ready for the rest of the tests. Again block
|
/* Empty the buffer again ready for the rest of the tests. Again block
|
||||||
indefinitely to ensure reading more than there can possible be won't lock this
|
* indefinitely to ensure reading more than there can possible be won't lock this
|
||||||
task up, so expect to actually receive one byte less than requested. */
|
* task up, so expect to actually receive one byte less than requested. */
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
|
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucData, xTrueSize, portMAX_DELAY );
|
||||||
prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
|
prvCheckExpectedState( xReturned == ( xTrueSize - ( size_t ) 1 ) );
|
||||||
xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
|
xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
|
||||||
|
|
@ -362,18 +364,19 @@ UBaseType_t uxOriginalPriority;
|
||||||
|
|
||||||
|
|
||||||
/* The buffer is 30 bytes long. 6 5 byte messages should fit before the
|
/* The buffer is 30 bytes long. 6 5 byte messages should fit before the
|
||||||
buffer is completely full. */
|
* buffer is completely full. */
|
||||||
xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
|
xExpected = xStreamBufferSpacesAvailable( xStreamBuffer );
|
||||||
|
|
||||||
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
||||||
{
|
{
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
||||||
|
|
||||||
/* Generate recognisable data to write to the buffer. This is just
|
/* Generate recognisable data to write to the buffer. This is just
|
||||||
ascii characters that shows which loop iteration the data was written
|
* ascii characters that shows which loop iteration the data was written
|
||||||
in. The 'FromISR' version is used to give it some exercise as a block
|
* in. The 'FromISR' version is used to give it some exercise as a block
|
||||||
time is not used, so the call must be inside a critical section so it
|
* time is not used, so the call must be inside a critical section so it
|
||||||
runs with ports that don't support interrupt nesting (and therefore
|
* runs with ports that don't support interrupt nesting (and therefore
|
||||||
don't have interrupt safe critical sections). */
|
* don't have interrupt safe critical sections). */
|
||||||
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
|
|
@ -383,7 +386,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xReturned == x6ByteLength );
|
prvCheckExpectedState( xReturned == x6ByteLength );
|
||||||
|
|
||||||
/* The space in the buffer will have reduced by the amount of user data
|
/* The space in the buffer will have reduced by the amount of user data
|
||||||
written into the buffer. */
|
* written into the buffer. */
|
||||||
xExpected -= x6ByteLength;
|
xExpected -= x6ByteLength;
|
||||||
xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
|
xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
|
||||||
prvCheckExpectedState( xReturned == xExpected );
|
prvCheckExpectedState( xReturned == xExpected );
|
||||||
|
|
@ -398,8 +401,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xReturned == 0 );
|
prvCheckExpectedState( xReturned == 0 );
|
||||||
|
|
||||||
/* Adding with a timeout should also fail after the appropriate time. The
|
/* Adding with a timeout should also fail after the appropriate time. The
|
||||||
priority is temporarily boosted in this part of the test to keep the
|
* priority is temporarily boosted in this part of the test to keep the
|
||||||
allowable margin to a minimum. */
|
* allowable margin to a minimum. */
|
||||||
uxOriginalPriority = uxTaskPriorityGet( NULL );
|
uxOriginalPriority = uxTaskPriorityGet( NULL );
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
xTimeBeforeCall = xTaskGetTickCount();
|
xTimeBeforeCall = xTaskGetTickCount();
|
||||||
|
|
@ -411,17 +414,17 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xReturned == 0 );
|
prvCheckExpectedState( xReturned == 0 );
|
||||||
|
|
||||||
/* The buffer is now full of data in the form "000000", "111111", etc. Make
|
/* The buffer is now full of data in the form "000000", "111111", etc. Make
|
||||||
sure the data is read out as expected. */
|
* sure the data is read out as expected. */
|
||||||
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
for( xItem = 0; xItem < xMax6ByteMessages; xItem++ )
|
||||||
{
|
{
|
||||||
/* Generate the data that is expected to be read out for this loop
|
/* Generate the data that is expected to be read out for this loop
|
||||||
iteration. */
|
* iteration. */
|
||||||
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x6ByteLength );
|
||||||
|
|
||||||
/* Read the next 6 bytes out. The 'FromISR' version is used to give it
|
/* Read the next 6 bytes out. The 'FromISR' version is used to give it
|
||||||
some exercise as a block time is not used, so a it must be called from
|
* some exercise as a block time is not used, so a it must be called from
|
||||||
a critical section so this will work on ports that don't support
|
* a critical section so this will work on ports that don't support
|
||||||
interrupt nesting (so don't have interrupt safe critical sections). */
|
* interrupt nesting (so don't have interrupt safe critical sections). */
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
xReturned = xStreamBufferReceiveFromISR( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
|
xReturned = xStreamBufferReceiveFromISR( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, NULL );
|
||||||
|
|
@ -433,7 +436,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
|
prvCheckExpectedState( memcmp( ( void * ) pucData, ( void * ) pucReadData, x6ByteLength ) == 0 );
|
||||||
|
|
||||||
/* The space in the buffer will have increased by the amount of user
|
/* The space in the buffer will have increased by the amount of user
|
||||||
data removed from the buffer. */
|
* data removed from the buffer. */
|
||||||
xExpected += x6ByteLength;
|
xExpected += x6ByteLength;
|
||||||
xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
|
xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
|
||||||
prvCheckExpectedState( xReturned == xExpected );
|
prvCheckExpectedState( xReturned == xExpected );
|
||||||
|
|
@ -447,8 +450,8 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xExpected == sbSTREAM_BUFFER_LENGTH_BYTES );
|
prvCheckExpectedState( xExpected == sbSTREAM_BUFFER_LENGTH_BYTES );
|
||||||
|
|
||||||
/* Reading with a timeout should also fail after the appropriate time. The
|
/* Reading with a timeout should also fail after the appropriate time. The
|
||||||
priority is temporarily boosted in this part of the test to keep the
|
* priority is temporarily boosted in this part of the test to keep the
|
||||||
allowable margin to a minimum. */
|
* allowable margin to a minimum. */
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
xTimeBeforeCall = xTaskGetTickCount();
|
xTimeBeforeCall = xTaskGetTickCount();
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
|
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucReadData, x6ByteLength, xBlockTime );
|
||||||
|
|
@ -460,20 +463,20 @@ UBaseType_t uxOriginalPriority;
|
||||||
|
|
||||||
|
|
||||||
/* In the next loop 17 bytes are written to then read out on each
|
/* In the next loop 17 bytes are written to then read out on each
|
||||||
iteration. As 30 is not divisible by 17 the data will wrap around. */
|
* iteration. As 30 is not divisible by 17 the data will wrap around. */
|
||||||
xExpected = sbSTREAM_BUFFER_LENGTH_BYTES - x17ByteLength;
|
xExpected = sbSTREAM_BUFFER_LENGTH_BYTES - x17ByteLength;
|
||||||
|
|
||||||
for( xItem = 0; xItem < 100; xItem++ )
|
for( xItem = 0; xItem < 100; xItem++ )
|
||||||
{
|
{
|
||||||
/* Generate recognisable data to write to the queue. This is just
|
/* Generate recognisable data to write to the queue. This is just
|
||||||
ascii characters that shows which loop iteration the data was written
|
* ascii characters that shows which loop iteration the data was written
|
||||||
in. */
|
* in. */
|
||||||
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
|
memset( ( void * ) pucData, ( ( int ) '0' ) + ( int ) xItem, x17ByteLength );
|
||||||
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, x17ByteLength, sbDONT_BLOCK );
|
xReturned = xStreamBufferSend( xStreamBuffer, ( void * ) pucData, x17ByteLength, sbDONT_BLOCK );
|
||||||
prvCheckExpectedState( xReturned == x17ByteLength );
|
prvCheckExpectedState( xReturned == x17ByteLength );
|
||||||
|
|
||||||
/* The space in the buffer will have reduced by the amount of user data
|
/* The space in the buffer will have reduced by the amount of user data
|
||||||
written into the buffer. */
|
* written into the buffer. */
|
||||||
xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
|
xReturned = xStreamBufferSpacesAvailable( xStreamBuffer );
|
||||||
prvCheckExpectedState( xReturned == xExpected );
|
prvCheckExpectedState( xReturned == xExpected );
|
||||||
xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
|
xReturned = xStreamBufferBytesAvailable( xStreamBuffer );
|
||||||
|
|
@ -498,7 +501,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill the buffer with one message, check it is full, then read it back
|
/* Fill the buffer with one message, check it is full, then read it back
|
||||||
again and check the correct data is received. */
|
* again and check the correct data is received. */
|
||||||
xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
|
xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
|
||||||
xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
|
xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES, sbDONT_BLOCK );
|
||||||
prvCheckExpectedState( memcmp( pc55ByteString, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
|
prvCheckExpectedState( memcmp( pc55ByteString, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
|
||||||
|
|
@ -507,7 +510,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
|
for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
|
||||||
{
|
{
|
||||||
/* Block time is only for test coverage, the task should never actually
|
/* Block time is only for test coverage, the task should never actually
|
||||||
block here. */
|
* block here. */
|
||||||
xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xItem ] ), sizeof( char ), sbRX_TX_BLOCK_TIME );
|
xStreamBufferSend( xStreamBuffer, ( const void * ) &( pc54ByteString[ xItem ] ), sizeof( char ), sbRX_TX_BLOCK_TIME );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,9 +518,9 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdTRUE );
|
||||||
|
|
||||||
/* Read the message out in one go, even though it was written in individual
|
/* Read the message out in one go, even though it was written in individual
|
||||||
bytes. Try reading much more data than is actually available to ensure only
|
* bytes. Try reading much more data than is actually available to ensure only
|
||||||
the available bytes are returned (otherwise this read will write outside of
|
* the available bytes are returned (otherwise this read will write outside of
|
||||||
the memory allocated anyway!). */
|
* the memory allocated anyway!). */
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, sbRX_TX_BLOCK_TIME );
|
xReturned = xStreamBufferReceive( xStreamBuffer, pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES * ( size_t ) 2, sbRX_TX_BLOCK_TIME );
|
||||||
prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
|
prvCheckExpectedState( xReturned == sbSTREAM_BUFFER_LENGTH_BYTES );
|
||||||
prvCheckExpectedState( memcmp( ( const void * ) pc54ByteString, ( const void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
|
prvCheckExpectedState( memcmp( ( const void * ) pc54ByteString, ( const void * ) pucFullBuffer, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
|
||||||
|
|
@ -534,10 +537,11 @@ UBaseType_t uxOriginalPriority;
|
||||||
for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
|
for( xItem = 0; xItem < sbSTREAM_BUFFER_LENGTH_BYTES; xItem++ )
|
||||||
{
|
{
|
||||||
/* Block time is only for test coverage, the task should never actually
|
/* Block time is only for test coverage, the task should never actually
|
||||||
block here. */
|
* block here. */
|
||||||
xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sizeof( char ), sbRX_TX_BLOCK_TIME );
|
xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, sizeof( char ), sbRX_TX_BLOCK_TIME );
|
||||||
prvCheckExpectedState( pc55ByteString[ xItem ] == pucFullBuffer[ 0 ] );
|
prvCheckExpectedState( pc55ByteString[ xItem ] == pucFullBuffer[ 0 ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
|
prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
||||||
|
|
||||||
|
|
@ -554,15 +558,15 @@ UBaseType_t uxOriginalPriority;
|
||||||
prvCheckExpectedState( xReturned == 0 );
|
prvCheckExpectedState( xReturned == 0 );
|
||||||
|
|
||||||
/* Ensure data was written as expected even when there was an attempt to
|
/* Ensure data was written as expected even when there was an attempt to
|
||||||
write more than was available. This also tries to read more bytes than are
|
* write more than was available. This also tries to read more bytes than are
|
||||||
available. */
|
* available. */
|
||||||
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, xFullBufferSize, xMinimalBlockTime );
|
xReturned = xStreamBufferReceive( xStreamBuffer, ( void * ) pucFullBuffer, xFullBufferSize, xMinimalBlockTime );
|
||||||
prvCheckExpectedState( memcmp( ( const void * ) pucFullBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
|
prvCheckExpectedState( memcmp( ( const void * ) pucFullBuffer, ( const void * ) pc54ByteString, sbSTREAM_BUFFER_LENGTH_BYTES ) == 0 );
|
||||||
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
prvCheckExpectedState( xStreamBufferIsFull( xStreamBuffer ) == pdFALSE );
|
||||||
prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
|
prvCheckExpectedState( xStreamBufferIsEmpty( xStreamBuffer ) == pdTRUE );
|
||||||
|
|
||||||
/* Clean up with data in the buffer to ensure the tests that follow don't
|
/* Clean up with data in the buffer to ensure the tests that follow don't
|
||||||
see the data (the data should be discarded). */
|
* see the data (the data should be discarded). */
|
||||||
( void ) xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES / ( size_t ) 2, sbDONT_BLOCK );
|
( void ) xStreamBufferSend( xStreamBuffer, ( const void * ) pc55ByteString, sbSTREAM_BUFFER_LENGTH_BYTES / ( size_t ) 2, sbDONT_BLOCK );
|
||||||
vPortFree( pucFullBuffer );
|
vPortFree( pucFullBuffer );
|
||||||
xStreamBufferReset( xStreamBuffer );
|
xStreamBufferReset( xStreamBuffer );
|
||||||
|
|
@ -576,17 +580,17 @@ size_t xNextChar = 0, xBytesToSend, xBytesActuallySent;
|
||||||
const size_t xStringLength = strlen( pc54ByteString );
|
const size_t xStringLength = strlen( pc54ByteString );
|
||||||
|
|
||||||
/* In this case the stream buffer has already been created and is passed
|
/* In this case the stream buffer has already been created and is passed
|
||||||
into the task using the task's parameter. */
|
* into the task using the task's parameter. */
|
||||||
xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
|
xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
|
||||||
|
|
||||||
/* Keep sending the string to the stream buffer as many bytes as possible in
|
/* Keep sending the string to the stream buffer as many bytes as possible in
|
||||||
each go. Doesn't block so calls can interleave with the non-blocking
|
* each go. Doesn't block so calls can interleave with the non-blocking
|
||||||
receives performed by prvNonBlockingReceiverTask(). */
|
* receives performed by prvNonBlockingReceiverTask(). */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The whole string cannot be sent at once, so xNextChar is an index to
|
/* The whole string cannot be sent at once, so xNextChar is an index to
|
||||||
the position within the string that has been sent so far. How many
|
* the position within the string that has been sent so far. How many
|
||||||
bytes are there left to send before the end of the string? */
|
* bytes are there left to send before the end of the string? */
|
||||||
xBytesToSend = xStringLength - xNextChar;
|
xBytesToSend = xStringLength - xNextChar;
|
||||||
|
|
||||||
/* Attempt to send right up to the end of the string. */
|
/* Attempt to send right up to the end of the string. */
|
||||||
|
|
@ -594,7 +598,7 @@ const size_t xStringLength = strlen( pc54ByteString );
|
||||||
prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
|
prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
|
||||||
|
|
||||||
/* Move the index up the string to the next character to be sent,
|
/* Move the index up the string to the next character to be sent,
|
||||||
wrapping if the end of the string has been reached. */
|
* wrapping if the end of the string has been reached. */
|
||||||
xNextChar += xBytesActuallySent;
|
xNextChar += xBytesActuallySent;
|
||||||
prvCheckExpectedState( xNextChar <= xStringLength );
|
prvCheckExpectedState( xNextChar <= xStringLength );
|
||||||
|
|
||||||
|
|
@ -615,25 +619,26 @@ char cRxString[ 12 ]; /* Holds received characters. */
|
||||||
BaseType_t xNonBlockingReceiveError = pdFALSE;
|
BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
|
|
||||||
/* In this case the stream buffer has already been created and is passed
|
/* In this case the stream buffer has already been created and is passed
|
||||||
into the task using the task's parameter. */
|
* into the task using the task's parameter. */
|
||||||
xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
|
xStreamBuffer = ( StreamBufferHandle_t ) pvParameters;
|
||||||
|
|
||||||
/* Expects to receive the pc54ByteString over and over again. Sends and
|
/* Expects to receive the pc54ByteString over and over again. Sends and
|
||||||
receives are not blocking so will interleave. */
|
* receives are not blocking so will interleave. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Attempt to receive as many bytes as possible, up to the limit of the
|
/* Attempt to receive as many bytes as possible, up to the limit of the
|
||||||
Rx buffer size. */
|
* Rx buffer size. */
|
||||||
xReceiveLength = xStreamBufferReceive( xStreamBuffer, ( void * ) cRxString, sizeof( cRxString ), sbDONT_BLOCK );
|
xReceiveLength = xStreamBufferReceive( xStreamBuffer, ( void * ) cRxString, sizeof( cRxString ), sbDONT_BLOCK );
|
||||||
|
|
||||||
if( xReceiveLength > 0 )
|
if( xReceiveLength > 0 )
|
||||||
{
|
{
|
||||||
/* xNextChar is the index into pc54ByteString that has been received
|
/* xNextChar is the index into pc54ByteString that has been received
|
||||||
already. If xReceiveLength bytes are added to that, will it go off
|
* already. If xReceiveLength bytes are added to that, will it go off
|
||||||
the end of the string? If so, then first test up to the end of the
|
* the end of the string? If so, then first test up to the end of the
|
||||||
string, then go back to the start of pc54ByteString to test the
|
* string, then go back to the start of pc54ByteString to test the
|
||||||
remains of the received data. */
|
* remains of the received data. */
|
||||||
xBytesToTest = xReceiveLength;
|
xBytesToTest = xReceiveLength;
|
||||||
|
|
||||||
if( ( xNextChar + xBytesToTest ) > xStringLength )
|
if( ( xNextChar + xBytesToTest ) > xStringLength )
|
||||||
{
|
{
|
||||||
/* Cap to test the received data to the end of the string. */
|
/* Cap to test the received data to the end of the string. */
|
||||||
|
|
@ -645,7 +650,7 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then move back to the start of the string to test the
|
/* Then move back to the start of the string to test the
|
||||||
remaining received bytes. */
|
* remaining received bytes. */
|
||||||
xNextChar = 0;
|
xNextChar = 0;
|
||||||
xStartIndex = xBytesToTest;
|
xStartIndex = xBytesToTest;
|
||||||
xBytesToTest = xReceiveLength - xBytesToTest;
|
xBytesToTest = xReceiveLength - xBytesToTest;
|
||||||
|
|
@ -653,12 +658,12 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The string didn't wrap in the buffer, so start comparing from
|
/* The string didn't wrap in the buffer, so start comparing from
|
||||||
the start of the received data. */
|
* the start of the received data. */
|
||||||
xStartIndex = 0;
|
xStartIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test the received bytes are as expected, then move the index
|
/* Test the received bytes are as expected, then move the index
|
||||||
along the string to the next expected char to receive. */
|
* along the string to the next expected char to receive. */
|
||||||
if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) &( cRxString[ xStartIndex ] ), xBytesToTest ) != 0 )
|
if( memcmp( ( const void * ) &( pc54ByteString[ xNextChar ] ), ( const void * ) &( cRxString[ xStartIndex ] ), xBytesToTest ) != 0 )
|
||||||
{
|
{
|
||||||
xNonBlockingReceiveError = pdTRUE;
|
xNonBlockingReceiveError = pdTRUE;
|
||||||
|
|
@ -667,11 +672,12 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
if( xNonBlockingReceiveError == pdFALSE )
|
if( xNonBlockingReceiveError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* No errors detected so increment the counter that lets the
|
/* No errors detected so increment the counter that lets the
|
||||||
check task know this test is still functioning correctly. */
|
* check task know this test is still functioning correctly. */
|
||||||
ulNonBlockingRxCounter++;
|
ulNonBlockingRxCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
xNextChar += xBytesToTest;
|
xNextChar += xBytesToTest;
|
||||||
|
|
||||||
if( xNextChar >= xStringLength )
|
if( xNextChar >= xStringLength )
|
||||||
{
|
{
|
||||||
xNextChar = 0;
|
xNextChar = 0;
|
||||||
|
|
@ -693,11 +699,11 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
const size_t xStringLength = strlen( pc55ByteString );
|
const size_t xStringLength = strlen( pc55ByteString );
|
||||||
|
|
||||||
/* The task's priority is used as an index into the loop counters used to
|
/* The task's priority is used as an index into the loop counters used to
|
||||||
indicate this task is still running. */
|
* indicate this task is still running. */
|
||||||
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
/* Make sure a change in priority does not inadvertently result in an
|
/* Make sure a change in priority does not inadvertently result in an
|
||||||
invalid array index. */
|
* invalid array index. */
|
||||||
prvCheckExpectedState( uxIndex < sbNUMBER_OF_ECHO_CLIENTS );
|
prvCheckExpectedState( uxIndex < sbNUMBER_OF_ECHO_CLIENTS );
|
||||||
|
|
||||||
/* Avoid compiler warnings about unused parameters. */
|
/* Avoid compiler warnings about unused parameters. */
|
||||||
|
|
@ -709,14 +715,14 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
&( xStaticStreamBuffers[ uxIndex ] ) ); /* The static stream buffer structure to use within the array. */
|
&( xStaticStreamBuffers[ uxIndex ] ) ); /* The static stream buffer structure to use within the array. */
|
||||||
|
|
||||||
/* Now the stream buffer has been created the receiver task can be
|
/* Now the stream buffer has been created the receiver task can be
|
||||||
created. If this sender task has the higher priority then the receiver
|
* created. If this sender task has the higher priority then the receiver
|
||||||
task is created at the lower priority - if this sender task has the
|
* task is created at the lower priority - if this sender task has the
|
||||||
lower priority then the receiver task is created at the higher
|
* lower priority then the receiver task is created at the higher
|
||||||
priority. */
|
* priority. */
|
||||||
if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
|
||||||
{
|
{
|
||||||
/* Here prvSingleTaskTests() performs various tests on a stream buffer
|
/* Here prvSingleTaskTests() performs various tests on a stream buffer
|
||||||
that was created statically. */
|
* that was created statically. */
|
||||||
prvSingleTaskTests( xStreamBuffer );
|
prvSingleTaskTests( xStreamBuffer );
|
||||||
xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvReceiverTask, "StrReceiver", sbSMALLER_STACK_SIZE, ( void * ) xStreamBuffer, sbHIGHER_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -728,8 +734,8 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* The whole string cannot be sent at once, so xNextChar is an index
|
/* The whole string cannot be sent at once, so xNextChar is an index
|
||||||
to the position within the string that has been sent so far. How
|
* to the position within the string that has been sent so far. How
|
||||||
many bytes are there left to send before the end of the string? */
|
* many bytes are there left to send before the end of the string? */
|
||||||
xBytesToSend = xStringLength - xNextChar;
|
xBytesToSend = xStringLength - xNextChar;
|
||||||
|
|
||||||
/* Attempt to send right up to the end of the string. */
|
/* Attempt to send right up to the end of the string. */
|
||||||
|
|
@ -737,7 +743,7 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
|
prvCheckExpectedState( xBytesActuallySent <= xBytesToSend );
|
||||||
|
|
||||||
/* Move the index up the string to the next character to be sent,
|
/* Move the index up the string to the next character to be sent,
|
||||||
wrapping if the end of the string has been reached. */
|
* wrapping if the end of the string has been reached. */
|
||||||
xNextChar += xBytesActuallySent;
|
xNextChar += xBytesActuallySent;
|
||||||
prvCheckExpectedState( xNextChar <= xStringLength );
|
prvCheckExpectedState( xNextChar <= xStringLength );
|
||||||
|
|
||||||
|
|
@ -747,7 +753,7 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment a loop counter so a check task can tell this task is
|
/* Increment a loop counter so a check task can tell this task is
|
||||||
still running as expected. */
|
* still running as expected. */
|
||||||
ulSenderLoopCounters[ uxIndex ]++;
|
ulSenderLoopCounters[ uxIndex ]++;
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) == sbHIGHER_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == sbHIGHER_PRIORITY )
|
||||||
|
|
@ -757,11 +763,11 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This stream buffer is just created and deleted to ensure no
|
/* This stream buffer is just created and deleted to ensure no
|
||||||
issues when attempting to delete a stream buffer that was
|
* issues when attempting to delete a stream buffer that was
|
||||||
created using statically allocated memory. To save stack space
|
* created using statically allocated memory. To save stack space
|
||||||
the buffer is set to point to the pc55ByteString, which is a const
|
* the buffer is set to point to the pc55ByteString, which is a const
|
||||||
string, but no data is written into the buffer so any valid address
|
* string, but no data is written into the buffer so any valid address
|
||||||
will do. */
|
* will do. */
|
||||||
xTempStreamBuffer = xStreamBufferCreateStatic( sizeof( ucTempBuffer ), sbTRIGGER_LEVEL_1, ucTempBuffer, &xStaticStreamBuffer );
|
xTempStreamBuffer = xStreamBufferCreateStatic( sizeof( ucTempBuffer ), sbTRIGGER_LEVEL_1, ucTempBuffer, &xStaticStreamBuffer );
|
||||||
xStreamBufferReset( xTempStreamBuffer );
|
xStreamBufferReset( xTempStreamBuffer );
|
||||||
vStreamBufferDelete( xTempStreamBuffer );
|
vStreamBufferDelete( xTempStreamBuffer );
|
||||||
|
|
@ -784,23 +790,23 @@ BaseType_t xNonBlockingReceiveError = pdFALSE;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Attempt to receive the number of bytes to the end of the string,
|
/* Attempt to receive the number of bytes to the end of the string,
|
||||||
or the number of byte that can be placed into the rx buffer,
|
* or the number of byte that can be placed into the rx buffer,
|
||||||
whichever is smallest. */
|
* whichever is smallest. */
|
||||||
xBytesToReceive = configMIN( ( xStringLength - xNextChar ), sizeof( cRxString ) );
|
xBytesToReceive = configMIN( ( xStringLength - xNextChar ), sizeof( cRxString ) );
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
xReceivedLength = xStreamBufferReceive( pxStreamBuffer, ( void * ) cRxString, xBytesToReceive, xTicksToWait );
|
xReceivedLength = xStreamBufferReceive( pxStreamBuffer, ( void * ) cRxString, xBytesToReceive, xTicksToWait );
|
||||||
|
|
||||||
} while( xReceivedLength == 0 );
|
} while( xReceivedLength == 0 );
|
||||||
|
|
||||||
/* Ensure the received string matches the expected string. */
|
/* Ensure the received string matches the expected string. */
|
||||||
prvCheckExpectedState( memcmp( ( void * ) cRxString, ( const void * ) &( pc55ByteString[ xNextChar ] ), xReceivedLength ) == 0 );
|
prvCheckExpectedState( memcmp( ( void * ) cRxString, ( const void * ) &( pc55ByteString[ xNextChar ] ), xReceivedLength ) == 0 );
|
||||||
|
|
||||||
/* Move the index into the string up to the end of the bytes
|
/* Move the index into the string up to the end of the bytes
|
||||||
received so far - wrapping if the end of the string has been
|
* received so far - wrapping if the end of the string has been
|
||||||
reached. */
|
* reached. */
|
||||||
xNextChar += xReceivedLength;
|
xNextChar += xReceivedLength;
|
||||||
|
|
||||||
if( xNextChar >= xStringLength )
|
if( xNextChar >= xStringLength )
|
||||||
{
|
{
|
||||||
xNextChar = 0;
|
xNextChar = 0;
|
||||||
|
|
@ -819,19 +825,19 @@ const TickType_t xTicksToWait = pdMS_TO_TICKS( 50 );
|
||||||
StreamBufferHandle_t xTempStreamBuffer;
|
StreamBufferHandle_t xTempStreamBuffer;
|
||||||
|
|
||||||
/* The task's priority is used as an index into the loop counters used to
|
/* The task's priority is used as an index into the loop counters used to
|
||||||
indicate this task is still running. */
|
* indicate this task is still running. */
|
||||||
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
UBaseType_t uxIndex = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
/* Pointers to the client and server stream buffers are passed into this task
|
/* Pointers to the client and server stream buffers are passed into this task
|
||||||
using the task's parameter. */
|
* using the task's parameter. */
|
||||||
EchoStreamBuffers_t * pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
|
EchoStreamBuffers_t * pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
|
||||||
|
|
||||||
/* Prevent compiler warnings. */
|
/* Prevent compiler warnings. */
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create the buffer into which strings to send to the server will be
|
/* Create the buffer into which strings to send to the server will be
|
||||||
created, and the buffer into which strings echoed back from the server will
|
* created, and the buffer into which strings echoed back from the server will
|
||||||
be copied. */
|
* be copied. */
|
||||||
pcStringToSend = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
|
pcStringToSend = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
|
||||||
pcStringReceived = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
|
pcStringReceived = ( char * ) pvPortMalloc( sbSTREAM_BUFFER_LENGTH_BYTES );
|
||||||
|
|
||||||
|
|
@ -844,8 +850,8 @@ EchoStreamBuffers_t *pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
|
||||||
xSendLength++;
|
xSendLength++;
|
||||||
|
|
||||||
/* The stream buffer is being used to hold variable length data, so
|
/* The stream buffer is being used to hold variable length data, so
|
||||||
each data item requires sizeof( size_t ) bytes to hold the data's
|
* each data item requires sizeof( size_t ) bytes to hold the data's
|
||||||
length, hence the sizeof() in the if() condition below. */
|
* length, hence the sizeof() in the if() condition below. */
|
||||||
if( xSendLength > ( sbSTREAM_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
|
if( xSendLength > ( sbSTREAM_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) )
|
||||||
{
|
{
|
||||||
/* Back to a string length of 1. */
|
/* Back to a string length of 1. */
|
||||||
|
|
@ -870,7 +876,6 @@ EchoStreamBuffers_t *pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ux = xStreamBufferSend( pxStreamBuffers->xEchoClientBuffer, ( void * ) pcStringToSend, xSendLength, xTicksToWait );
|
ux = xStreamBufferSend( pxStreamBuffers->xEchoClientBuffer, ( void * ) pcStringToSend, xSendLength, xTicksToWait );
|
||||||
|
|
||||||
} while( ux == 0 );
|
} while( ux == 0 );
|
||||||
|
|
||||||
/* Wait for the string to be echoed back. */
|
/* Wait for the string to be echoed back. */
|
||||||
|
|
@ -880,14 +885,14 @@ EchoStreamBuffers_t *pxStreamBuffers = ( EchoStreamBuffers_t * ) pvParameters;
|
||||||
prvCheckExpectedState( strcmp( pcStringToSend, pcStringReceived ) == 0 );
|
prvCheckExpectedState( strcmp( pcStringToSend, pcStringReceived ) == 0 );
|
||||||
|
|
||||||
/* Maintain a count of the number of times this code executes so a
|
/* Maintain a count of the number of times this code executes so a
|
||||||
check task can determine if this task is still functioning as
|
* check task can determine if this task is still functioning as
|
||||||
expected or not. As there are two client tasks, and the priorities
|
* expected or not. As there are two client tasks, and the priorities
|
||||||
used are 0 and 1, the task's priority is used as an index into the
|
* used are 0 and 1, the task's priority is used as an index into the
|
||||||
loop count array. */
|
* loop count array. */
|
||||||
ulEchoLoopCounters[ uxIndex ]++;
|
ulEchoLoopCounters[ uxIndex ]++;
|
||||||
|
|
||||||
/* This stream buffer is just created and deleted to ensure no memory
|
/* This stream buffer is just created and deleted to ensure no memory
|
||||||
leaks. */
|
* leaks. */
|
||||||
xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
xTempStreamBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
||||||
vStreamBufferDelete( xTempStreamBuffer );
|
vStreamBufferDelete( xTempStreamBuffer );
|
||||||
|
|
||||||
|
|
@ -951,8 +956,8 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create the stream buffer used to send data from the client to the server,
|
/* Create the stream buffer used to send data from the client to the server,
|
||||||
and the stream buffer used to echo the data from the server back to the
|
* and the stream buffer used to echo the data from the server back to the
|
||||||
client. */
|
* client. */
|
||||||
xStreamBuffers.xEchoClientBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
xStreamBuffers.xEchoClientBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
||||||
xStreamBuffers.xEchoServerBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
xStreamBuffers.xEchoServerBuffer = xStreamBufferCreate( sbSTREAM_BUFFER_LENGTH_BYTES, sbTRIGGER_LEVEL_1 );
|
||||||
configASSERT( xStreamBuffers.xEchoClientBuffer );
|
configASSERT( xStreamBuffers.xEchoClientBuffer );
|
||||||
|
|
@ -969,9 +974,9 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
|
||||||
prvCheckExpectedState( xReceivedLength == 0 );
|
prvCheckExpectedState( xReceivedLength == 0 );
|
||||||
|
|
||||||
/* Now the stream buffers have been created the echo client task can be
|
/* Now the stream buffers have been created the echo client task can be
|
||||||
created. If this server task has the higher priority then the client task
|
* created. If this server task has the higher priority then the client task
|
||||||
is created at the lower priority - if this server task has the lower
|
* is created at the lower priority - if this server task has the lower
|
||||||
priority then the client task is created at the higher priority. */
|
* priority then the client task is created at the higher priority. */
|
||||||
if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
|
if( uxTaskPriorityGet( NULL ) == sbLOWER_PRIORITY )
|
||||||
{
|
{
|
||||||
xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbHIGHER_PRIORITY, NULL );
|
xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbHIGHER_PRIORITY, NULL );
|
||||||
|
|
@ -979,7 +984,7 @@ const TickType_t xTicksToBlock = pdMS_TO_TICKS( 350UL );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Here prvSingleTaskTests() performs various tests on a stream buffer
|
/* Here prvSingleTaskTests() performs various tests on a stream buffer
|
||||||
that was created dynamically. */
|
* that was created dynamically. */
|
||||||
prvSingleTaskTests( xStreamBuffers.xEchoClientBuffer );
|
prvSingleTaskTests( xStreamBuffers.xEchoClientBuffer );
|
||||||
xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
|
xTaskCreate( prvEchoClient, "EchoClient", sbSMALLER_STACK_SIZE, ( void * ) &xStreamBuffers, sbLOWER_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
|
|
@ -1006,13 +1011,13 @@ static size_t xNextChar = 0;
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
/* Called from the tick interrupt hook. If the global stream buffer
|
/* Called from the tick interrupt hook. If the global stream buffer
|
||||||
variable is not NULL then the prvInterruptTriggerTest() task expects a byte
|
* variable is not NULL then the prvInterruptTriggerTest() task expects a byte
|
||||||
to be sent to the stream buffer on each tick interrupt. */
|
* to be sent to the stream buffer on each tick interrupt. */
|
||||||
if( xInterruptStreamBuffer != NULL )
|
if( xInterruptStreamBuffer != NULL )
|
||||||
{
|
{
|
||||||
/* One character from the pcDataSentFromInterrupt string is sent on each
|
/* One character from the pcDataSentFromInterrupt string is sent on each
|
||||||
interrupt. The task blocked on the stream buffer should not be
|
* interrupt. The task blocked on the stream buffer should not be
|
||||||
unblocked until the defined trigger level is hit. */
|
* unblocked until the defined trigger level is hit. */
|
||||||
xStreamBufferSendFromISR( xInterruptStreamBuffer, ( const void * ) &( pcDataSentFromInterrupt[ xNextChar ] ), sizeof( char ), &xHigherPriorityTaskWoken );
|
xStreamBufferSendFromISR( xInterruptStreamBuffer, ( const void * ) &( pcDataSentFromInterrupt[ xNextChar ] ), sizeof( char ), &xHigherPriorityTaskWoken );
|
||||||
|
|
||||||
if( xNextChar < strlen( pcDataSentFromInterrupt ) )
|
if( xNextChar < strlen( pcDataSentFromInterrupt ) )
|
||||||
|
|
@ -1036,6 +1041,7 @@ const size_t xStreamBufferSizeBytes = ( size_t ) 9, xMaxTriggerLevel = ( size_t
|
||||||
const TickType_t xReadBlockTime = 5, xCycleBlockTime = pdMS_TO_TICKS( 100 );
|
const TickType_t xReadBlockTime = 5, xCycleBlockTime = pdMS_TO_TICKS( 100 );
|
||||||
uint8_t ucRxData[ 9 ];
|
uint8_t ucRxData[ 9 ];
|
||||||
BaseType_t xErrorDetected = pdFALSE;
|
BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
#ifndef configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN
|
#ifndef configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN
|
||||||
const size_t xAllowableMargin = ( size_t ) 0;
|
const size_t xAllowableMargin = ( size_t ) 0;
|
||||||
#else
|
#else
|
||||||
|
|
@ -1050,20 +1056,20 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
for( xTriggerLevel = xMinTriggerLevel; xTriggerLevel < xMaxTriggerLevel; xTriggerLevel++ )
|
for( xTriggerLevel = xMinTriggerLevel; xTriggerLevel < xMaxTriggerLevel; xTriggerLevel++ )
|
||||||
{
|
{
|
||||||
/* This test is very time sensitive so delay at the beginning to ensure
|
/* This test is very time sensitive so delay at the beginning to ensure
|
||||||
the rest of the system is up and running before starting. Delay between
|
* the rest of the system is up and running before starting. Delay between
|
||||||
each loop to ensure the interrupt that sends to the stream buffer
|
* each loop to ensure the interrupt that sends to the stream buffer
|
||||||
detects it needs to start sending from the start of the strin again.. */
|
* detects it needs to start sending from the start of the strin again.. */
|
||||||
vTaskDelay( xCycleBlockTime );
|
vTaskDelay( xCycleBlockTime );
|
||||||
|
|
||||||
/* Create the stream buffer that will be used from inside the tick
|
/* Create the stream buffer that will be used from inside the tick
|
||||||
interrupt. */
|
* interrupt. */
|
||||||
memset( ucRxData, 0x00, sizeof( ucRxData ) );
|
memset( ucRxData, 0x00, sizeof( ucRxData ) );
|
||||||
xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
|
xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );
|
||||||
configASSERT( xStreamBuffer );
|
configASSERT( xStreamBuffer );
|
||||||
|
|
||||||
/* Now the stream buffer has been created it can be assigned to the
|
/* Now the stream buffer has been created it can be assigned to the
|
||||||
file scope variable, which will allow the tick interrupt to start
|
* file scope variable, which will allow the tick interrupt to start
|
||||||
using it. */
|
* using it. */
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
xInterruptStreamBuffer = xStreamBuffer;
|
xInterruptStreamBuffer = xStreamBuffer;
|
||||||
|
|
@ -1073,7 +1079,7 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
xBytesReceived = xStreamBufferReceive( xStreamBuffer, ( void * ) ucRxData, sizeof( ucRxData ), xReadBlockTime );
|
xBytesReceived = xStreamBufferReceive( xStreamBuffer, ( void * ) ucRxData, sizeof( ucRxData ), xReadBlockTime );
|
||||||
|
|
||||||
/* Set the file scope variable back to NULL so the interrupt doesn't
|
/* Set the file scope variable back to NULL so the interrupt doesn't
|
||||||
try to use it again. */
|
* try to use it again. */
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
xInterruptStreamBuffer = NULL;
|
xInterruptStreamBuffer = NULL;
|
||||||
|
|
@ -1081,18 +1087,18 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
/* Now check the number of bytes received equals the trigger level,
|
/* Now check the number of bytes received equals the trigger level,
|
||||||
except in the case that the read timed out before the trigger level
|
* except in the case that the read timed out before the trigger level
|
||||||
was reached. */
|
* was reached. */
|
||||||
if( xTriggerLevel > xReadBlockTime )
|
if( xTriggerLevel > xReadBlockTime )
|
||||||
{
|
{
|
||||||
/* Trigger level was greater than the block time so expect to
|
/* Trigger level was greater than the block time so expect to
|
||||||
time out having received xReadBlockTime bytes. */
|
* time out having received xReadBlockTime bytes. */
|
||||||
if( xBytesReceived > xReadBlockTime )
|
if( xBytesReceived > xReadBlockTime )
|
||||||
{
|
{
|
||||||
/* Received more bytes than expected. That could happen if
|
/* Received more bytes than expected. That could happen if
|
||||||
this task unblocked at the right time, but an interrupt
|
* this task unblocked at the right time, but an interrupt
|
||||||
added another byte to the stream buffer before this task was
|
* added another byte to the stream buffer before this task was
|
||||||
able to run. */
|
* able to run. */
|
||||||
if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
|
if( ( xBytesReceived - xReadBlockTime ) > xAllowableMargin )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -1101,9 +1107,9 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
else if( xReadBlockTime != xBytesReceived )
|
else if( xReadBlockTime != xBytesReceived )
|
||||||
{
|
{
|
||||||
/* It is possible the interrupt placed an item in the stream
|
/* It is possible the interrupt placed an item in the stream
|
||||||
buffer before this task called xStreamBufferReceive(), but
|
* buffer before this task called xStreamBufferReceive(), but
|
||||||
if that is the case then xBytesReceived will only every be
|
* if that is the case then xBytesReceived will only every be
|
||||||
0 as the interrupt will only have executed once. */
|
* 0 as the interrupt will only have executed once. */
|
||||||
if( xBytesReceived != 1 )
|
if( xBytesReceived != 1 )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -1113,15 +1119,15 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
else if( xTriggerLevel < xReadBlockTime )
|
else if( xTriggerLevel < xReadBlockTime )
|
||||||
{
|
{
|
||||||
/* Trigger level was less than the block time so we expect to
|
/* Trigger level was less than the block time so we expect to
|
||||||
have received the trigger level number of bytes - could be more
|
* have received the trigger level number of bytes - could be more
|
||||||
though depending on other activity between the task being
|
* though depending on other activity between the task being
|
||||||
unblocked and the task reading the number of bytes received. It
|
* unblocked and the task reading the number of bytes received. It
|
||||||
could also be less if the interrupt already put something in the
|
* could also be less if the interrupt already put something in the
|
||||||
stream buffer before this task attempted to read it - in which
|
* stream buffer before this task attempted to read it - in which
|
||||||
case the task would have returned the available bytes immediately
|
* case the task would have returned the available bytes immediately
|
||||||
without ever blocking - in that case the bytes received will
|
* without ever blocking - in that case the bytes received will
|
||||||
only ever be 1 as the interrupt would not have executed more
|
* only ever be 1 as the interrupt would not have executed more
|
||||||
than one in that time unless this task has too low a priority. */
|
* than one in that time unless this task has too low a priority. */
|
||||||
if( xBytesReceived < xTriggerLevel )
|
if( xBytesReceived < xTriggerLevel )
|
||||||
{
|
{
|
||||||
if( xBytesReceived != 1 )
|
if( xBytesReceived != 1 )
|
||||||
|
|
@ -1137,13 +1143,13 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The trigger level equalled the block time, so expect to
|
/* The trigger level equalled the block time, so expect to
|
||||||
receive no greater than the block time. It could also be less
|
* receive no greater than the block time. It could also be less
|
||||||
if the interrupt already put something in the stream buffer
|
* if the interrupt already put something in the stream buffer
|
||||||
before this task attempted to read it - in which case the task
|
* before this task attempted to read it - in which case the task
|
||||||
would have returned the available bytes immediately without ever
|
* would have returned the available bytes immediately without ever
|
||||||
blocking - in that case the bytes received would only ever be 1
|
* blocking - in that case the bytes received would only ever be 1
|
||||||
because the interrupt is not going to execute twice in that time
|
* because the interrupt is not going to execute twice in that time
|
||||||
unless this task is running a too low a priority. */
|
* unless this task is running a too low a priority. */
|
||||||
if( xBytesReceived < xReadBlockTime )
|
if( xBytesReceived < xReadBlockTime )
|
||||||
{
|
{
|
||||||
if( xBytesReceived != 1 )
|
if( xBytesReceived != 1 )
|
||||||
|
|
@ -1170,7 +1176,7 @@ BaseType_t xErrorDetected = pdFALSE;
|
||||||
if( xErrorDetected == pdFALSE )
|
if( xErrorDetected == pdFALSE )
|
||||||
{
|
{
|
||||||
/* Increment the cycle counter so the 'check' task knows this test
|
/* Increment the cycle counter so the 'check' task knows this test
|
||||||
is still running without error. */
|
* is still running without error. */
|
||||||
ulInterruptTriggerCounter++;
|
ulInterruptTriggerCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,19 +62,19 @@ static void prvReceivingTask( void *pvParameters );
|
||||||
static StreamBufferHandle_t xStreamBuffer = NULL;
|
static StreamBufferHandle_t xStreamBuffer = NULL;
|
||||||
|
|
||||||
/* The string that is sent from the interrupt to the task four bytes at a
|
/* The string that is sent from the interrupt to the task four bytes at a
|
||||||
time. Must be multiple of 4 bytes long as the ISR sends 4 bytes at a time*/
|
* time. Must be multiple of 4 bytes long as the ISR sends 4 bytes at a time*/
|
||||||
static const char * pcStringToSend = "_____Hello FreeRTOS_____";
|
static const char * pcStringToSend = "_____Hello FreeRTOS_____";
|
||||||
|
|
||||||
/* The string to task is looking for, which must be a substring of
|
/* The string to task is looking for, which must be a substring of
|
||||||
pcStringToSend. */
|
* pcStringToSend. */
|
||||||
static const char * pcStringToReceive = "Hello FreeRTOS";
|
static const char * pcStringToReceive = "Hello FreeRTOS";
|
||||||
|
|
||||||
/* Set to pdFAIL if anything unexpected happens. */
|
/* Set to pdFAIL if anything unexpected happens. */
|
||||||
static BaseType_t xDemoStatus = pdPASS;
|
static BaseType_t xDemoStatus = pdPASS;
|
||||||
|
|
||||||
/* Incremented each time pcStringToReceive is correctly received, provided no
|
/* Incremented each time pcStringToReceive is correctly received, provided no
|
||||||
errors have occurred. Used so the check task can check this task is still
|
* errors have occurred. Used so the check task can check this task is still
|
||||||
running as expected. */
|
* running as expected. */
|
||||||
static uint32_t ulCycleCount = 0;
|
static uint32_t ulCycleCount = 0;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -82,7 +82,7 @@ static uint32_t ulCycleCount = 0;
|
||||||
void vStartStreamBufferInterruptDemo( void )
|
void vStartStreamBufferInterruptDemo( void )
|
||||||
{
|
{
|
||||||
/* Create the stream buffer that sends data from the interrupt to the
|
/* Create the stream buffer that sends data from the interrupt to the
|
||||||
task, and create the task. */
|
* task, and create the task. */
|
||||||
xStreamBuffer = xStreamBufferCreate( /* The buffer length in bytes. */
|
xStreamBuffer = xStreamBufferCreate( /* The buffer length in bytes. */
|
||||||
sbiSTREAM_BUFFER_LENGTH_BYTES,
|
sbiSTREAM_BUFFER_LENGTH_BYTES,
|
||||||
/* The stream buffer's trigger level. */
|
/* The stream buffer's trigger level. */
|
||||||
|
|
@ -106,7 +106,7 @@ BaseType_t xNextByte = 0;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Make sure the string will fit in the Rx buffer, including the NULL
|
/* Make sure the string will fit in the Rx buffer, including the NULL
|
||||||
terminator. */
|
* terminator. */
|
||||||
configASSERT( sizeof( cRxBuffer ) > strlen( pcStringToReceive ) );
|
configASSERT( sizeof( cRxBuffer ) > strlen( pcStringToReceive ) );
|
||||||
|
|
||||||
/* Make sure the stream buffer has been created. */
|
/* Make sure the stream buffer has been created. */
|
||||||
|
|
@ -118,34 +118,35 @@ BaseType_t xNextByte = 0;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Keep receiving characters until the end of the string is received.
|
/* Keep receiving characters until the end of the string is received.
|
||||||
Note: An infinite block time is used to simplify the example. Infinite
|
* Note: An infinite block time is used to simplify the example. Infinite
|
||||||
block times are not recommended in production code as they do not allow
|
* block times are not recommended in production code as they do not allow
|
||||||
for error recovery. */
|
* for error recovery. */
|
||||||
xStreamBufferReceive( /* The stream buffer data is being received from. */
|
xStreamBufferReceive( /* The stream buffer data is being received from. */
|
||||||
xStreamBuffer,
|
xStreamBuffer,
|
||||||
/* Where to place received data. */
|
/* Where to place received data. */
|
||||||
( void * ) &( cRxBuffer[ xNextByte ] ),
|
( void * ) &( cRxBuffer[ xNextByte ] ),
|
||||||
/* The number of bytes to receive. */
|
/* The number of bytes to receive. */
|
||||||
sizeof( char ),
|
sizeof( char ),
|
||||||
|
|
||||||
/* The time to wait for the next data if the buffer
|
/* The time to wait for the next data if the buffer
|
||||||
is empty. */
|
* is empty. */
|
||||||
portMAX_DELAY );
|
portMAX_DELAY );
|
||||||
|
|
||||||
/* If xNextByte is 0 then this task is looking for the start of the
|
/* If xNextByte is 0 then this task is looking for the start of the
|
||||||
string, which is 'H'. */
|
* string, which is 'H'. */
|
||||||
if( xNextByte == 0 )
|
if( xNextByte == 0 )
|
||||||
{
|
{
|
||||||
if( cRxBuffer[ xNextByte ] == 'H' )
|
if( cRxBuffer[ xNextByte ] == 'H' )
|
||||||
{
|
{
|
||||||
/* The start of the string has been found. Now receive
|
/* The start of the string has been found. Now receive
|
||||||
characters until the end of the string is found. */
|
* characters until the end of the string is found. */
|
||||||
xNextByte++;
|
xNextByte++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Receiving characters while looking for the end of the string,
|
/* Receiving characters while looking for the end of the string,
|
||||||
which is an 'S'. */
|
* which is an 'S'. */
|
||||||
if( cRxBuffer[ xNextByte ] == 'S' )
|
if( cRxBuffer[ xNextByte ] == 'S' )
|
||||||
{
|
{
|
||||||
/* The string has now been received. Check its validity. */
|
/* The string has now been received. Check its validity. */
|
||||||
|
|
@ -155,12 +156,12 @@ BaseType_t xNextByte = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return to start looking for the beginning of the string
|
/* Return to start looking for the beginning of the string
|
||||||
again. */
|
* again. */
|
||||||
memset( cRxBuffer, 0x00, sizeof( cRxBuffer ) );
|
memset( cRxBuffer, 0x00, sizeof( cRxBuffer ) );
|
||||||
xNextByte = 0;
|
xNextByte = 0;
|
||||||
|
|
||||||
/* Increment the cycle count as an indication to the check task
|
/* Increment the cycle count as an indication to the check task
|
||||||
that this demo is still running. */
|
* that this demo is still running. */
|
||||||
if( xDemoStatus == pdPASS )
|
if( xDemoStatus == pdPASS )
|
||||||
{
|
{
|
||||||
ulCycleCount++;
|
ulCycleCount++;
|
||||||
|
|
@ -169,7 +170,7 @@ BaseType_t xNextByte = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Receive the next character the next time around, while
|
/* Receive the next character the next time around, while
|
||||||
continuing to look for the end of the string. */
|
* continuing to look for the end of the string. */
|
||||||
xNextByte++;
|
xNextByte++;
|
||||||
|
|
||||||
configASSERT( ( size_t ) xNextByte < sizeof( cRxBuffer ) );
|
configASSERT( ( size_t ) xNextByte < sizeof( cRxBuffer ) );
|
||||||
|
|
@ -187,6 +188,7 @@ static BaseType_t xCallCount = 0;
|
||||||
|
|
||||||
/* Is it time to write to the stream buffer again? */
|
/* Is it time to write to the stream buffer again? */
|
||||||
xCallCount++;
|
xCallCount++;
|
||||||
|
|
||||||
if( xCallCount > xCallsBetweenSends )
|
if( xCallCount > xCallsBetweenSends )
|
||||||
{
|
{
|
||||||
xCallCount = 0;
|
xCallCount = 0;
|
||||||
|
|
@ -198,7 +200,7 @@ static BaseType_t xCallCount = 0;
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
/* Send the next four bytes the next time around, wrapping to the start
|
/* Send the next four bytes the next time around, wrapping to the start
|
||||||
of the string if necessary. */
|
* of the string if necessary. */
|
||||||
xNextByteToSend += xBytesToSend;
|
xNextByteToSend += xBytesToSend;
|
||||||
|
|
||||||
if( xNextByteToSend >= strlen( pcStringToSend ) )
|
if( xNextByteToSend >= strlen( pcStringToSend ) )
|
||||||
|
|
@ -225,4 +227,3 @@ uint32_t ulLastCycleCount = 0;
|
||||||
|
|
||||||
return xDemoStatus;
|
return xDemoStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,8 @@ static volatile uint32_t ulNotifyCycleCount = 0;
|
||||||
static TaskHandle_t xTaskToNotify = NULL;
|
static TaskHandle_t xTaskToNotify = NULL;
|
||||||
|
|
||||||
/* Used to count the notifications sent to the task from a software timer and
|
/* Used to count the notifications sent to the task from a software timer and
|
||||||
the number of notifications received by the task from the software timer. The
|
* the number of notifications received by the task from the software timer. The
|
||||||
two should stay synchronised. */
|
* two should stay synchronised. */
|
||||||
static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0UL;
|
static uint32_t ulTimerNotificationsReceived = 0UL, ulTimerNotificationsSent = 0UL;
|
||||||
|
|
||||||
/* The timer used to notify the task. */
|
/* The timer used to notify the task. */
|
||||||
|
|
@ -113,7 +113,7 @@ static size_t uxNextRand = 0;
|
||||||
void vStartTaskNotifyTask( void )
|
void vStartTaskNotifyTask( void )
|
||||||
{
|
{
|
||||||
/* Create the task that performs some tests by itself, then loops around
|
/* Create the task that performs some tests by itself, then loops around
|
||||||
being notified by both a software timer and an interrupt. */
|
* being notified by both a software timer and an interrupt. */
|
||||||
xTaskCreate( prvNotifiedTask, /* Function that implements the task. */
|
xTaskCreate( prvNotifiedTask, /* Function that implements the task. */
|
||||||
"Notified", /* Text name for the task - for debugging only - not used by the kernel. */
|
"Notified", /* Text name for the task - for debugging only - not used by the kernel. */
|
||||||
notifyNOTIFIED_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */
|
notifyNOTIFIED_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */
|
||||||
|
|
@ -138,7 +138,7 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Check blocking when there are no notifications. */
|
* Check blocking when there are no notifications. */
|
||||||
xTimeOnEntering = xTaskGetTickCount();
|
xTimeOnEntering = xTaskGetTickCount();
|
||||||
xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
|
xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -148,6 +148,7 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
{
|
{
|
||||||
xErrorStatus = pdFAIL;
|
xErrorStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
configASSERT( xReturned == pdFAIL );
|
configASSERT( xReturned == pdFAIL );
|
||||||
configASSERT( ulNotifiedValue == 0UL );
|
configASSERT( ulNotifiedValue == 0UL );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -155,15 +156,14 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Check no blocking when notifications are pending. First notify itself -
|
* Check no blocking when notifications are pending. First notify itself -
|
||||||
this would not be a normal thing to do and is done here for test purposes
|
* this would not be a normal thing to do and is done here for test purposes
|
||||||
only. */
|
* only. */
|
||||||
xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
xReturned = xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
||||||
|
|
||||||
/* Even through the 'without overwrite' action was used the update should
|
/* Even through the 'without overwrite' action was used the update should
|
||||||
have been successful. */
|
* have been successful. */
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
|
|
@ -181,7 +181,7 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The task should have been notified, and the notified value should
|
/* The task should have been notified, and the notified value should
|
||||||
be equal to ulFirstNotifiedConst. */
|
* be equal to ulFirstNotifiedConst. */
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
|
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -192,13 +192,11 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check the non-overwriting functionality. The notification is done twice
|
* Check the non-overwriting functionality. The notification is done twice
|
||||||
using two different notification values. The action says don't overwrite so
|
* using two different notification values. The action says don't overwrite so
|
||||||
only the first notification should pass and the value read back should also
|
* only the first notification should pass and the value read back should also
|
||||||
be that used with the first notification. */
|
* be that used with the first notification. */
|
||||||
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
|
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -208,7 +206,7 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Waiting for the notification should now return immediately so a block
|
/* Waiting for the notification should now return immediately so a block
|
||||||
time of zero is used. */
|
* time of zero is used. */
|
||||||
xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
|
||||||
|
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
|
|
@ -218,13 +216,11 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Do the same again, only this time use the overwriting version. This time
|
* Do the same again, only this time use the overwriting version. This time
|
||||||
both notifications should pass, and the value written the second time should
|
* both notifications should pass, and the value written the second time should
|
||||||
overwrite the value written the first time, and so be the value that is read
|
* overwrite the value written the first time, and so be the value that is read
|
||||||
back. */
|
* back. */
|
||||||
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );
|
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithOverwrite );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -239,11 +235,10 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check notifications with no action pass without updating the value. Even
|
* Check notifications with no action pass without updating the value. Even
|
||||||
though ulFirstNotifiedConst is used as the value the value read back should
|
* though ulFirstNotifiedConst is used as the value the value read back should
|
||||||
remain at ulSecondNotifiedConst. */
|
* remain at ulSecondNotifiedConst. */
|
||||||
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );
|
xReturned = xTaskNotify( xTaskToNotify, ulFirstNotifiedConst, eNoAction );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -251,13 +246,10 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
|
configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
|
||||||
( void ) ulNotifiedValue; /* In case configASSERT() is not defined. */
|
( void ) ulNotifiedValue; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check incrementing values. Send ulMaxLoop increment notifications, then
|
* Check incrementing values. Send ulMaxLoop increment notifications, then
|
||||||
ensure the received value is as expected - which should be
|
* ensure the received value is as expected - which should be
|
||||||
ulSecondNotificationValueConst plus how ever many times to loop iterated. */
|
* ulSecondNotificationValueConst plus how ever many times to loop iterated. */
|
||||||
for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
|
for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
|
||||||
{
|
{
|
||||||
xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );
|
xReturned = xTaskNotify( xTaskToNotify, 0, eIncrement );
|
||||||
|
|
@ -279,12 +271,11 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check all bits can be set by notifying the task with one additional bit set
|
* Check all bits can be set by notifying the task with one additional bit set
|
||||||
on each notification, and exiting the loop when all the bits are found to be
|
* on each notification, and exiting the loop when all the bits are found to be
|
||||||
set. As there are 32-bits the loop should execute 32 times before all the
|
* set. As there are 32-bits the loop should execute 32 times before all the
|
||||||
bits are found to be set. */
|
* bits are found to be set. */
|
||||||
ulNotifyingValue = 0x01;
|
ulNotifyingValue = 0x01;
|
||||||
ulLoop = 0;
|
ulLoop = 0;
|
||||||
|
|
||||||
|
|
@ -297,8 +288,8 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits );
|
xTaskNotify( xTaskToNotify, ulNotifyingValue, eSetBits );
|
||||||
|
|
||||||
/* Wait for the notified value - which of course will already be
|
/* Wait for the notified value - which of course will already be
|
||||||
available. Don't clear the bits on entry or exit as this loop is exited
|
* available. Don't clear the bits on entry or exit as this loop is exited
|
||||||
when all the bits are set. */
|
* when all the bits are set. */
|
||||||
xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWait( 0, 0, &ulNotifiedValue, 0 );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
@ -307,34 +298,32 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
/* Use the next bit on the next iteration around this loop. */
|
/* Use the next bit on the next iteration around this loop. */
|
||||||
ulNotifyingValue <<= 1UL;
|
ulNotifyingValue <<= 1UL;
|
||||||
|
|
||||||
} while( ulNotifiedValue != notifyUINT32_MAX );
|
} while( ulNotifiedValue != notifyUINT32_MAX );
|
||||||
|
|
||||||
/* As a 32-bit value was used the loop should have executed 32 times before
|
/* As a 32-bit value was used the loop should have executed 32 times before
|
||||||
all the bits were set. */
|
* all the bits were set. */
|
||||||
configASSERT( ulLoop == 32 );
|
configASSERT( ulLoop == 32 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check bits are cleared on entry but not on exit when a notification fails
|
* Check bits are cleared on entry but not on exit when a notification fails
|
||||||
to arrive before timing out - both with and without a timeout value. Wait
|
* to arrive before timing out - both with and without a timeout value. Wait
|
||||||
for the notification again - but this time it is not given by anything and
|
* for the notification again - but this time it is not given by anything and
|
||||||
should return pdFAIL. The parameters are set to clear bit zero on entry and
|
* should return pdFAIL. The parameters are set to clear bit zero on entry and
|
||||||
bit one on exit. As no notification was received only the bit cleared on
|
* bit one on exit. As no notification was received only the bit cleared on
|
||||||
entry should actually get cleared. */
|
* entry should actually get cleared. */
|
||||||
xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
|
xReturned = xTaskNotifyWait( ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
|
||||||
configASSERT( xReturned == pdFAIL );
|
configASSERT( xReturned == pdFAIL );
|
||||||
( void ) xReturned; /* In case configASSERT() is not defined. */
|
( void ) xReturned; /* In case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Notify the task with no action so as not to update the bits even though
|
/* Notify the task with no action so as not to update the bits even though
|
||||||
notifyUINT32_MAX is used as the notification value. */
|
* notifyUINT32_MAX is used as the notification value. */
|
||||||
xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eNoAction );
|
xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eNoAction );
|
||||||
|
|
||||||
/* Reading back the value should should find bit 0 is clear, as this was
|
/* Reading back the value should should find bit 0 is clear, as this was
|
||||||
cleared on entry, but bit 1 is not clear as it will not have been cleared on
|
* cleared on entry, but bit 1 is not clear as it will not have been cleared on
|
||||||
exit as no notification was received. */
|
* exit as no notification was received. */
|
||||||
xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWait( 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
|
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
|
||||||
|
|
@ -342,22 +331,20 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Now try clearing the bit on exit. For that to happen a notification must be
|
* Now try clearing the bit on exit. For that to happen a notification must be
|
||||||
received, so the task is notified first. */
|
* received, so the task is notified first. */
|
||||||
xTaskNotify( xTaskToNotify, 0, eNoAction );
|
xTaskNotify( xTaskToNotify, 0, eNoAction );
|
||||||
xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 );
|
xTaskNotifyWait( 0x00, ulBit1, &ulNotifiedValue, 0 );
|
||||||
|
|
||||||
/* However as the bit is cleared on exit, after the returned notification
|
/* However as the bit is cleared on exit, after the returned notification
|
||||||
value is set, the returned notification value should not have the bit
|
* value is set, the returned notification value should not have the bit
|
||||||
cleared... */
|
* cleared... */
|
||||||
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
|
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
|
||||||
|
|
||||||
/* ...but reading the value back again should find that the bit was indeed
|
/* ...but reading the value back again should find that the bit was indeed
|
||||||
cleared internally. The returned value should be pdFAIL however as nothing
|
* cleared internally. The returned value should be pdFAIL however as nothing
|
||||||
has notified the task in the mean time. */
|
* has notified the task in the mean time. */
|
||||||
xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWait( 0x00, 0x00, &ulNotifiedValue, 0 );
|
||||||
configASSERT( xReturned == pdFAIL );
|
configASSERT( xReturned == pdFAIL );
|
||||||
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
|
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
|
||||||
|
|
@ -365,9 +352,8 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Now try querying the previous value while notifying a task. */
|
* Now try querying the previous value while notifying a task. */
|
||||||
xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
|
xTaskNotifyAndQuery( xTaskToNotify, 0x00, eSetBits, &ulPreviousValue );
|
||||||
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
|
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
|
||||||
|
|
||||||
|
|
@ -377,54 +363,53 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
configASSERT( ulPreviousValue == 0 );
|
configASSERT( ulPreviousValue == 0 );
|
||||||
|
|
||||||
ulExpectedValue = 0;
|
ulExpectedValue = 0;
|
||||||
|
|
||||||
for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
|
for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
|
||||||
{
|
{
|
||||||
/* Set the next bit up, and expect to receive the last bits set (so
|
/* Set the next bit up, and expect to receive the last bits set (so
|
||||||
the previous value will not yet have the bit being set this time
|
* the previous value will not yet have the bit being set this time
|
||||||
around). */
|
* around). */
|
||||||
xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue );
|
xTaskNotifyAndQuery( xTaskToNotify, ulLoop, eSetBits, &ulPreviousValue );
|
||||||
configASSERT( ulExpectedValue == ulPreviousValue );
|
configASSERT( ulExpectedValue == ulPreviousValue );
|
||||||
ulExpectedValue |= ulLoop;
|
ulExpectedValue |= ulLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Clear the previous notifications. */
|
* Clear the previous notifications. */
|
||||||
xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
|
xTaskNotifyWait( notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
|
||||||
|
|
||||||
/* The task should not have any notifications pending, so an attempt to clear
|
/* The task should not have any notifications pending, so an attempt to clear
|
||||||
the notification state should fail. */
|
* the notification state should fail. */
|
||||||
configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
|
configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
|
||||||
|
|
||||||
/* Get the task to notify itself. This is not a normal thing to do, and is
|
/* Get the task to notify itself. This is not a normal thing to do, and is
|
||||||
only done here for test purposes. */
|
* only done here for test purposes. */
|
||||||
xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
xTaskNotifyAndQuery( xTaskToNotify, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
||||||
|
|
||||||
/* Now the notification state should be eNotified, so it should now be
|
/* Now the notification state should be eNotified, so it should now be
|
||||||
possible to clear the notification state. */
|
* possible to clear the notification state. */
|
||||||
configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
|
configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
|
||||||
configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
|
configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Clear bits in the notification value. */
|
* Clear bits in the notification value. */
|
||||||
|
|
||||||
/* Get the task to set all bits its own notification value. This is not a
|
/* Get the task to set all bits its own notification value. This is not a
|
||||||
normal thing to do, and is only done here for test purposes. */
|
* normal thing to do, and is only done here for test purposes. */
|
||||||
xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eSetBits );
|
xTaskNotify( xTaskToNotify, notifyUINT32_MAX, eSetBits );
|
||||||
|
|
||||||
/* Now clear the top bytes - the returned value from the first call should
|
/* Now clear the top bytes - the returned value from the first call should
|
||||||
indicate that previously all bits were set. */
|
* indicate that previously all bits were set. */
|
||||||
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );
|
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );
|
||||||
|
|
||||||
/* Next clear the bottom bytes - the returned value this time should indicate
|
/* Next clear the bottom bytes - the returned value this time should indicate
|
||||||
that the top byte was clear (before the bottom byte was cleared. */
|
* that the top byte was clear (before the bottom byte was cleared. */
|
||||||
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
|
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
|
||||||
|
|
||||||
/* Next clear all bytes - the returned value should indicate that previously the
|
/* Next clear all bytes - the returned value should indicate that previously the
|
||||||
high and low bytes were clear. */
|
* high and low bytes were clear. */
|
||||||
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );
|
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );
|
||||||
|
|
||||||
/* Now all bits should be clear. */
|
/* Now all bits should be clear. */
|
||||||
|
|
@ -433,14 +418,14 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == 0 );
|
configASSERT( ulTaskNotifyValueClear( xTaskToNotify, notifyUINT32_MAX ) == 0 );
|
||||||
|
|
||||||
/* Now the notification state should be eNotified, so it should now be
|
/* Now the notification state should be eNotified, so it should now be
|
||||||
possible to clear the notification state. */
|
* possible to clear the notification state. */
|
||||||
configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
|
configASSERT( xTaskNotifyStateClear( NULL ) == pdTRUE );
|
||||||
configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
|
configASSERT( xTaskNotifyStateClear( NULL ) == pdFALSE );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Create a timer that will try notifying this task while it is suspended. */
|
* Create a timer that will try notifying this task while it is suspended. */
|
||||||
xSingleTaskTimer = xTimerCreate( "SingleNotify", notifySUSPENDED_TEST_TIMER_PERIOD, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
|
xSingleTaskTimer = xTimerCreate( "SingleNotify", notifySUSPENDED_TEST_TIMER_PERIOD, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
|
||||||
configASSERT( xSingleTaskTimer );
|
configASSERT( xSingleTaskTimer );
|
||||||
|
|
||||||
|
|
@ -451,13 +436,13 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
|
xTaskNotifyWait( notifyUINT32_MAX, 0, NULL, 0 );
|
||||||
|
|
||||||
/* Raise the task's priority so it can suspend itself before the timer
|
/* Raise the task's priority so it can suspend itself before the timer
|
||||||
expires. */
|
* expires. */
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
|
|
||||||
/* Start the timer that will try notifying this task while it is
|
/* Start the timer that will try notifying this task while it is
|
||||||
suspended, then wait for a notification. The first time the callback
|
* suspended, then wait for a notification. The first time the callback
|
||||||
executes the timer will suspend the task, then resume the task, without
|
* executes the timer will suspend the task, then resume the task, without
|
||||||
ever sending a notification to the task. */
|
* ever sending a notification to the task. */
|
||||||
ulNotifiedValue = 0;
|
ulNotifiedValue = 0;
|
||||||
xTimerStart( xSingleTaskTimer, portMAX_DELAY );
|
xTimerStart( xSingleTaskTimer, portMAX_DELAY );
|
||||||
|
|
||||||
|
|
@ -471,9 +456,9 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
ulNotifyCycleCount++;
|
ulNotifyCycleCount++;
|
||||||
|
|
||||||
/* Start the timer that will try notifying this task while it is
|
/* Start the timer that will try notifying this task while it is
|
||||||
suspended, then wait for a notification. The second time the callback
|
* suspended, then wait for a notification. The second time the callback
|
||||||
executes the timer will suspend the task, notify the task, then resume the
|
* executes the timer will suspend the task, notify the task, then resume the
|
||||||
task (previously it was suspended and resumed without being notified). */
|
* task (previously it was suspended and resumed without being notified). */
|
||||||
xTimerStart( xSingleTaskTimer, portMAX_DELAY );
|
xTimerStart( xSingleTaskTimer, portMAX_DELAY );
|
||||||
|
|
||||||
/* Check a notification is received. */
|
/* Check a notification is received. */
|
||||||
|
|
@ -483,7 +468,7 @@ TimerHandle_t xSingleTaskTimer;
|
||||||
configASSERT( ulNotifiedValue != 0 );
|
configASSERT( ulNotifiedValue != 0 );
|
||||||
|
|
||||||
/* Return the task to its proper priority and delete the timer as it is
|
/* Return the task to its proper priority and delete the timer as it is
|
||||||
not used again. */
|
* not used again. */
|
||||||
vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
|
vTaskPrioritySet( NULL, notifyTASK_PRIORITY );
|
||||||
xTimerDelete( xSingleTaskTimer, portMAX_DELAY );
|
xTimerDelete( xSingleTaskTimer, portMAX_DELAY );
|
||||||
|
|
||||||
|
|
@ -503,9 +488,9 @@ static uint32_t ulCallCount = 0;
|
||||||
( void ) xExpiredTimer;
|
( void ) xExpiredTimer;
|
||||||
|
|
||||||
/* Callback for a timer that is used during preliminary testing. The timer
|
/* Callback for a timer that is used during preliminary testing. The timer
|
||||||
tests the behaviour when 1: a task waiting for a notification is suspended
|
* tests the behaviour when 1: a task waiting for a notification is suspended
|
||||||
and then resumed without ever receiving a notification, and 2: when a task
|
* and then resumed without ever receiving a notification, and 2: when a task
|
||||||
waiting for a notification receives a notification while it is suspended. */
|
* waiting for a notification receives a notification while it is suspended. */
|
||||||
|
|
||||||
if( ulCallCount == 0 )
|
if( ulCallCount == 0 )
|
||||||
{
|
{
|
||||||
|
|
@ -518,8 +503,8 @@ static uint32_t ulCallCount = 0;
|
||||||
vTaskSuspend( xTaskToNotify );
|
vTaskSuspend( xTaskToNotify );
|
||||||
|
|
||||||
/* Sending a notification while the task is suspended should pass, but
|
/* Sending a notification while the task is suspended should pass, but
|
||||||
not cause the task to resume. ulCallCount is just used as a convenient
|
* not cause the task to resume. ulCallCount is just used as a convenient
|
||||||
non-zero value. */
|
* non-zero value. */
|
||||||
xTaskNotify( xTaskToNotify, ulCallCount, eSetValueWithOverwrite );
|
xTaskNotify( xTaskToNotify, ulCallCount, eSetValueWithOverwrite );
|
||||||
|
|
||||||
/* Make sure giving the notification didn't resume the task. */
|
/* Make sure giving the notification didn't resume the task. */
|
||||||
|
|
@ -557,19 +542,20 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Run a few tests that can be done from a single task before entering the
|
/* Run a few tests that can be done from a single task before entering the
|
||||||
main loop. */
|
* main loop. */
|
||||||
prvSingleTaskTests();
|
prvSingleTaskTests();
|
||||||
|
|
||||||
/* Create the software timer that is used to send notifications to this
|
/* Create the software timer that is used to send notifications to this
|
||||||
task. Notifications are also received from an interrupt. */
|
* task. Notifications are also received from an interrupt. */
|
||||||
xTimer = xTimerCreate( "Notifier", xMaxPeriod, pdFALSE, NULL, prvNotifyingTimer );
|
xTimer = xTimerCreate( "Notifier", xMaxPeriod, pdFALSE, NULL, prvNotifyingTimer );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Start the timer again with a different period. Sometimes the period
|
/* Start the timer again with a different period. Sometimes the period
|
||||||
will be higher than the task's block time, sometimes it will be lower
|
* will be higher than the task's block time, sometimes it will be lower
|
||||||
than the task's block time. */
|
* than the task's block time. */
|
||||||
xPeriod = prvRand() % xMaxPeriod;
|
xPeriod = prvRand() % xMaxPeriod;
|
||||||
|
|
||||||
if( xPeriod < xMinPeriod )
|
if( xPeriod < xMinPeriod )
|
||||||
{
|
{
|
||||||
xPeriod = xMinPeriod;
|
xPeriod = xMinPeriod;
|
||||||
|
|
@ -579,47 +565,47 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
|
||||||
xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );
|
xTimerChangePeriod( xTimer, xPeriod, portMAX_DELAY );
|
||||||
|
|
||||||
/* Block waiting for the notification again with a different period.
|
/* Block waiting for the notification again with a different period.
|
||||||
Sometimes the period will be higher than the task's block time,
|
* Sometimes the period will be higher than the task's block time,
|
||||||
sometimes it will be lower than the task's block time. */
|
* sometimes it will be lower than the task's block time. */
|
||||||
xPeriod = prvRand() % xMaxPeriod;
|
xPeriod = prvRand() % xMaxPeriod;
|
||||||
|
|
||||||
if( xPeriod < xMinPeriod )
|
if( xPeriod < xMinPeriod )
|
||||||
{
|
{
|
||||||
xPeriod = xMinPeriod;
|
xPeriod = xMinPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Block to wait for a notification but without clearing the
|
/* Block to wait for a notification but without clearing the
|
||||||
notification count, so only add one to the count of received
|
* notification count, so only add one to the count of received
|
||||||
notifications as any other notifications will remain pending. */
|
* notifications as any other notifications will remain pending. */
|
||||||
if( ulTaskNotifyTake( pdFALSE, xPeriod ) != 0 )
|
if( ulTaskNotifyTake( pdFALSE, xPeriod ) != 0 )
|
||||||
{
|
{
|
||||||
ulTimerNotificationsReceived++;
|
ulTimerNotificationsReceived++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Take a notification without clearing again, but this time without a
|
/* Take a notification without clearing again, but this time without a
|
||||||
block time specified. */
|
* block time specified. */
|
||||||
if( ulTaskNotifyTake( pdFALSE, xDontBlock ) != 0 )
|
if( ulTaskNotifyTake( pdFALSE, xDontBlock ) != 0 )
|
||||||
{
|
{
|
||||||
ulTimerNotificationsReceived++;
|
ulTimerNotificationsReceived++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the next notification from the timer, clearing all
|
/* Wait for the next notification from the timer, clearing all
|
||||||
notifications if one is received, so this time adding the total number
|
* notifications if one is received, so this time adding the total number
|
||||||
of notifications that were pending as none will be left pending after
|
* of notifications that were pending as none will be left pending after
|
||||||
the function call. */
|
* the function call. */
|
||||||
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );
|
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, xPeriod );
|
||||||
|
|
||||||
/* Occasionally raise the priority of the task being notified to test
|
/* Occasionally raise the priority of the task being notified to test
|
||||||
the path where the task is notified from an ISR and becomes the highest
|
* the path where the task is notified from an ISR and becomes the highest
|
||||||
priority ready state task, but the pxHigherPriorityTaskWoken parameter
|
* priority ready state task, but the pxHigherPriorityTaskWoken parameter
|
||||||
is NULL (which it is in the tick hook that sends notifications to this
|
* is NULL (which it is in the tick hook that sends notifications to this
|
||||||
task). */
|
* task). */
|
||||||
if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )
|
if( ( ulNotifyCycleCount % ulCyclesToRaisePriority ) == 0 )
|
||||||
{
|
{
|
||||||
vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( xTaskToNotify, configMAX_PRIORITIES - 1 );
|
||||||
|
|
||||||
/* Wait for the next notification again, clearing all notifications
|
/* Wait for the next notification again, clearing all notifications
|
||||||
if one is received, but this time blocking indefinitely. */
|
* if one is received, but this time blocking indefinitely. */
|
||||||
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
|
|
||||||
/* Reset the priority. */
|
/* Reset the priority. */
|
||||||
|
|
@ -628,7 +614,7 @@ const uint32_t ulCyclesToRaisePriority = 50UL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Wait for the next notification again, clearing all notifications
|
/* Wait for the next notification again, clearing all notifications
|
||||||
if one is received, but this time blocking indefinitely. */
|
* if one is received, but this time blocking indefinitely. */
|
||||||
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
ulTimerNotificationsReceived += ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -649,9 +635,9 @@ const uint32_t ulUnexpectedValue = 0xff;
|
||||||
configASSERT( xTaskToNotify );
|
configASSERT( xTaskToNotify );
|
||||||
|
|
||||||
/* The task performs some tests before starting the timer that gives the
|
/* The task performs some tests before starting the timer that gives the
|
||||||
notification from this interrupt. If the timer has not been created yet
|
* notification from this interrupt. If the timer has not been created yet
|
||||||
then the initial tests have not yet completed and the notification should
|
* then the initial tests have not yet completed and the notification should
|
||||||
not be sent. */
|
* not be sent. */
|
||||||
if( xTimer != NULL )
|
if( xTimer != NULL )
|
||||||
{
|
{
|
||||||
xCallCount++;
|
xCallCount++;
|
||||||
|
|
@ -662,18 +648,21 @@ const uint32_t ulUnexpectedValue = 0xff;
|
||||||
xCallCount = 0;
|
xCallCount = 0;
|
||||||
|
|
||||||
/* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
|
/* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
|
||||||
and xTaskNotifyAndQueryFromISR(). */
|
* and xTaskNotifyAndQueryFromISR(). */
|
||||||
switch( xAPIToUse )
|
switch( xAPIToUse )
|
||||||
{
|
{
|
||||||
case 0: vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
|
case 0:
|
||||||
|
vTaskNotifyGiveFromISR( xTaskToNotify, NULL );
|
||||||
xAPIToUse++;
|
xAPIToUse++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );
|
case 1:
|
||||||
|
xTaskNotifyFromISR( xTaskToNotify, 0, eIncrement, NULL );
|
||||||
xAPIToUse++;
|
xAPIToUse++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: ulPreviousValue = ulUnexpectedValue;
|
case 2:
|
||||||
|
ulPreviousValue = ulUnexpectedValue;
|
||||||
xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );
|
xTaskNotifyAndQueryFromISR( xTaskToNotify, 0, eIncrement, &ulPreviousValue, NULL );
|
||||||
configASSERT( ulPreviousValue != ulUnexpectedValue );
|
configASSERT( ulPreviousValue != ulUnexpectedValue );
|
||||||
xAPIToUse = 0;
|
xAPIToUse = 0;
|
||||||
|
|
@ -690,14 +679,14 @@ const uint32_t ulUnexpectedValue = 0xff;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* This is called to check the created tasks are still running and have not
|
/* This is called to check the created tasks are still running and have not
|
||||||
detected any errors. */
|
* detected any errors. */
|
||||||
BaseType_t xAreTaskNotificationTasksStillRunning( void )
|
BaseType_t xAreTaskNotificationTasksStillRunning( void )
|
||||||
{
|
{
|
||||||
static uint32_t ulLastNotifyCycleCount = 0;
|
static uint32_t ulLastNotifyCycleCount = 0;
|
||||||
const uint32_t ulMaxSendReceiveDeviation = 5UL;
|
const uint32_t ulMaxSendReceiveDeviation = 5UL;
|
||||||
|
|
||||||
/* Check the cycle count is still incrementing to ensure the task is still
|
/* Check the cycle count is still incrementing to ensure the task is still
|
||||||
actually running. */
|
* actually running. */
|
||||||
if( ulLastNotifyCycleCount == ulNotifyCycleCount )
|
if( ulLastNotifyCycleCount == ulNotifyCycleCount )
|
||||||
{
|
{
|
||||||
xErrorStatus = pdFAIL;
|
xErrorStatus = pdFAIL;
|
||||||
|
|
@ -708,7 +697,7 @@ const uint32_t ulMaxSendReceiveDeviation = 5UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the count of 'takes' from the software timer is keeping track with
|
/* Check the count of 'takes' from the software timer is keeping track with
|
||||||
the amount of 'gives'. */
|
* the amount of 'gives'. */
|
||||||
if( ulTimerNotificationsSent > ulTimerNotificationsReceived )
|
if( ulTimerNotificationsSent > ulTimerNotificationsReceived )
|
||||||
{
|
{
|
||||||
if( ( ulTimerNotificationsSent - ulTimerNotificationsReceived ) > ulMaxSendReceiveDeviation )
|
if( ( ulTimerNotificationsSent - ulTimerNotificationsReceived ) > ulMaxSendReceiveDeviation )
|
||||||
|
|
|
||||||
|
|
@ -122,14 +122,14 @@ static UBaseType_t prvRand( void );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Counters used to check the task has not stalled. ulFineCycleCount is
|
/* Counters used to check the task has not stalled. ulFineCycleCount is
|
||||||
incremented within each test. ulCourseCycleCounter is incremented one every
|
* incremented within each test. ulCourseCycleCounter is incremented one every
|
||||||
loop of all the tests to ensure each test is actually executing. The check task
|
* loop of all the tests to ensure each test is actually executing. The check task
|
||||||
calls xAreTaskNotificationArrayTasksStillRunning() (implemented within this
|
* calls xAreTaskNotificationArrayTasksStillRunning() (implemented within this
|
||||||
file) to check both counters are changing. */
|
* file) to check both counters are changing. */
|
||||||
static volatile uint32_t ulFineCycleCount = 0, ulCourseCycleCounter = 0;
|
static volatile uint32_t ulFineCycleCount = 0, ulCourseCycleCounter = 0;
|
||||||
|
|
||||||
/* The handle of the task that runs the tests and receives the notifications
|
/* The handle of the task that runs the tests and receives the notifications
|
||||||
from the software timers and interrupts. */
|
* from the software timers and interrupts. */
|
||||||
static TaskHandle_t xTaskToNotify = NULL;
|
static TaskHandle_t xTaskToNotify = NULL;
|
||||||
|
|
||||||
/* The software timers used to send notifications to the main test task. */
|
/* The software timers used to send notifications to the main test task. */
|
||||||
|
|
@ -150,14 +150,14 @@ const TickType_t xIncrementingIndexTimerPeriod = pdMS_TO_TICKS( 100 );
|
||||||
const TickType_t xSuspendTimerPeriod = pdMS_TO_TICKS( 50 );
|
const TickType_t xSuspendTimerPeriod = pdMS_TO_TICKS( 50 );
|
||||||
|
|
||||||
/* Create the software timers used for these tests. The timer callbacks send
|
/* Create the software timers used for these tests. The timer callbacks send
|
||||||
notifications to this task. */
|
* notifications to this task. */
|
||||||
xNotifyWhileSuspendedTimer = xTimerCreate( "SingleNotify", xSuspendTimerPeriod, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
|
xNotifyWhileSuspendedTimer = xTimerCreate( "SingleNotify", xSuspendTimerPeriod, pdFALSE, NULL, prvSuspendedTaskTimerTestCallback );
|
||||||
xIncrementingIndexTimer = xTimerCreate( "Notifier", xIncrementingIndexTimerPeriod, pdFALSE, NULL, prvNotifyingTimerCallback );
|
xIncrementingIndexTimer = xTimerCreate( "Notifier", xIncrementingIndexTimerPeriod, pdFALSE, NULL, prvNotifyingTimerCallback );
|
||||||
configASSERT( xNotifyWhileSuspendedTimer );
|
configASSERT( xNotifyWhileSuspendedTimer );
|
||||||
configASSERT( xIncrementingIndexTimer );
|
configASSERT( xIncrementingIndexTimer );
|
||||||
|
|
||||||
/* Create the task that performs some tests by itself, then loops around
|
/* Create the task that performs some tests by itself, then loops around
|
||||||
being notified by both a software timer and an interrupt. */
|
* being notified by both a software timer and an interrupt. */
|
||||||
xTaskCreate( prvNotifiedTask, /* Function that implements the task. */
|
xTaskCreate( prvNotifiedTask, /* Function that implements the task. */
|
||||||
"ArrayNotifed", /* Text name for the task - for debugging only - not used by the kernel. */
|
"ArrayNotifed", /* Text name for the task - for debugging only - not used by the kernel. */
|
||||||
notifyNOTIFY_ARRAY_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */
|
notifyNOTIFY_ARRAY_TASK_STACK_SIZE, /* Task's stack size in words, not bytes!. */
|
||||||
|
|
@ -176,7 +176,7 @@ static void prvNotifiedTask( void *pvParameters )
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Loop through each set of test functions in turn. See the comments above
|
/* Loop through each set of test functions in turn. See the comments above
|
||||||
the respective function prototypes above for more details. */
|
* the respective function prototypes above for more details. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
prvSingleTaskTests();
|
prvSingleTaskTests();
|
||||||
|
|
@ -201,12 +201,12 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Check blocking when there are no notifications. */
|
* Check blocking when there are no notifications. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* Send notifications to the task notification in each index of the
|
/* Send notifications to the task notification in each index of the
|
||||||
task notification array other than the one on which this task will
|
* task notification array other than the one on which this task will
|
||||||
block. */
|
* block. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
if( uxOtherIndexes != uxIndexToTest )
|
if( uxOtherIndexes != uxIndexToTest )
|
||||||
|
|
@ -229,7 +229,7 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
( void ) ulNotifiedValue;
|
( void ) ulNotifiedValue;
|
||||||
|
|
||||||
/* Clear all the other notifications within the array of task
|
/* Clear all the other notifications within the array of task
|
||||||
notifications again ready for the next round. */
|
* notifications again ready for the next round. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
if( uxOtherIndexes != uxIndexToTest )
|
if( uxOtherIndexes != uxIndexToTest )
|
||||||
|
|
@ -237,26 +237,24 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
|
xReturned = xTaskNotifyStateClearIndexed( xTaskToNotify, uxOtherIndexes );
|
||||||
|
|
||||||
/* The notification state was set above so expect it to still be
|
/* The notification state was set above so expect it to still be
|
||||||
set. */
|
* set. */
|
||||||
configASSERT( xReturned == pdTRUE );
|
configASSERT( xReturned == pdTRUE );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
Check no blocking when notifications are pending. */
|
* Check no blocking when notifications are pending. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* First notify the task notification at index uxIndexToTest within this
|
/* First notify the task notification at index uxIndexToTest within this
|
||||||
task's own array of task notifications - this would not be a normal
|
* task's own array of task notifications - this would not be a normal
|
||||||
thing to do and is done here for test purposes only. */
|
* thing to do and is done here for test purposes only. */
|
||||||
xReturned = xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
xReturned = xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
||||||
|
|
||||||
/* Even through the 'without overwrite' action was used the update should
|
/* Even through the 'without overwrite' action was used the update should
|
||||||
have been successful. */
|
* have been successful. */
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
|
|
@ -265,8 +263,8 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
( void ) ulPreviousValue;
|
( void ) ulPreviousValue;
|
||||||
|
|
||||||
/* The task should now have a notification pending in the task
|
/* The task should now have a notification pending in the task
|
||||||
notification at index uxIndexToTest within the task notification array,
|
* notification at index uxIndexToTest within the task notification array,
|
||||||
and so not time out. */
|
* and so not time out. */
|
||||||
xTimeOnEntering = xTaskGetTickCount();
|
xTimeOnEntering = xTaskGetTickCount();
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, xTicksToWait );
|
||||||
xTimeNow = xTaskGetTickCount();
|
xTimeNow = xTaskGetTickCount();
|
||||||
|
|
@ -274,22 +272,19 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
configASSERT( xTimeDifference < xTicksToWait );
|
configASSERT( xTimeDifference < xTicksToWait );
|
||||||
|
|
||||||
/* The task should have been notified, and the notified value should
|
/* The task should have been notified, and the notified value should
|
||||||
be equal to ulFirstNotifiedConst. */
|
* be equal to ulFirstNotifiedConst. */
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
|
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
( void ) ulNotifiedValue;
|
( void ) ulNotifiedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check the non-overwriting functionality. */
|
* Check the non-overwriting functionality. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* Send notifications to all indexes with the array of task
|
/* Send notifications to all indexes with the array of task
|
||||||
notifications other than the one on which this task will block. */
|
* notifications other than the one on which this task will block. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
if( uxOtherIndexes != uxIndexToTest )
|
if( uxOtherIndexes != uxIndexToTest )
|
||||||
|
|
@ -301,10 +296,10 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The notification is performed twice using two different notification
|
/* The notification is performed twice using two different notification
|
||||||
values. The action says don't overwrite so only the first notification
|
* values. The action says don't overwrite so only the first notification
|
||||||
should pass and the value read back should also be that used with the
|
* should pass and the value read back should also be that used with the
|
||||||
first notification. The notification is sent to the task notification at
|
* first notification. The notification is sent to the task notification at
|
||||||
index uxIndexToTest within the array of task notifications. */
|
* index uxIndexToTest within the array of task notifications. */
|
||||||
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
|
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
@ -314,7 +309,7 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Waiting for the notification should now return immediately so a block
|
/* Waiting for the notification should now return immediately so a block
|
||||||
time of zero is used. */
|
* time of zero is used. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, notifyUINT32_MAX, 0, &ulNotifiedValue, 0 );
|
||||||
|
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
|
|
@ -323,7 +318,7 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
( void ) ulNotifiedValue;
|
( void ) ulNotifiedValue;
|
||||||
|
|
||||||
/* Clear all the other task notifications within the array of task
|
/* Clear all the other task notifications within the array of task
|
||||||
notifications again ready for the next round. */
|
* notifications again ready for the next round. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
if( uxOtherIndexes != uxIndexToTest )
|
if( uxOtherIndexes != uxIndexToTest )
|
||||||
|
|
@ -335,21 +330,18 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
|
ulNotifiedValue = ulTaskNotifyValueClearIndexed( xTaskToNotify, uxOtherIndexes, notifyUINT32_MAX );
|
||||||
|
|
||||||
/* The notification value was set to ulFirstNotifiedConst in all
|
/* The notification value was set to ulFirstNotifiedConst in all
|
||||||
the other indexes, so expect it to still have that value. */
|
* the other indexes, so expect it to still have that value. */
|
||||||
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
|
configASSERT( ulNotifiedValue == ulFirstNotifiedConst );
|
||||||
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Do the same again, only this time use the overwriting version. This time
|
* Do the same again, only this time use the overwriting version. This time
|
||||||
both notifications should pass, and the value written the second time should
|
* both notifications should pass, and the value written the second time should
|
||||||
overwrite the value written the first time, and so be the value that is read
|
* overwrite the value written the first time, and so be the value that is read
|
||||||
back. */
|
* back. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
|
|
@ -386,43 +378,40 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
For each task notification within the array of task notifications, check
|
* For each task notification within the array of task notifications, check
|
||||||
notifications with no action pass without updating the value. */
|
* notifications with no action pass without updating the value. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* First set the notification values of the task notification at index
|
/* First set the notification values of the task notification at index
|
||||||
uxIndexToTest of the array of task notification to
|
* uxIndexToTest of the array of task notification to
|
||||||
ulSecondNotifiedValueConst. */
|
* ulSecondNotifiedValueConst. */
|
||||||
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
|
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulSecondNotifiedValueConst, eSetValueWithOverwrite );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Even though ulFirstNotifiedConst is used as the value next, the value
|
/* Even though ulFirstNotifiedConst is used as the value next, the value
|
||||||
read back should remain at ulSecondNotifiedConst as the action is set
|
* read back should remain at ulSecondNotifiedConst as the action is set
|
||||||
to eNoAction. */
|
* to eNoAction. */
|
||||||
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eNoAction );
|
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eNoAction );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* All task notifications in the array of task notifications up to and
|
/* All task notifications in the array of task notifications up to and
|
||||||
including index uxIndexToTest should still contain the same value. */
|
* including index uxIndexToTest should still contain the same value. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* First zero is bits to clear on entry, the second is bits to clear on
|
/* First zero is bits to clear on entry, the second is bits to clear on
|
||||||
exist, the last 0 is the block time. */
|
* exist, the last 0 is the block time. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
||||||
configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
|
configASSERT( ulNotifiedValue == ulSecondNotifiedValueConst );
|
||||||
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All array indexes in the array of task notifications after index
|
/* All array indexes in the array of task notifications after index
|
||||||
uxIndexToTest should still contain 0 as they have not been set in this
|
* uxIndexToTest should still contain 0 as they have not been set in this
|
||||||
loop yet. This time use ulTaskNotifyValueClearIndexed() instead of
|
* loop yet. This time use ulTaskNotifyValueClearIndexed() instead of
|
||||||
xTaskNotifyWaitIndexed(), just for test coverage. */
|
* xTaskNotifyWaitIndexed(), just for test coverage. */
|
||||||
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
||||||
|
|
@ -432,31 +421,28 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Check incrementing values. For each task notification in the array of task
|
* Check incrementing values. For each task notification in the array of task
|
||||||
notifications in turn, send ulMaxLoop increment notifications, then ensure
|
* notifications in turn, send ulMaxLoop increment notifications, then ensure
|
||||||
the received value is as expected - which should be
|
* the received value is as expected - which should be
|
||||||
ulSecondNotificationValueConst plus how ever many times to loop iterated. */
|
* ulSecondNotificationValueConst plus how ever many times to loop iterated. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
|
for( ulLoop = 0; ulLoop < ulMaxLoops; ulLoop++ )
|
||||||
{
|
{
|
||||||
/* Increment the value of the task notification at index
|
/* Increment the value of the task notification at index
|
||||||
uxIndexToTest within the array of task notifications. */
|
* uxIndexToTest within the array of task notifications. */
|
||||||
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eIncrement );
|
xReturned = xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eIncrement );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All array indexes up to and including uxIndexToTest should still
|
/* All array indexes up to and including uxIndexToTest should still
|
||||||
contain the updated value. */
|
* contain the updated value. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* First zero is bits to clear on entry, the second is bits to clear on
|
/* First zero is bits to clear on entry, the second is bits to clear on
|
||||||
exist, the last 0 is the block time. */
|
* exist, the last 0 is the block time. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
||||||
configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
|
configASSERT( ulNotifiedValue == ( ulSecondNotifiedValueConst + ulMaxLoops ) );
|
||||||
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
@ -469,10 +455,10 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
( void ) ulNotifiedValue;
|
( void ) ulNotifiedValue;
|
||||||
|
|
||||||
/* All notifications values in the array of task notifications after
|
/* All notifications values in the array of task notifications after
|
||||||
index uxIndexToTest should still contain the un-incremented
|
* index uxIndexToTest should still contain the un-incremented
|
||||||
ulSecondNotifiedValueConst as they have not been set in this loop yet.
|
* ulSecondNotifiedValueConst as they have not been set in this loop yet.
|
||||||
This time use ulTaskNotifyValueClearIndexed() instead of xTaskNotifyWaitIndexed(),
|
* This time use ulTaskNotifyValueClearIndexed() instead of xTaskNotifyWaitIndexed(),
|
||||||
just for test coverage. */
|
* just for test coverage. */
|
||||||
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
||||||
|
|
@ -489,14 +475,12 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
ulTaskNotifyValueClearIndexed( NULL, uxIndexToTest, notifyUINT32_MAX );
|
ulTaskNotifyValueClearIndexed( NULL, uxIndexToTest, notifyUINT32_MAX );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
For each task notification in the array of task notifications in turn, check
|
* For each task notification in the array of task notifications in turn, check
|
||||||
all bits in the notification's value can be set by notifying the task with
|
* all bits in the notification's value can be set by notifying the task with
|
||||||
one additional bit set on each notification, and exiting the loop when all
|
* one additional bit set on each notification, and exiting the loop when all
|
||||||
the bits are found to be set. As there are 32-bits the loop should execute
|
* the bits are found to be set. As there are 32-bits the loop should execute
|
||||||
32 times before all the bits are found to be set. */
|
* 32 times before all the bits are found to be set. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
ulNotifyingValue = 0x01;
|
ulNotifyingValue = 0x01;
|
||||||
|
|
@ -505,12 +489,12 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Set the next bit in the value of the task notification at index
|
/* Set the next bit in the value of the task notification at index
|
||||||
uxIndexToTest within the array of task notifications. */
|
* uxIndexToTest within the array of task notifications. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulNotifyingValue, eSetBits );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, ulNotifyingValue, eSetBits );
|
||||||
|
|
||||||
/* Wait for the notified value - which of course will already be
|
/* Wait for the notified value - which of course will already be
|
||||||
available. Don't clear the bits on entry or exit as this loop is
|
* available. Don't clear the bits on entry or exit as this loop is
|
||||||
exited when all the bits are set. */
|
* exited when all the bits are set. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, 0 );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
@ -519,29 +503,28 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
|
|
||||||
/* Use the next bit on the next iteration around this loop. */
|
/* Use the next bit on the next iteration around this loop. */
|
||||||
ulNotifyingValue <<= 1UL;
|
ulNotifyingValue <<= 1UL;
|
||||||
|
|
||||||
} while( ulNotifiedValue != notifyUINT32_MAX );
|
} while( ulNotifiedValue != notifyUINT32_MAX );
|
||||||
|
|
||||||
/* As a 32-bit value was used the loop should have executed 32 times before
|
/* As a 32-bit value was used the loop should have executed 32 times before
|
||||||
all the bits were set. */
|
* all the bits were set. */
|
||||||
configASSERT( ulLoop == 32 );
|
configASSERT( ulLoop == 32 );
|
||||||
|
|
||||||
/* The value of each task notification within the array of task
|
/* The value of each task notification within the array of task
|
||||||
notifications up to and including index uxIndexToTest should still have
|
* notifications up to and including index uxIndexToTest should still have
|
||||||
all bits set. */
|
* all bits set. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* First zero is bits to clear on entry, the second is bits to clear on
|
/* First zero is bits to clear on entry, the second is bits to clear on
|
||||||
exist, the last 0 is the block time. */
|
* exist, the last 0 is the block time. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
||||||
configASSERT( ulNotifiedValue == notifyUINT32_MAX );
|
configASSERT( ulNotifiedValue == notifyUINT32_MAX );
|
||||||
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) ulNotifiedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The value of each task notification within the array of task
|
/* The value of each task notification within the array of task
|
||||||
notifications after index uxIndexToTest should still contain 0 as they
|
* notifications after index uxIndexToTest should still contain 0 as they
|
||||||
have not been set in this loop yet. This time use ulTaskNotifyValueClearIndexed()
|
* have not been set in this loop yet. This time use ulTaskNotifyValueClearIndexed()
|
||||||
instead of xTaskNotifyWaitIndexed(), just for test coverage. */
|
* instead of xTaskNotifyWaitIndexed(), just for test coverage. */
|
||||||
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
||||||
|
|
@ -551,40 +534,39 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
For each task notification within the array of task notifications in turn,
|
* For each task notification within the array of task notifications in turn,
|
||||||
check bits are cleared on entry but not on exit when a notification fails
|
* check bits are cleared on entry but not on exit when a notification fails
|
||||||
to arrive before timing out - both with and without a timeout value. */
|
* to arrive before timing out - both with and without a timeout value. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* Wait for the notification - but this time it is not given by anything
|
/* Wait for the notification - but this time it is not given by anything
|
||||||
and should return pdFAIL. The parameters are set to clear bit zero on
|
* and should return pdFAIL. The parameters are set to clear bit zero on
|
||||||
entry and bit one on exit. As no notification was received only the bit
|
* entry and bit one on exit. As no notification was received only the bit
|
||||||
cleared on entry should actually get cleared. */
|
* cleared on entry should actually get cleared. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, ulBit0, ulBit1, &ulNotifiedValue, xTicksToWait );
|
||||||
configASSERT( xReturned == pdFAIL );
|
configASSERT( xReturned == pdFAIL );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Send a notification with no action to the task notification at index
|
/* Send a notification with no action to the task notification at index
|
||||||
uxIndexToTest within the array of task notifications. This should not
|
* uxIndexToTest within the array of task notifications. This should not
|
||||||
update the bits even though notifyUINT32_MAX is used as the notification
|
* update the bits even though notifyUINT32_MAX is used as the notification
|
||||||
value. */
|
* value. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eNoAction );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eNoAction );
|
||||||
|
|
||||||
/* All array indexes up to and including uxIndexToTest within the array
|
/* All array indexes up to and including uxIndexToTest within the array
|
||||||
of task notifications should have the modified value. */
|
* of task notifications should have the modified value. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes <= uxIndexToTest; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* Reading back the value should find bit 0 is clear, as this was cleared
|
/* Reading back the value should find bit 0 is clear, as this was cleared
|
||||||
on entry, but bit 1 is not clear as it will not have been cleared on exit
|
* on entry, but bit 1 is not clear as it will not have been cleared on exit
|
||||||
as no notification was received. */
|
* as no notification was received. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0x00UL, 0x00UL, &ulNotifiedValue, 0 );
|
||||||
|
|
||||||
if( uxOtherIndexes == uxIndexToTest )
|
if( uxOtherIndexes == uxIndexToTest )
|
||||||
{
|
{
|
||||||
/* This is the index being used this time round the loop and its
|
/* This is the index being used this time round the loop and its
|
||||||
notification state was set immediately above. */
|
* notification state was set immediately above. */
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -598,8 +580,8 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All array indexes after uxIndexToTest should still contain notifyUINT32_MAX
|
/* All array indexes after uxIndexToTest should still contain notifyUINT32_MAX
|
||||||
left over from the previous test. This time use xTaskNotifyValueClear()
|
* left over from the previous test. This time use xTaskNotifyValueClear()
|
||||||
instead of xTaskNotifyWaitIndexed(), just for test coverage. */
|
* instead of xTaskNotifyWaitIndexed(), just for test coverage. */
|
||||||
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = uxIndexToTest + 1; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
/* This time 0 is the bits to clear parameter - so clearing no bits. */
|
||||||
|
|
@ -609,26 +591,23 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
Now try clearing the bit on exit. */
|
* Now try clearing the bit on exit. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* The task is notified first using the task notification at index
|
/* The task is notified first using the task notification at index
|
||||||
uxIndexToTest within the array of task notifications. */
|
* uxIndexToTest within the array of task notifications. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eNoAction );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, 0, eNoAction );
|
||||||
xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, ulBit1, &ulNotifiedValue, 0 );
|
xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, ulBit1, &ulNotifiedValue, 0 );
|
||||||
|
|
||||||
/* However as the bit is cleared on exit, after the returned notification
|
/* However as the bit is cleared on exit, after the returned notification
|
||||||
value is set, the returned notification value should not have the bit
|
* value is set, the returned notification value should not have the bit
|
||||||
cleared... */
|
* cleared... */
|
||||||
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
|
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~ulBit0 ) );
|
||||||
|
|
||||||
/* ...but reading the value back again should find that the bit was indeed
|
/* ...but reading the value back again should find that the bit was indeed
|
||||||
cleared internally. The returned value should be pdFAIL however as nothing
|
* cleared internally. The returned value should be pdFAIL however as nothing
|
||||||
has notified the task in the mean time. */
|
* has notified the task in the mean time. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, 0x00, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0x00, 0x00, &ulNotifiedValue, 0 );
|
||||||
configASSERT( xReturned == pdFAIL );
|
configASSERT( xReturned == pdFAIL );
|
||||||
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
|
configASSERT( ulNotifiedValue == ( notifyUINT32_MAX & ~( ulBit0 | ulBit1 ) ) );
|
||||||
|
|
@ -646,11 +625,9 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
For each task notification within the array of task notifications, try
|
* For each task notification within the array of task notifications, try
|
||||||
querying the previous value while notifying a task. */
|
* querying the previous value while notifying a task. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
|
xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, 0x00, eSetBits, &ulPreviousValue );
|
||||||
|
|
@ -662,18 +639,18 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
configASSERT( ulPreviousValue == 0 );
|
configASSERT( ulPreviousValue == 0 );
|
||||||
|
|
||||||
ulExpectedValue = 0;
|
ulExpectedValue = 0;
|
||||||
|
|
||||||
for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
|
for( ulLoop = 0x01; ulLoop < 0x80UL; ulLoop <<= 1UL )
|
||||||
{
|
{
|
||||||
/* Set the next bit up, and expect to receive the last bits set (so
|
/* Set the next bit up, and expect to receive the last bits set (so
|
||||||
the previous value will not yet have the bit being set this time
|
* the previous value will not yet have the bit being set this time
|
||||||
around). */
|
* around). */
|
||||||
xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulLoop, eSetBits, &ulPreviousValue );
|
xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulLoop, eSetBits, &ulPreviousValue );
|
||||||
configASSERT( ulExpectedValue == ulPreviousValue );
|
configASSERT( ulExpectedValue == ulPreviousValue );
|
||||||
ulExpectedValue |= ulLoop;
|
ulExpectedValue |= ulLoop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
|
|
@ -684,22 +661,22 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* No task notification within the array of task notifications should
|
/* No task notification within the array of task notifications should
|
||||||
have any notification pending, so an attempt to clear the notification
|
* have any notification pending, so an attempt to clear the notification
|
||||||
state should fail. */
|
* state should fail. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
|
configASSERT( xTaskNotifyStateClearIndexed( NULL, uxOtherIndexes ) == pdFALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the task to notify itself using the task notification at index
|
/* Get the task to notify itself using the task notification at index
|
||||||
uxIndexToTest within the array of task notifications. This is not a
|
* uxIndexToTest within the array of task notifications. This is not a
|
||||||
normal thing to do, and is only done here for test purposes. */
|
* normal thing to do, and is only done here for test purposes. */
|
||||||
xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToTest, ulFirstNotifiedConst, eSetValueWithoutOverwrite, &ulPreviousValue );
|
||||||
|
|
||||||
/* Now the notification state should be eNotified, so it should now be
|
/* Now the notification state should be eNotified, so it should now be
|
||||||
possible to clear the notification state. Other indexes should still
|
* possible to clear the notification state. Other indexes should still
|
||||||
not have a notification pending - likewise uxIndexToTest should not have
|
* not have a notification pending - likewise uxIndexToTest should not have
|
||||||
a notification pending once it has been cleared. */
|
* a notification pending once it has been cleared. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
if( uxOtherIndexes == uxIndexToTest )
|
if( uxOtherIndexes == uxIndexToTest )
|
||||||
|
|
@ -711,28 +688,27 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
For each task notification within the array of task notifications, clear
|
* For each task notification within the array of task notifications, clear
|
||||||
bits in the notification value. */
|
* bits in the notification value. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* Get the task to set all bits in its task notification at index
|
/* Get the task to set all bits in its task notification at index
|
||||||
uxIndexToTest within its array of task notifications. This is not a
|
* uxIndexToTest within its array of task notifications. This is not a
|
||||||
normal thing to do, and is only done here for test purposes. */
|
* normal thing to do, and is only done here for test purposes. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eSetBits );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX, eSetBits );
|
||||||
|
|
||||||
/* Now clear the top bytes - the returned value from the first call
|
/* Now clear the top bytes - the returned value from the first call
|
||||||
should indicate that previously all bits were set. */
|
* should indicate that previously all bits were set. */
|
||||||
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );
|
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_HIGH_BYTE ) == notifyUINT32_MAX );
|
||||||
|
|
||||||
/* Next clear the bottom bytes - the returned value this time should
|
/* Next clear the bottom bytes - the returned value this time should
|
||||||
indicate that the top byte was clear (before the bottom byte was
|
* indicate that the top byte was clear (before the bottom byte was
|
||||||
cleared. */
|
* cleared. */
|
||||||
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
|
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_LOW_BYTE ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE ) );
|
||||||
|
|
||||||
/* Next clear all bytes - the returned value should indicate that previously the
|
/* Next clear all bytes - the returned value should indicate that previously the
|
||||||
high and low bytes were clear. */
|
* high and low bytes were clear. */
|
||||||
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );
|
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == ( notifyUINT32_MAX & ~notifyUINT32_HIGH_BYTE & ~notifyUINT32_LOW_BYTE ) );
|
||||||
|
|
||||||
/* Now all bits should be clear. */
|
/* Now all bits should be clear. */
|
||||||
|
|
@ -741,14 +717,11 @@ UBaseType_t uxIndexToTest, uxOtherIndexes;
|
||||||
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == 0 );
|
configASSERT( ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToTest, notifyUINT32_MAX ) == 0 );
|
||||||
|
|
||||||
/* Now the notification state should be eNotified, so it should now be
|
/* Now the notification state should be eNotified, so it should now be
|
||||||
possible to clear the notification state. */
|
* possible to clear the notification state. */
|
||||||
configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdTRUE );
|
configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdTRUE );
|
||||||
configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdFALSE );
|
configASSERT( xTaskNotifyStateClearIndexed( NULL, uxIndexToTest ) == pdFALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Incremented to show the task is still running. */
|
/* Incremented to show the task is still running. */
|
||||||
ulFineCycleCount++;
|
ulFineCycleCount++;
|
||||||
|
|
||||||
|
|
@ -769,12 +742,12 @@ static UBaseType_t uxIndexToNotify = 0;
|
||||||
( void ) xExpiredTimer;
|
( void ) xExpiredTimer;
|
||||||
|
|
||||||
/* Callback for a timer that is used to send notifications to a task while
|
/* Callback for a timer that is used to send notifications to a task while
|
||||||
it is suspended. The timer tests the behaviour when 1: a task waiting for a
|
* it is suspended. The timer tests the behaviour when 1: a task waiting for a
|
||||||
notification is suspended and then resumed without ever receiving a
|
* notification is suspended and then resumed without ever receiving a
|
||||||
notification, and 2: when a task waiting for a notification receives a
|
* notification, and 2: when a task waiting for a notification receives a
|
||||||
notification while it is suspended. Run one of two tests on every other
|
* notification while it is suspended. Run one of two tests on every other
|
||||||
invocation of this callback. The notification is sent to the task
|
* invocation of this callback. The notification is sent to the task
|
||||||
notification at index uxIndexToNotify. */
|
* notification at index uxIndexToNotify. */
|
||||||
if( ( ulCallCount & 0x01 ) == 0 )
|
if( ( ulCallCount & 0x01 ) == 0 )
|
||||||
{
|
{
|
||||||
vTaskSuspend( xTaskToNotify );
|
vTaskSuspend( xTaskToNotify );
|
||||||
|
|
@ -786,12 +759,13 @@ static UBaseType_t uxIndexToNotify = 0;
|
||||||
vTaskSuspend( xTaskToNotify );
|
vTaskSuspend( xTaskToNotify );
|
||||||
|
|
||||||
/* Sending a notification while the task is suspended should pass, but
|
/* Sending a notification while the task is suspended should pass, but
|
||||||
not cause the task to resume. */
|
* not cause the task to resume. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 1, eSetValueWithOverwrite );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 1, eSetValueWithOverwrite );
|
||||||
|
|
||||||
/* Use the next task notification within the array of task notifications
|
/* Use the next task notification within the array of task notifications
|
||||||
the next time around. */
|
* the next time around. */
|
||||||
uxIndexToNotify++;
|
uxIndexToNotify++;
|
||||||
|
|
||||||
if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
|
if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
|
||||||
{
|
{
|
||||||
uxIndexToNotify = 0;
|
uxIndexToNotify = 0;
|
||||||
|
|
@ -814,13 +788,14 @@ static BaseType_t uxIndexToNotify = 0;
|
||||||
( void ) xNotUsed;
|
( void ) xNotUsed;
|
||||||
|
|
||||||
/* "Give" the task notification (which increments the target task
|
/* "Give" the task notification (which increments the target task
|
||||||
notification value) at index uxIndexToNotify within the array of task
|
* notification value) at index uxIndexToNotify within the array of task
|
||||||
notifications. */
|
* notifications. */
|
||||||
xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
|
xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
|
||||||
|
|
||||||
/* Use the next task notification within the array of task notifications the
|
/* Use the next task notification within the array of task notifications the
|
||||||
next time around. */
|
* next time around. */
|
||||||
uxIndexToNotify++;
|
uxIndexToNotify++;
|
||||||
|
|
||||||
if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
|
if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
|
||||||
{
|
{
|
||||||
uxIndexToNotify = 0;
|
uxIndexToNotify = 0;
|
||||||
|
|
@ -835,15 +810,15 @@ BaseType_t xReturned;
|
||||||
uint32_t ulNotifiedValue;
|
uint32_t ulNotifiedValue;
|
||||||
|
|
||||||
/* Raise the task's priority so it can suspend itself before the timer
|
/* Raise the task's priority so it can suspend itself before the timer
|
||||||
expires. */
|
* expires. */
|
||||||
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
|
|
||||||
/* Perform the test on each task notification within the array or task
|
/* Perform the test on each task notification within the array or task
|
||||||
notifications. */
|
* notifications. */
|
||||||
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
for( uxIndexToTest = 0; uxIndexToTest < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToTest++ )
|
||||||
{
|
{
|
||||||
/* Ensure no notifications within the array of task notifications are
|
/* Ensure no notifications within the array of task notifications are
|
||||||
pending. */
|
* pending. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, NULL, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, NULL, 0 );
|
||||||
|
|
@ -852,21 +827,21 @@ uint32_t ulNotifiedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the timer that will try notifying this task while it is
|
/* Start the timer that will try notifying this task while it is
|
||||||
suspended, then wait for a notification. The first time the callback
|
* suspended, then wait for a notification. The first time the callback
|
||||||
executes the timer will suspend the task, then resume the task, without
|
* executes the timer will suspend the task, then resume the task, without
|
||||||
ever sending a notification to the task. */
|
* ever sending a notification to the task. */
|
||||||
ulNotifiedValue = 0;
|
ulNotifiedValue = 0;
|
||||||
xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
|
xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
|
||||||
|
|
||||||
/* Check a notification is not received on the task notification at
|
/* Check a notification is not received on the task notification at
|
||||||
index uxIndexToTest within the array of task notifications. */
|
* index uxIndexToTest within the array of task notifications. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
|
||||||
configASSERT( xReturned == pdFALSE );
|
configASSERT( xReturned == pdFALSE );
|
||||||
configASSERT( ulNotifiedValue == 0 );
|
configASSERT( ulNotifiedValue == 0 );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* Check none of the task notifications within the array of task
|
/* Check none of the task notifications within the array of task
|
||||||
notifications as been notified. */
|
* notifications as been notified. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
||||||
|
|
@ -875,23 +850,23 @@ uint32_t ulNotifiedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the timer that will try notifying this task while it is
|
/* Start the timer that will try notifying this task while it is
|
||||||
suspended, then wait for a notification at index uxIndexToTest within
|
* suspended, then wait for a notification at index uxIndexToTest within
|
||||||
the array of task notifications. The second time the callback executes
|
* the array of task notifications. The second time the callback executes
|
||||||
the timer will suspend the task, notify the task, then resume the task
|
* the timer will suspend the task, notify the task, then resume the task
|
||||||
(previously it was suspended and resumed without being notified). */
|
* (previously it was suspended and resumed without being notified). */
|
||||||
xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
|
xTimerStart( xNotifyWhileSuspendedTimer, portMAX_DELAY );
|
||||||
|
|
||||||
/* Check a notification is only received in the index within the array
|
/* Check a notification is only received in the index within the array
|
||||||
of task notifications under test. */
|
* of task notifications under test. */
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToTest, 0, 0, &ulNotifiedValue, portMAX_DELAY );
|
||||||
configASSERT( xReturned == pdPASS );
|
configASSERT( xReturned == pdPASS );
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
configASSERT( ulNotifiedValue != 0 );
|
configASSERT( ulNotifiedValue != 0 );
|
||||||
|
|
||||||
/* Check a notification is not received in any index within the array
|
/* Check a notification is not received in any index within the array
|
||||||
of task notifications at and below the index being tested have a notification
|
* of task notifications at and below the index being tested have a notification
|
||||||
value, and that indexes above the index being tested to not have
|
* value, and that indexes above the index being tested to not have
|
||||||
notification values. */
|
* notification values. */
|
||||||
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
for( uxOtherIndexes = 0; uxOtherIndexes < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxOtherIndexes++ )
|
||||||
{
|
{
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
xReturned = xTaskNotifyWaitIndexed( uxOtherIndexes, 0, 0, &ulNotifiedValue, 0 );
|
||||||
|
|
@ -905,6 +880,7 @@ uint32_t ulNotifiedValue;
|
||||||
{
|
{
|
||||||
configASSERT( ulNotifiedValue == 0 );
|
configASSERT( ulNotifiedValue == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) xReturned; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
( void ) ulNotifiedValue;
|
( void ) ulNotifiedValue;
|
||||||
}
|
}
|
||||||
|
|
@ -932,9 +908,9 @@ uint32_t ulReceivedValue;
|
||||||
BaseType_t xReturned;
|
BaseType_t xReturned;
|
||||||
|
|
||||||
/* Set the value of each notification in the array of task notifications to
|
/* Set the value of each notification in the array of task notifications to
|
||||||
the value of its index position plus 1 so everything starts in a known
|
* the value of its index position plus 1 so everything starts in a known
|
||||||
state, then clear the notification state ready for the next test. Plus 1 is
|
* state, then clear the notification state ready for the next test. Plus 1 is
|
||||||
used because the index under test will use 0. */
|
* used because the index under test will use 0. */
|
||||||
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
||||||
{
|
{
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndex, uxIndex + 1, eSetValueWithOverwrite );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndex, uxIndex + 1, eSetValueWithOverwrite );
|
||||||
|
|
@ -942,30 +918,30 @@ BaseType_t xReturned;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Peform the test on each task notification within the array of task
|
/* Peform the test on each task notification within the array of task
|
||||||
notifications. */
|
* notifications. */
|
||||||
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
||||||
{
|
{
|
||||||
/* Set the notification value of the index being tested to 0 so the
|
/* Set the notification value of the index being tested to 0 so the
|
||||||
notification value increment/decrement functions can be tested. */
|
* notification value increment/decrement functions can be tested. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 0, eSetValueWithOverwrite );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, 0, eSetValueWithOverwrite );
|
||||||
xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
|
xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
|
||||||
|
|
||||||
/* Start the software timer then wait for it to notify this task. Block
|
/* Start the software timer then wait for it to notify this task. Block
|
||||||
on the notification index we expect to receive the notification on. The
|
* on the notification index we expect to receive the notification on. The
|
||||||
margin is to ensure the task blocks longer than the timer period. */
|
* margin is to ensure the task blocks longer than the timer period. */
|
||||||
xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
|
xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
|
||||||
ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdFALSE, xTimerPeriod + xMargin );
|
ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdFALSE, xTimerPeriod + xMargin );
|
||||||
|
|
||||||
/* The notification value was initially zero, and should have been
|
/* The notification value was initially zero, and should have been
|
||||||
incremented by the software timer, so now one. It will also have been
|
* incremented by the software timer, so now one. It will also have been
|
||||||
decremented again by the call to ulTaskNotifyTakeIndexed() so gone back
|
* decremented again by the call to ulTaskNotifyTakeIndexed() so gone back
|
||||||
to 0. */
|
* to 0. */
|
||||||
configASSERT( ulReceivedValue == 1UL );
|
configASSERT( ulReceivedValue == 1UL );
|
||||||
( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* No other notification indexes should have changed, and therefore should
|
/* No other notification indexes should have changed, and therefore should
|
||||||
still have their value set to their index plus 1 within the array of
|
* still have their value set to their index plus 1 within the array of
|
||||||
notifications. */
|
* notifications. */
|
||||||
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
||||||
{
|
{
|
||||||
if( uxIndex != uxIndexToNotify )
|
if( uxIndex != uxIndexToNotify )
|
||||||
|
|
@ -979,7 +955,7 @@ BaseType_t xReturned;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the notification value for the index just tested back to the
|
/* Reset the notification value for the index just tested back to the
|
||||||
index value plus 1 ready for the next iteration around this loop. */
|
* index value plus 1 ready for the next iteration around this loop. */
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, uxIndexToNotify + 1, eSetValueWithOverwrite );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, uxIndexToNotify + 1, eSetValueWithOverwrite );
|
||||||
xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
|
xTaskNotifyStateClearIndexed( xTaskToNotify, uxIndexToNotify );
|
||||||
|
|
||||||
|
|
@ -998,42 +974,41 @@ BaseType_t xReturned;
|
||||||
TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
|
TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
|
||||||
|
|
||||||
/* Set all notify values within the array of tasks notifications to zero
|
/* Set all notify values within the array of tasks notifications to zero
|
||||||
ready for the next test. */
|
* ready for the next test. */
|
||||||
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
||||||
{
|
{
|
||||||
ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToNotify, notifyUINT32_MAX );
|
ulTaskNotifyValueClearIndexed( xTaskToNotify, uxIndexToNotify, notifyUINT32_MAX );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the test for each notification within the array of task
|
/* Perform the test for each notification within the array of task
|
||||||
notifications. */
|
* notifications. */
|
||||||
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
||||||
{
|
{
|
||||||
/* Start the software timer then wait for it to notify this task. Block
|
/* Start the software timer then wait for it to notify this task. Block
|
||||||
on a notification index that we do not expect to receive the notification
|
* on a notification index that we do not expect to receive the notification
|
||||||
on. The margin is to ensure the task blocks longer than the timer period. */
|
* on. The margin is to ensure the task blocks longer than the timer period. */
|
||||||
xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
|
xTimerStart( xIncrementingIndexTimer, portMAX_DELAY );
|
||||||
xTimeBeforeBlocking = xTaskGetTickCount();
|
xTimeBeforeBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
|
|
||||||
if( uxIndexToNotify == ( configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 ) )
|
if( uxIndexToNotify == ( configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 ) )
|
||||||
{
|
{
|
||||||
/* configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 is to be notified, so
|
/* configTASK_NOTIFICATION_ARRAY_ENTRIES - 1 is to be notified, so
|
||||||
block on index 0. */
|
* block on index 0. */
|
||||||
uxIndex = 0;
|
uxIndex = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The next index to get notified will be uxIndexToNotify, so block
|
/* The next index to get notified will be uxIndexToNotify, so block
|
||||||
on uxIndexToNotify + 1 */
|
* on uxIndexToNotify + 1 */
|
||||||
uxIndex = uxIndexToNotify + 1;
|
uxIndex = uxIndexToNotify + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xTimerPeriod + xMargin );
|
xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xTimerPeriod + xMargin );
|
||||||
|
|
||||||
/* The notification will have been sent to task notification at index
|
/* The notification will have been sent to task notification at index
|
||||||
uxIndexToNotify in this task by the timer callback after xTimerPeriodTicks.
|
* uxIndexToNotify in this task by the timer callback after xTimerPeriodTicks.
|
||||||
The notification should not have woken this task, so xReturned should
|
* The notification should not have woken this task, so xReturned should
|
||||||
be false and at least xTimerPeriod + xMargin ticks should have passed. */
|
* be false and at least xTimerPeriod + xMargin ticks should have passed. */
|
||||||
configASSERT( xReturned == pdFALSE );
|
configASSERT( xReturned == pdFALSE );
|
||||||
xTimeNow = xTaskGetTickCount();
|
xTimeNow = xTaskGetTickCount();
|
||||||
xTimeDifference = xTimeNow - xTimeBeforeBlocking;
|
xTimeDifference = xTimeNow - xTimeBeforeBlocking;
|
||||||
|
|
@ -1043,7 +1018,7 @@ TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
|
||||||
( void ) xTimeDifference;
|
( void ) xTimeDifference;
|
||||||
|
|
||||||
/* Only the notification at index position uxIndexToNotify should be
|
/* Only the notification at index position uxIndexToNotify should be
|
||||||
set. Calling this function will clear it again. */
|
* set. Calling this function will clear it again. */
|
||||||
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
||||||
{
|
{
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
|
xReturned = xTaskNotifyWaitIndexed( uxIndex, 0, 0, &ulReceivedValue, xDontBlock );
|
||||||
|
|
@ -1051,7 +1026,7 @@ TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
|
||||||
if( uxIndex == uxIndexToNotify )
|
if( uxIndex == uxIndexToNotify )
|
||||||
{
|
{
|
||||||
/* Expect the notification state to be set and the notification
|
/* Expect the notification state to be set and the notification
|
||||||
value to have been incremented. */
|
* value to have been incremented. */
|
||||||
configASSERT( xReturned == pdTRUE );
|
configASSERT( xReturned == pdTRUE );
|
||||||
configASSERT( ulReceivedValue == 1 );
|
configASSERT( ulReceivedValue == 1 );
|
||||||
|
|
||||||
|
|
@ -1061,7 +1036,7 @@ TickType_t xTimeBeforeBlocking, xTimeNow, xTimeDifference;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Expect the notification state to be clear and the notification
|
/* Expect the notification state to be clear and the notification
|
||||||
value to remain at zer0. */
|
* value to remain at zer0. */
|
||||||
configASSERT( xReturned == pdFALSE );
|
configASSERT( xReturned == pdFALSE );
|
||||||
configASSERT( ulReceivedValue == 0 );
|
configASSERT( ulReceivedValue == 0 );
|
||||||
}
|
}
|
||||||
|
|
@ -1081,7 +1056,7 @@ BaseType_t xReturned;
|
||||||
const TickType_t xDontBlock = 0;
|
const TickType_t xDontBlock = 0;
|
||||||
|
|
||||||
/* Set the value of each notification within the array of task notifications
|
/* Set the value of each notification within the array of task notifications
|
||||||
to zero so the task can block on xTaskNotifyTake(). */
|
* to zero so the task can block on xTaskNotifyTake(). */
|
||||||
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
||||||
{
|
{
|
||||||
xTaskNotifyIndexed( xTaskToNotify, uxIndex, 0, eSetValueWithOverwrite );
|
xTaskNotifyIndexed( xTaskToNotify, uxIndex, 0, eSetValueWithOverwrite );
|
||||||
|
|
@ -1089,37 +1064,37 @@ const TickType_t xDontBlock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the test on each task notification within the array of task
|
/* Perform the test on each task notification within the array of task
|
||||||
notifications. */
|
* notifications. */
|
||||||
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
for( uxIndexToNotify = 0; uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndexToNotify++ )
|
||||||
{
|
{
|
||||||
/* Tell the interrupt to send the next notification. */
|
/* Tell the interrupt to send the next notification. */
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
/* Don't expect to find xSendNotificationFromISR set at this time as
|
/* Don't expect to find xSendNotificationFromISR set at this time as
|
||||||
the interrupt should have cleared it back to pdFALSE last time it
|
* the interrupt should have cleared it back to pdFALSE last time it
|
||||||
executed. */
|
* executed. */
|
||||||
configASSERT( xSendNotificationFromISR == pdFALSE );
|
configASSERT( xSendNotificationFromISR == pdFALSE );
|
||||||
xSendNotificationFromISR = pdTRUE;
|
xSendNotificationFromISR = pdTRUE;
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
/* Wait for a notification on the task notification at index
|
/* Wait for a notification on the task notification at index
|
||||||
uxIndexToNotify within the array of task notifications. */
|
* uxIndexToNotify within the array of task notifications. */
|
||||||
ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdTRUE, portMAX_DELAY );
|
ulReceivedValue = ulTaskNotifyTakeIndexed( uxIndexToNotify, pdTRUE, portMAX_DELAY );
|
||||||
|
|
||||||
/* Interrupt should have reset xSendNotificationFromISR after it sent
|
/* Interrupt should have reset xSendNotificationFromISR after it sent
|
||||||
the notification. */
|
* the notification. */
|
||||||
configASSERT( xSendNotificationFromISR == pdFALSE );
|
configASSERT( xSendNotificationFromISR == pdFALSE );
|
||||||
|
|
||||||
/* The notification value was initially zero, and should have been
|
/* The notification value was initially zero, and should have been
|
||||||
incremented by the interrupt, so now one. */
|
* incremented by the interrupt, so now one. */
|
||||||
configASSERT( ulReceivedValue == 1UL );
|
configASSERT( ulReceivedValue == 1UL );
|
||||||
( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
( void ) ulReceivedValue; /* Remove compiler warnings in case configASSERT() is not defined. */
|
||||||
|
|
||||||
/* No other notification indexes should have changed, and therefore should
|
/* No other notification indexes should have changed, and therefore should
|
||||||
still have their value set to 0. The value in array index uxIndexToNotify
|
* still have their value set to 0. The value in array index uxIndexToNotify
|
||||||
should also have been decremented back to zero by the call to
|
* should also have been decremented back to zero by the call to
|
||||||
ulTaskNotifyTakeIndexed(). */
|
* ulTaskNotifyTakeIndexed(). */
|
||||||
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
for( uxIndex = 0; uxIndex < configTASK_NOTIFICATION_ARRAY_ENTRIES; uxIndex++ )
|
||||||
{
|
{
|
||||||
xReturned = xTaskNotifyWaitIndexed( uxIndexToNotify, 0, 0, &ulReceivedValue, xDontBlock );
|
xReturned = xTaskNotifyWaitIndexed( uxIndexToNotify, 0, 0, &ulReceivedValue, xDontBlock );
|
||||||
|
|
@ -1146,27 +1121,30 @@ static UBaseType_t uxIndexToNotify = 0;
|
||||||
configASSERT( xTaskToNotify );
|
configASSERT( xTaskToNotify );
|
||||||
|
|
||||||
/* The task sets xSendNotificationFromISR to pdTRUE each time it wants this
|
/* The task sets xSendNotificationFromISR to pdTRUE each time it wants this
|
||||||
interrupt (this function runs in the RTOS tick hook) to send the next
|
* interrupt (this function runs in the RTOS tick hook) to send the next
|
||||||
notification. */
|
* notification. */
|
||||||
if( xSendNotificationFromISR == pdTRUE )
|
if( xSendNotificationFromISR == pdTRUE )
|
||||||
{
|
{
|
||||||
xSendNotificationFromISR = pdFALSE;
|
xSendNotificationFromISR = pdFALSE;
|
||||||
|
|
||||||
/* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
|
/* Test using both vTaskNotifyGiveFromISR(), xTaskNotifyFromISR()
|
||||||
and xTaskNotifyAndQueryFromISR(). The notification is set to the task
|
* and xTaskNotifyAndQueryFromISR(). The notification is set to the task
|
||||||
notification at index uxIndexToNotify within the array of task
|
* notification at index uxIndexToNotify within the array of task
|
||||||
notifications. */
|
* notifications. */
|
||||||
switch( xAPIToUse )
|
switch( xAPIToUse )
|
||||||
{
|
{
|
||||||
case 0: vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, NULL );
|
case 0:
|
||||||
|
vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, NULL );
|
||||||
xAPIToUse++;
|
xAPIToUse++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, NULL );
|
case 1:
|
||||||
|
xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, NULL );
|
||||||
xAPIToUse++;
|
xAPIToUse++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: ulPreviousValue = ulUnexpectedValue;
|
case 2:
|
||||||
|
ulPreviousValue = ulUnexpectedValue;
|
||||||
xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, &ulPreviousValue, NULL );
|
xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, 0, eIncrement, &ulPreviousValue, NULL );
|
||||||
configASSERT( ulPreviousValue == 0 );
|
configASSERT( ulPreviousValue == 0 );
|
||||||
xAPIToUse = 0;
|
xAPIToUse = 0;
|
||||||
|
|
@ -1177,8 +1155,9 @@ static UBaseType_t uxIndexToNotify = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the next index in the array of task notifications the next time
|
/* Use the next index in the array of task notifications the next time
|
||||||
around. */
|
* around. */
|
||||||
uxIndexToNotify++;
|
uxIndexToNotify++;
|
||||||
|
|
||||||
if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
|
if( uxIndexToNotify >= configTASK_NOTIFICATION_ARRAY_ENTRIES )
|
||||||
{
|
{
|
||||||
uxIndexToNotify = 0;
|
uxIndexToNotify = 0;
|
||||||
|
|
@ -1188,7 +1167,7 @@ static UBaseType_t uxIndexToNotify = 0;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* This is called to check the created tasks are still running and have not
|
/* This is called to check the created tasks are still running and have not
|
||||||
detected any errors. */
|
* detected any errors. */
|
||||||
BaseType_t xAreTaskNotificationArrayTasksStillRunning( void )
|
BaseType_t xAreTaskNotificationArrayTasksStillRunning( void )
|
||||||
{
|
{
|
||||||
static uint32_t ulLastFineCycleCount = 0, ulLastCourseCycleCount = 0, ulCallCount = 0;
|
static uint32_t ulLastFineCycleCount = 0, ulLastCourseCycleCount = 0, ulCallCount = 0;
|
||||||
|
|
@ -1196,9 +1175,9 @@ const uint32_t ulCallsBetweenCourseCycleCountChecks = 3UL;
|
||||||
static BaseType_t xErrorStatus = pdPASS;
|
static BaseType_t xErrorStatus = pdPASS;
|
||||||
|
|
||||||
/* Check the cycle count is still incrementing to ensure the task is still
|
/* Check the cycle count is still incrementing to ensure the task is still
|
||||||
actually running. The fine counter is incremented within individual test
|
* actually running. The fine counter is incremented within individual test
|
||||||
functions. The course counter is incremented one each time all the test
|
* functions. The course counter is incremented one each time all the test
|
||||||
functions have been executed to ensure all the tests are running. */
|
* functions have been executed to ensure all the tests are running. */
|
||||||
if( ulLastFineCycleCount == ulFineCycleCount )
|
if( ulLastFineCycleCount == ulFineCycleCount )
|
||||||
{
|
{
|
||||||
xErrorStatus = pdFAIL;
|
xErrorStatus = pdFAIL;
|
||||||
|
|
@ -1209,9 +1188,11 @@ static BaseType_t xErrorStatus = pdPASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulCallCount++;
|
ulCallCount++;
|
||||||
|
|
||||||
if( ulCallCount >= ulCallsBetweenCourseCycleCountChecks )
|
if( ulCallCount >= ulCallsBetweenCourseCycleCountChecks )
|
||||||
{
|
{
|
||||||
ulCallCount = 0;
|
ulCallCount = 0;
|
||||||
|
|
||||||
if( ulLastCourseCycleCount == ulCourseCycleCounter )
|
if( ulLastCourseCycleCount == ulCourseCycleCounter )
|
||||||
{
|
{
|
||||||
xErrorStatus = pdFAIL;
|
xErrorStatus = pdFAIL;
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,12 @@
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* The callback functions used by the timers. These each increment a counter
|
/* The callback functions used by the timers. These each increment a counter
|
||||||
to indicate which timer has expired. The auto-reload timers that are used by
|
* to indicate which timer has expired. The auto-reload timers that are used by
|
||||||
the test task (as opposed to being used from an ISR) all share the same
|
* the test task (as opposed to being used from an ISR) all share the same
|
||||||
prvAutoReloadTimerCallback() callback function, and use the ID of the
|
* prvAutoReloadTimerCallback() callback function, and use the ID of the
|
||||||
pxExpiredTimer parameter passed into that function to know which counter to
|
* pxExpiredTimer parameter passed into that function to know which counter to
|
||||||
increment. The other timers all have their own unique callback function and
|
* increment. The other timers all have their own unique callback function and
|
||||||
simply increment their counters without using the callback function parameter. */
|
* simply increment their counters without using the callback function parameter. */
|
||||||
static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer );
|
static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer );
|
||||||
static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer );
|
static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer );
|
||||||
static void prvTimerTestTask( void * pvParameters );
|
static void prvTimerTestTask( void * pvParameters );
|
||||||
|
|
@ -69,8 +69,8 @@ static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer );
|
||||||
static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer );
|
static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer );
|
||||||
|
|
||||||
/* The test functions used by the timer test task. These manipulate the auto
|
/* The test functions used by the timer test task. These manipulate the auto
|
||||||
reload and one-shot timers in various ways, then delay, then inspect the timers
|
* reload and one-shot timers in various ways, then delay, then inspect the timers
|
||||||
to ensure they have behaved as expected. */
|
* to ensure they have behaved as expected. */
|
||||||
static void prvTest1_CreateTimersWithoutSchedulerRunning( void );
|
static void prvTest1_CreateTimersWithoutSchedulerRunning( void );
|
||||||
static void prvTest2_CheckTaskAndTimersInitialState( void );
|
static void prvTest2_CheckTaskAndTimersInitialState( void );
|
||||||
static void prvTest3_CheckAutoReloadExpireRates( void );
|
static void prvTest3_CheckAutoReloadExpireRates( void );
|
||||||
|
|
@ -83,47 +83,47 @@ static void prvResetStartConditionsForNextIteration( void );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Flag that will be latched to pdFAIL should any unexpected behaviour be
|
/* Flag that will be latched to pdFAIL should any unexpected behaviour be
|
||||||
detected in any of the demo tests. */
|
* detected in any of the demo tests. */
|
||||||
static volatile BaseType_t xTestStatus = pdPASS;
|
static volatile BaseType_t xTestStatus = pdPASS;
|
||||||
|
|
||||||
/* Flag indicating whether the testing includes the backlog demo. The backlog
|
/* Flag indicating whether the testing includes the backlog demo. The backlog
|
||||||
demo can be disruptive to other demos because the timer backlog is created by
|
* demo can be disruptive to other demos because the timer backlog is created by
|
||||||
calling xTaskCatchUpTicks(). */
|
* calling xTaskCatchUpTicks(). */
|
||||||
static uint8_t ucIsBacklogDemoEnabled = ( uint8_t ) pdFALSE;
|
static uint8_t ucIsBacklogDemoEnabled = ( uint8_t ) pdFALSE;
|
||||||
|
|
||||||
/* Counter that is incremented on each cycle of a test. This is used to
|
/* Counter that is incremented on each cycle of a test. This is used to
|
||||||
detect a stalled task - a test that is no longer running. */
|
* detect a stalled task - a test that is no longer running. */
|
||||||
static volatile uint32_t ulLoopCounter = 0;
|
static volatile uint32_t ulLoopCounter = 0;
|
||||||
|
|
||||||
/* A set of auto-reload timers - each of which use the same callback function.
|
/* A set of auto-reload timers - each of which use the same callback function.
|
||||||
The callback function uses the timer ID to index into, and then increment, a
|
* The callback function uses the timer ID to index into, and then increment, a
|
||||||
counter in the ucAutoReloadTimerCounters[] array. The callback function stops
|
* counter in the ucAutoReloadTimerCounters[] array. The callback function stops
|
||||||
xAutoReloadTimers[0] during its callback if ucIsStopNeededInTimerZeroCallback is
|
* xAutoReloadTimers[0] during its callback if ucIsStopNeededInTimerZeroCallback is
|
||||||
pdTRUE. The auto-reload timers referenced from xAutoReloadTimers[] are used by
|
* pdTRUE. The auto-reload timers referenced from xAutoReloadTimers[] are used by
|
||||||
the prvTimerTestTask task. */
|
* the prvTimerTestTask task. */
|
||||||
static TimerHandle_t xAutoReloadTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };
|
static TimerHandle_t xAutoReloadTimers[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };
|
||||||
static uint8_t ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };
|
static uint8_t ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH + 1 ] = { 0 };
|
||||||
static uint8_t ucIsStopNeededInTimerZeroCallback = ( uint8_t ) pdFALSE;
|
static uint8_t ucIsStopNeededInTimerZeroCallback = ( uint8_t ) pdFALSE;
|
||||||
|
|
||||||
/* The one-shot timer is configured to use a callback function that increments
|
/* The one-shot timer is configured to use a callback function that increments
|
||||||
ucOneShotTimerCounter each time it gets called. */
|
* ucOneShotTimerCounter each time it gets called. */
|
||||||
static TimerHandle_t xOneShotTimer = NULL;
|
static TimerHandle_t xOneShotTimer = NULL;
|
||||||
static uint8_t ucOneShotTimerCounter = ( uint8_t ) 0;
|
static uint8_t ucOneShotTimerCounter = ( uint8_t ) 0;
|
||||||
|
|
||||||
/* The ISR reload timer is controlled from the tick hook to exercise the timer
|
/* The ISR reload timer is controlled from the tick hook to exercise the timer
|
||||||
API functions that can be used from an ISR. It is configured to increment
|
* API functions that can be used from an ISR. It is configured to increment
|
||||||
ucISRReloadTimerCounter each time its callback function is executed. */
|
* ucISRReloadTimerCounter each time its callback function is executed. */
|
||||||
static TimerHandle_t xISRAutoReloadTimer = NULL;
|
static TimerHandle_t xISRAutoReloadTimer = NULL;
|
||||||
static uint8_t ucISRAutoReloadTimerCounter = ( uint8_t ) 0;
|
static uint8_t ucISRAutoReloadTimerCounter = ( uint8_t ) 0;
|
||||||
|
|
||||||
/* The ISR one-shot timer is controlled from the tick hook to exercise the timer
|
/* The ISR one-shot timer is controlled from the tick hook to exercise the timer
|
||||||
API functions that can be used from an ISR. It is configured to increment
|
* API functions that can be used from an ISR. It is configured to increment
|
||||||
ucISRReloadTimerCounter each time its callback function is executed. */
|
* ucISRReloadTimerCounter each time its callback function is executed. */
|
||||||
static TimerHandle_t xISROneShotTimer = NULL;
|
static TimerHandle_t xISROneShotTimer = NULL;
|
||||||
static uint8_t ucISROneShotTimerCounter = ( uint8_t ) 0;
|
static uint8_t ucISROneShotTimerCounter = ( uint8_t ) 0;
|
||||||
|
|
||||||
/* The period of all the timers are a multiple of the base period. The base
|
/* The period of all the timers are a multiple of the base period. The base
|
||||||
period is configured by the parameter to vStartTimerDemoTask(). */
|
* period is configured by the parameter to vStartTimerDemoTask(). */
|
||||||
static TickType_t xBasePeriod = 0;
|
static TickType_t xBasePeriod = 0;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -131,22 +131,22 @@ static TickType_t xBasePeriod = 0;
|
||||||
void vStartTimerDemoTask( TickType_t xBasePeriodIn )
|
void vStartTimerDemoTask( TickType_t xBasePeriodIn )
|
||||||
{
|
{
|
||||||
/* Start with the timer and counter arrays clear - this is only necessary
|
/* Start with the timer and counter arrays clear - this is only necessary
|
||||||
where the compiler does not clear them automatically on start up. */
|
* where the compiler does not clear them automatically on start up. */
|
||||||
memset( ucAutoReloadTimerCounters, 0x00, sizeof( ucAutoReloadTimerCounters ) );
|
memset( ucAutoReloadTimerCounters, 0x00, sizeof( ucAutoReloadTimerCounters ) );
|
||||||
memset( xAutoReloadTimers, 0x00, sizeof( xAutoReloadTimers ) );
|
memset( xAutoReloadTimers, 0x00, sizeof( xAutoReloadTimers ) );
|
||||||
|
|
||||||
/* Store the period from which all the timer periods will be generated from
|
/* Store the period from which all the timer periods will be generated from
|
||||||
(multiples of). */
|
* (multiples of). */
|
||||||
xBasePeriod = xBasePeriodIn;
|
xBasePeriod = xBasePeriodIn;
|
||||||
|
|
||||||
/* Create a set of timers for use by this demo/test. */
|
/* Create a set of timers for use by this demo/test. */
|
||||||
prvTest1_CreateTimersWithoutSchedulerRunning();
|
prvTest1_CreateTimersWithoutSchedulerRunning();
|
||||||
|
|
||||||
/* Create the task that will control and monitor the timers. This is
|
/* Create the task that will control and monitor the timers. This is
|
||||||
created at a lower priority than the timer service task to ensure, as
|
* created at a lower priority than the timer service task to ensure, as
|
||||||
far as it is concerned, commands on timers are acted on immediately
|
* far as it is concerned, commands on timers are acted on immediately
|
||||||
(sending a command to the timer service task will unblock the timer service
|
* (sending a command to the timer service task will unblock the timer service
|
||||||
task, which will then preempt this task). */
|
* task, which will then preempt this task). */
|
||||||
if( xTestStatus != pdFAIL )
|
if( xTestStatus != pdFAIL )
|
||||||
{
|
{
|
||||||
xTaskCreate( prvTimerTestTask, "Tmr Tst", tmrTIMER_TEST_TASK_STACK_SIZE, NULL, configTIMER_TASK_PRIORITY - 1, NULL );
|
xTaskCreate( prvTimerTestTask, "Tmr Tst", tmrTIMER_TEST_TASK_STACK_SIZE, NULL, configTIMER_TASK_PRIORITY - 1, NULL );
|
||||||
|
|
@ -165,7 +165,7 @@ static void prvTimerTestTask( void *pvParameters )
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Create a one-shot timer for use later on in this test. For test purposes it
|
/* Create a one-shot timer for use later on in this test. For test purposes it
|
||||||
is created as an auto-reload timer then converted to a one-shot timer. */
|
* is created as an auto-reload timer then converted to a one-shot timer. */
|
||||||
xOneShotTimer = xTimerCreate( "Oneshot Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */
|
xOneShotTimer = xTimerCreate( "Oneshot Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */
|
||||||
tmrdemoONE_SHOT_TIMER_PERIOD, /* The period for the timer. */
|
tmrdemoONE_SHOT_TIMER_PERIOD, /* The period for the timer. */
|
||||||
pdFALSE, /* Autoreload is false, so created as a one-shot timer. */
|
pdFALSE, /* Autoreload is false, so created as a one-shot timer. */
|
||||||
|
|
@ -179,7 +179,7 @@ static void prvTimerTestTask( void *pvParameters )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Purely for test coverage purposes - change and query the reload mode to
|
/* Purely for test coverage purposes - change and query the reload mode to
|
||||||
auto-reload then back to one-shot. */
|
* auto-reload then back to one-shot. */
|
||||||
|
|
||||||
/* Change timer to auto-reload. */
|
/* Change timer to auto-reload. */
|
||||||
vTimerSetReloadMode( xOneShotTimer, pdTRUE );
|
vTimerSetReloadMode( xOneShotTimer, pdTRUE );
|
||||||
|
|
@ -194,7 +194,7 @@ static void prvTimerTestTask( void *pvParameters )
|
||||||
configASSERT( uxTimerGetReloadMode( xOneShotTimer ) == pdFALSE );
|
configASSERT( uxTimerGetReloadMode( xOneShotTimer ) == pdFALSE );
|
||||||
|
|
||||||
/* Ensure all the timers are in their expected initial state. This
|
/* Ensure all the timers are in their expected initial state. This
|
||||||
depends on the timer service task having a higher priority than this task. */
|
* depends on the timer service task having a higher priority than this task. */
|
||||||
prvTest2_CheckTaskAndTimersInitialState();
|
prvTest2_CheckTaskAndTimersInitialState();
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
|
|
@ -203,11 +203,11 @@ static void prvTimerTestTask( void *pvParameters )
|
||||||
prvTest3_CheckAutoReloadExpireRates();
|
prvTest3_CheckAutoReloadExpireRates();
|
||||||
|
|
||||||
/* Check the auto-reload timers can be stopped correctly, and correctly
|
/* Check the auto-reload timers can be stopped correctly, and correctly
|
||||||
report their state. */
|
* report their state. */
|
||||||
prvTest4_CheckAutoReloadTimersCanBeStopped();
|
prvTest4_CheckAutoReloadTimersCanBeStopped();
|
||||||
|
|
||||||
/* Check the one-shot timer only calls its callback once after it has been
|
/* Check the one-shot timer only calls its callback once after it has been
|
||||||
started, and that it reports its state correctly. */
|
* started, and that it reports its state correctly. */
|
||||||
prvTest5_CheckBasicOneShotTimerBehaviour();
|
prvTest5_CheckBasicOneShotTimerBehaviour();
|
||||||
|
|
||||||
/* Check timer reset behaviour. */
|
/* Check timer reset behaviour. */
|
||||||
|
|
@ -226,7 +226,7 @@ static void prvTimerTestTask( void *pvParameters )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* This is called to check that the created task is still running and has not
|
/* This is called to check that the created task is still running and has not
|
||||||
detected any errors. */
|
* detected any errors. */
|
||||||
BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency )
|
BaseType_t xAreTimerDemoTasksStillRunning( TickType_t xCycleFrequency )
|
||||||
{
|
{
|
||||||
static uint32_t ulLastLoopCounter = 0UL;
|
static uint32_t ulLastLoopCounter = 0UL;
|
||||||
|
|
@ -236,23 +236,24 @@ static TickType_t xIterationsWithoutCounterIncrement = ( TickType_t ) 0, xLastCy
|
||||||
if( xLastCycleFrequency != xCycleFrequency )
|
if( xLastCycleFrequency != xCycleFrequency )
|
||||||
{
|
{
|
||||||
/* The cycle frequency has probably become much faster due to an error
|
/* The cycle frequency has probably become much faster due to an error
|
||||||
elsewhere. Start counting Iterations again. */
|
* elsewhere. Start counting Iterations again. */
|
||||||
xIterationsWithoutCounterIncrement = ( TickType_t ) 0;
|
xIterationsWithoutCounterIncrement = ( TickType_t ) 0;
|
||||||
xLastCycleFrequency = xCycleFrequency;
|
xLastCycleFrequency = xCycleFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the maximum number of times that it is permissible for this
|
/* Calculate the maximum number of times that it is permissible for this
|
||||||
function to be called without ulLoopCounter being incremented. This is
|
* function to be called without ulLoopCounter being incremented. This is
|
||||||
necessary because the tests in this file block for extended periods, and the
|
* necessary because the tests in this file block for extended periods, and the
|
||||||
block period might be longer than the time between calls to this function. */
|
* block period might be longer than the time between calls to this function. */
|
||||||
xMaxBlockTimeUsedByTheseTests = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod;
|
xMaxBlockTimeUsedByTheseTests = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod;
|
||||||
xLoopCounterIncrementTimeMax = ( xMaxBlockTimeUsedByTheseTests / xCycleFrequency ) + 1;
|
xLoopCounterIncrementTimeMax = ( xMaxBlockTimeUsedByTheseTests / xCycleFrequency ) + 1;
|
||||||
|
|
||||||
/* If the demo task is still running then the loop counter is expected to
|
/* If the demo task is still running then the loop counter is expected to
|
||||||
have incremented every xLoopCounterIncrementTimeMax calls. */
|
* have incremented every xLoopCounterIncrementTimeMax calls. */
|
||||||
if( ulLastLoopCounter == ulLoopCounter )
|
if( ulLastLoopCounter == ulLoopCounter )
|
||||||
{
|
{
|
||||||
xIterationsWithoutCounterIncrement++;
|
xIterationsWithoutCounterIncrement++;
|
||||||
|
|
||||||
if( xIterationsWithoutCounterIncrement > xLoopCounterIncrementTimeMax )
|
if( xIterationsWithoutCounterIncrement > xLoopCounterIncrementTimeMax )
|
||||||
{
|
{
|
||||||
/* The tests appear to be no longer running (stalled). */
|
/* The tests appear to be no longer running (stalled). */
|
||||||
|
|
@ -262,14 +263,14 @@ static TickType_t xIterationsWithoutCounterIncrement = ( TickType_t ) 0, xLastCy
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* ulLoopCounter changed, so the count of times this function was called
|
/* ulLoopCounter changed, so the count of times this function was called
|
||||||
without a change can be reset to zero. */
|
* without a change can be reset to zero. */
|
||||||
xIterationsWithoutCounterIncrement = ( TickType_t ) 0;
|
xIterationsWithoutCounterIncrement = ( TickType_t ) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulLastLoopCounter = ulLoopCounter;
|
ulLastLoopCounter = ulLoopCounter;
|
||||||
|
|
||||||
/* Errors detected in the task itself will have latched xTestStatus
|
/* Errors detected in the task itself will have latched xTestStatus
|
||||||
to pdFAIL. */
|
* to pdFAIL. */
|
||||||
|
|
||||||
return xTestStatus;
|
return xTestStatus;
|
||||||
}
|
}
|
||||||
|
|
@ -282,9 +283,9 @@ TickType_t xTimer;
|
||||||
for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ )
|
for( xTimer = 0; xTimer < configTIMER_QUEUE_LENGTH; xTimer++ )
|
||||||
{
|
{
|
||||||
/* As the timer queue is not yet full, it should be possible to both
|
/* As the timer queue is not yet full, it should be possible to both
|
||||||
create and start a timer. These timers are being started before the
|
* create and start a timer. These timers are being started before the
|
||||||
scheduler has been started, so their block times should get set to zero
|
* scheduler has been started, so their block times should get set to zero
|
||||||
within the timer API itself. */
|
* within the timer API itself. */
|
||||||
xAutoReloadTimers[ xTimer ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */
|
xAutoReloadTimers[ xTimer ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */
|
||||||
( ( xTimer + ( TickType_t ) 1 ) * xBasePeriod ), /* The period for the timer. The plus 1 ensures a period of zero is not specified. */
|
( ( xTimer + ( TickType_t ) 1 ) * xBasePeriod ), /* The period for the timer. The plus 1 ensures a period of zero is not specified. */
|
||||||
pdTRUE, /* Auto-reload is set to true. */
|
pdTRUE, /* Auto-reload is set to true. */
|
||||||
|
|
@ -301,9 +302,9 @@ TickType_t xTimer;
|
||||||
configASSERT( strcmp( pcTimerGetName( xAutoReloadTimers[ xTimer ] ), "FR Timer" ) == 0 );
|
configASSERT( strcmp( pcTimerGetName( xAutoReloadTimers[ xTimer ] ), "FR Timer" ) == 0 );
|
||||||
|
|
||||||
/* The scheduler has not yet started, so the block period of
|
/* The scheduler has not yet started, so the block period of
|
||||||
portMAX_DELAY should just get set to zero in xTimerStart(). Also,
|
* portMAX_DELAY should just get set to zero in xTimerStart(). Also,
|
||||||
the timer queue is not yet full so xTimerStart() should return
|
* the timer queue is not yet full so xTimerStart() should return
|
||||||
pdPASS. */
|
* pdPASS. */
|
||||||
if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) != pdPASS )
|
if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -313,8 +314,8 @@ TickType_t xTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The timers queue should now be full, so it should be possible to create
|
/* The timers queue should now be full, so it should be possible to create
|
||||||
another timer, but not possible to start it (the timer queue will not get
|
* another timer, but not possible to start it (the timer queue will not get
|
||||||
drained until the scheduler has been started. */
|
* drained until the scheduler has been started. */
|
||||||
xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */
|
xAutoReloadTimers[ configTIMER_QUEUE_LENGTH ] = xTimerCreate( "FR Timer", /* Text name to facilitate debugging. The kernel does not use this itself. */
|
||||||
( configTIMER_QUEUE_LENGTH * xBasePeriod ), /* The period for the timer. */
|
( configTIMER_QUEUE_LENGTH * xBasePeriod ), /* The period for the timer. */
|
||||||
pdTRUE, /* Auto-reload is set to true. */
|
pdTRUE, /* Auto-reload is set to true. */
|
||||||
|
|
@ -331,14 +332,14 @@ TickType_t xTimer;
|
||||||
if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) == pdPASS )
|
if( xTimerStart( xAutoReloadTimers[ xTimer ], portMAX_DELAY ) == pdPASS )
|
||||||
{
|
{
|
||||||
/* This time it would not be expected that the timer could be
|
/* This time it would not be expected that the timer could be
|
||||||
started at this point. */
|
* started at this point. */
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
configASSERT( xTestStatus );
|
configASSERT( xTestStatus );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the timers that are used from the tick interrupt to test the timer
|
/* Create the timers that are used from the tick interrupt to test the timer
|
||||||
API functions that can be called from an ISR. */
|
* API functions that can be called from an ISR. */
|
||||||
xISRAutoReloadTimer = xTimerCreate( "ISR AR", /* The text name given to the timer. */
|
xISRAutoReloadTimer = xTimerCreate( "ISR AR", /* The text name given to the timer. */
|
||||||
0xffff, /* The timer is not given a period yet - this will be done from the tick hook, but a period of 0 is invalid. */
|
0xffff, /* The timer is not given a period yet - this will be done from the tick hook, but a period of 0 is invalid. */
|
||||||
pdTRUE, /* This is an auto-reload timer. */
|
pdTRUE, /* This is an auto-reload timer. */
|
||||||
|
|
@ -364,12 +365,12 @@ static void prvTest2_CheckTaskAndTimersInitialState( void )
|
||||||
uint8_t ucTimer;
|
uint8_t ucTimer;
|
||||||
|
|
||||||
/* Ensure all the timers are in their expected initial state. This depends
|
/* Ensure all the timers are in their expected initial state. This depends
|
||||||
on the timer service task having a higher priority than this task.
|
* on the timer service task having a higher priority than this task.
|
||||||
|
*
|
||||||
auto-reload timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now be active,
|
* auto-reload timers 0 to ( configTIMER_QUEUE_LENGTH - 1 ) should now be active,
|
||||||
and auto-reload timer configTIMER_QUEUE_LENGTH should not yet be active (it
|
* and auto-reload timer configTIMER_QUEUE_LENGTH should not yet be active (it
|
||||||
could not be started prior to the scheduler being started when it was
|
* could not be started prior to the scheduler being started when it was
|
||||||
created). */
|
* created). */
|
||||||
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
||||||
{
|
{
|
||||||
if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE )
|
if( xTimerIsTimerActive( xAutoReloadTimers[ ucTimer ] ) == pdFALSE )
|
||||||
|
|
@ -394,22 +395,22 @@ TickType_t xBlockPeriod, xTimerPeriod, xExpectedNumber;
|
||||||
UBaseType_t uxOriginalPriority;
|
UBaseType_t uxOriginalPriority;
|
||||||
|
|
||||||
/* Check the auto-reload timers expire at the expected rates. Do this at a
|
/* Check the auto-reload timers expire at the expected rates. Do this at a
|
||||||
high priority for maximum accuracy. This is ok as most of the time is spent
|
* high priority for maximum accuracy. This is ok as most of the time is spent
|
||||||
in the Blocked state. */
|
* in the Blocked state. */
|
||||||
uxOriginalPriority = uxTaskPriorityGet( NULL );
|
uxOriginalPriority = uxTaskPriorityGet( NULL );
|
||||||
vTaskPrioritySet( NULL, ( configMAX_PRIORITIES - 1 ) );
|
vTaskPrioritySet( NULL, ( configMAX_PRIORITIES - 1 ) );
|
||||||
|
|
||||||
/* Delaying for configTIMER_QUEUE_LENGTH * xBasePeriod ticks should allow
|
/* Delaying for configTIMER_QUEUE_LENGTH * xBasePeriod ticks should allow
|
||||||
all the auto-reload timers to expire at least once. */
|
* all the auto-reload timers to expire at least once. */
|
||||||
xBlockPeriod = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod;
|
xBlockPeriod = ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod;
|
||||||
vTaskDelay( xBlockPeriod );
|
vTaskDelay( xBlockPeriod );
|
||||||
|
|
||||||
/* Check that all the auto-reload timers have called their callback
|
/* Check that all the auto-reload timers have called their callback
|
||||||
function the expected number of times. */
|
* function the expected number of times. */
|
||||||
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
||||||
{
|
{
|
||||||
/* The expected number of expires is equal to the block period divided
|
/* The expected number of expires is equal to the block period divided
|
||||||
by the timer period. */
|
* by the timer period. */
|
||||||
xTimerPeriod = ( ( ( TickType_t ) ucTimer + ( TickType_t ) 1 ) * xBasePeriod );
|
xTimerPeriod = ( ( ( TickType_t ) ucTimer + ( TickType_t ) 1 ) * xBasePeriod );
|
||||||
xExpectedNumber = xBlockPeriod / xTimerPeriod;
|
xExpectedNumber = xBlockPeriod / xTimerPeriod;
|
||||||
|
|
||||||
|
|
@ -431,7 +432,7 @@ UBaseType_t uxOriginalPriority;
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so the
|
/* No errors have been reported so increment the loop counter so the
|
||||||
check task knows this task is still running. */
|
* check task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -442,7 +443,7 @@ static void prvTest4_CheckAutoReloadTimersCanBeStopped( void )
|
||||||
uint8_t ucTimer;
|
uint8_t ucTimer;
|
||||||
|
|
||||||
/* Check the auto-reload timers can be stopped correctly, and correctly
|
/* Check the auto-reload timers can be stopped correctly, and correctly
|
||||||
report their state. */
|
* report their state. */
|
||||||
|
|
||||||
/* Stop all the active timers. */
|
/* Stop all the active timers. */
|
||||||
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
||||||
|
|
@ -455,8 +456,8 @@ uint8_t ucTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now stop the timer. This will appear to happen immediately to
|
/* Now stop the timer. This will appear to happen immediately to
|
||||||
this task because this task is running at a priority below the
|
* this task because this task is running at a priority below the
|
||||||
timer service task. */
|
* timer service task. */
|
||||||
xTimerStop( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK );
|
xTimerStop( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK );
|
||||||
|
|
||||||
/* The timer should now be inactive. */
|
/* The timer should now be inactive. */
|
||||||
|
|
@ -470,9 +471,9 @@ uint8_t ucTimer;
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
/* The timer in array position configTIMER_QUEUE_LENGTH should not
|
/* The timer in array position configTIMER_QUEUE_LENGTH should not
|
||||||
be active. The critical section is used to ensure the timer does
|
* be active. The critical section is used to ensure the timer does
|
||||||
not call its callback between the next line running and the array
|
* not call its callback between the next line running and the array
|
||||||
being cleared back to zero, as that would mask an error condition. */
|
* being cleared back to zero, as that would mask an error condition. */
|
||||||
if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( uint8_t ) 0 )
|
if( ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH ] != ( uint8_t ) 0 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -485,8 +486,9 @@ uint8_t ucTimer;
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
/* The timers are now all inactive, so this time, after delaying, none
|
/* The timers are now all inactive, so this time, after delaying, none
|
||||||
of the callback counters should have incremented. */
|
* of the callback counters should have incremented. */
|
||||||
vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );
|
vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );
|
||||||
|
|
||||||
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
for( ucTimer = 0; ucTimer < ( uint8_t ) configTIMER_QUEUE_LENGTH; ucTimer++ )
|
||||||
{
|
{
|
||||||
if( ucAutoReloadTimerCounters[ ucTimer ] != ( uint8_t ) 0 )
|
if( ucAutoReloadTimerCounters[ ucTimer ] != ( uint8_t ) 0 )
|
||||||
|
|
@ -499,7 +501,7 @@ uint8_t ucTimer;
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so
|
/* No errors have been reported so increment the loop counter so
|
||||||
the check task knows this task is still running. */
|
* the check task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -508,7 +510,7 @@ uint8_t ucTimer;
|
||||||
static void prvTest5_CheckBasicOneShotTimerBehaviour( void )
|
static void prvTest5_CheckBasicOneShotTimerBehaviour( void )
|
||||||
{
|
{
|
||||||
/* Check the one-shot timer only calls its callback once after it has been
|
/* Check the one-shot timer only calls its callback once after it has been
|
||||||
started, and that it reports its state correctly. */
|
* started, and that it reports its state correctly. */
|
||||||
|
|
||||||
/* The one-shot timer should not be active yet. */
|
/* The one-shot timer should not be active yet. */
|
||||||
if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )
|
if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )
|
||||||
|
|
@ -525,6 +527,7 @@ static void prvTest5_CheckBasicOneShotTimerBehaviour( void )
|
||||||
|
|
||||||
/* Start the one-shot timer and check that it reports its state correctly. */
|
/* Start the one-shot timer and check that it reports its state correctly. */
|
||||||
xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );
|
xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );
|
||||||
|
|
||||||
if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )
|
if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -532,8 +535,8 @@ static void prvTest5_CheckBasicOneShotTimerBehaviour( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delay for three times as long as the one-shot timer period, then check
|
/* Delay for three times as long as the one-shot timer period, then check
|
||||||
to ensure it has only called its callback once, and is now not in the
|
* to ensure it has only called its callback once, and is now not in the
|
||||||
active state. */
|
* active state. */
|
||||||
vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD * ( TickType_t ) 3 );
|
vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD * ( TickType_t ) 3 );
|
||||||
|
|
||||||
if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )
|
if( xTimerIsTimerActive( xOneShotTimer ) != pdFALSE )
|
||||||
|
|
@ -556,7 +559,7 @@ static void prvTest5_CheckBasicOneShotTimerBehaviour( void )
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so the
|
/* No errors have been reported so increment the loop counter so the
|
||||||
check task knows this task is still running. */
|
* check task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -570,6 +573,7 @@ uint8_t ucTimer;
|
||||||
|
|
||||||
/* Restart the one-shot timer and check it reports its status correctly. */
|
/* Restart the one-shot timer and check it reports its status correctly. */
|
||||||
xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );
|
xTimerStart( xOneShotTimer, tmrdemoDONT_BLOCK );
|
||||||
|
|
||||||
if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )
|
if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -577,8 +581,9 @@ uint8_t ucTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restart one of the auto-reload timers and check that it reports its
|
/* Restart one of the auto-reload timers and check that it reports its
|
||||||
status correctly. */
|
* status correctly. */
|
||||||
xTimerStart( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );
|
xTimerStart( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ], tmrdemoDONT_BLOCK );
|
||||||
|
|
||||||
if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )
|
if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -588,12 +593,12 @@ uint8_t ucTimer;
|
||||||
for( ucTimer = 0; ucTimer < tmrdemoNUM_TIMER_RESETS; ucTimer++ )
|
for( ucTimer = 0; ucTimer < tmrdemoNUM_TIMER_RESETS; ucTimer++ )
|
||||||
{
|
{
|
||||||
/* Delay for half as long as the one-shot timer period, then reset it.
|
/* Delay for half as long as the one-shot timer period, then reset it.
|
||||||
It should never expire while this is done, so its callback count should
|
* It should never expire while this is done, so its callback count should
|
||||||
never increment. */
|
* never increment. */
|
||||||
vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD / 2 );
|
vTaskDelay( tmrdemoONE_SHOT_TIMER_PERIOD / 2 );
|
||||||
|
|
||||||
/* Check both running timers are still active, but have not called their
|
/* Check both running timers are still active, but have not called their
|
||||||
callback functions. */
|
* callback functions. */
|
||||||
if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )
|
if( xTimerIsTimerActive( xOneShotTimer ) == pdFALSE )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -625,7 +630,7 @@ uint8_t ucTimer;
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so
|
/* No errors have been reported so increment the loop counter so
|
||||||
the check task knows this task is still running. */
|
* the check task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -634,7 +639,7 @@ uint8_t ucTimer;
|
||||||
vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );
|
vTaskDelay( ( ( TickType_t ) configTIMER_QUEUE_LENGTH ) * xBasePeriod );
|
||||||
|
|
||||||
/* The timers were not reset during the above delay period so should now
|
/* The timers were not reset during the above delay period so should now
|
||||||
both have called their callback functions. */
|
* both have called their callback functions. */
|
||||||
if( ucOneShotTimerCounter != ( uint8_t ) 1 )
|
if( ucOneShotTimerCounter != ( uint8_t ) 1 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -648,7 +653,7 @@ uint8_t ucTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The one-shot timer should no longer be active, while the auto-reload
|
/* The one-shot timer should no longer be active, while the auto-reload
|
||||||
timer should still be active. */
|
* timer should still be active. */
|
||||||
if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )
|
if( xTimerIsTimerActive( xAutoReloadTimers[ configTIMER_QUEUE_LENGTH - 1 ] ) == pdFALSE )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -671,14 +676,14 @@ uint8_t ucTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the timer callback counts, ready for another iteration of these
|
/* Clear the timer callback counts, ready for another iteration of these
|
||||||
tests. */
|
* tests. */
|
||||||
ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( uint8_t ) 0;
|
ucAutoReloadTimerCounters[ configTIMER_QUEUE_LENGTH - 1 ] = ( uint8_t ) 0;
|
||||||
ucOneShotTimerCounter = ( uint8_t ) 0;
|
ucOneShotTimerCounter = ( uint8_t ) 0;
|
||||||
|
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so the check
|
/* No errors have been reported so increment the loop counter so the check
|
||||||
task knows this task is still running. */
|
* task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -687,7 +692,7 @@ uint8_t ucTimer;
|
||||||
static void prvTest7_CheckBacklogBehaviour( void )
|
static void prvTest7_CheckBacklogBehaviour( void )
|
||||||
{
|
{
|
||||||
/* Use the first auto-reload timer to test stopping a timer from a
|
/* Use the first auto-reload timer to test stopping a timer from a
|
||||||
backlogged callback. */
|
* backlogged callback. */
|
||||||
|
|
||||||
/* The timer has not been started yet! */
|
/* The timer has not been started yet! */
|
||||||
if( xTimerIsTimerActive( xAutoReloadTimers[ 0 ] ) != pdFALSE )
|
if( xTimerIsTimerActive( xAutoReloadTimers[ 0 ] ) != pdFALSE )
|
||||||
|
|
@ -700,10 +705,10 @@ static void prvTest7_CheckBacklogBehaviour( void )
|
||||||
ucIsStopNeededInTimerZeroCallback = ( uint8_t ) pdTRUE;
|
ucIsStopNeededInTimerZeroCallback = ( uint8_t ) pdTRUE;
|
||||||
|
|
||||||
/* Now start the timer. This will appear to happen immediately to
|
/* Now start the timer. This will appear to happen immediately to
|
||||||
this task because this task is running at a priority below the timer
|
* this task because this task is running at a priority below the timer
|
||||||
service task. Use a timer period of one tick so the call to
|
* service task. Use a timer period of one tick so the call to
|
||||||
xTaskCatchUpTicks() below has minimal impact on other tests that might
|
* xTaskCatchUpTicks() below has minimal impact on other tests that might
|
||||||
be running. */
|
* be running. */
|
||||||
#define tmrdemoBACKLOG_TIMER_PERIOD ( ( TickType_t ) 1 )
|
#define tmrdemoBACKLOG_TIMER_PERIOD ( ( TickType_t ) 1 )
|
||||||
xTimerChangePeriod( xAutoReloadTimers[ 0 ], tmrdemoBACKLOG_TIMER_PERIOD, tmrdemoDONT_BLOCK );
|
xTimerChangePeriod( xAutoReloadTimers[ 0 ], tmrdemoBACKLOG_TIMER_PERIOD, tmrdemoDONT_BLOCK );
|
||||||
|
|
||||||
|
|
@ -715,8 +720,8 @@ static void prvTest7_CheckBacklogBehaviour( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Arrange for the callback to execute late enough that it will execute
|
/* Arrange for the callback to execute late enough that it will execute
|
||||||
twice, back-to-back. The timer must handle the stop request properly
|
* twice, back-to-back. The timer must handle the stop request properly
|
||||||
in spite of the backlog of callbacks. */
|
* in spite of the backlog of callbacks. */
|
||||||
#define tmrdemoEXPECTED_BACKLOG_EXPIRES ( ( TickType_t ) 2 )
|
#define tmrdemoEXPECTED_BACKLOG_EXPIRES ( ( TickType_t ) 2 )
|
||||||
xTaskCatchUpTicks( tmrdemoBACKLOG_TIMER_PERIOD * tmrdemoEXPECTED_BACKLOG_EXPIRES );
|
xTaskCatchUpTicks( tmrdemoBACKLOG_TIMER_PERIOD * tmrdemoEXPECTED_BACKLOG_EXPIRES );
|
||||||
|
|
||||||
|
|
@ -737,7 +742,7 @@ static void prvTest7_CheckBacklogBehaviour( void )
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so the check
|
/* No errors have been reported so increment the loop counter so the check
|
||||||
task knows this task is still running. */
|
* task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -760,8 +765,8 @@ uint8_t ucTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now start the timer. This will appear to happen immediately to
|
/* Now start the timer. This will appear to happen immediately to
|
||||||
this task because this task is running at a priority below the timer
|
* this task because this task is running at a priority below the timer
|
||||||
service task. */
|
* service task. */
|
||||||
xTimerStart( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK );
|
xTimerStart( xAutoReloadTimers[ ucTimer ], tmrdemoDONT_BLOCK );
|
||||||
|
|
||||||
/* The timer should now be active. */
|
/* The timer should now be active. */
|
||||||
|
|
@ -775,7 +780,7 @@ uint8_t ucTimer;
|
||||||
if( xTestStatus == pdPASS )
|
if( xTestStatus == pdPASS )
|
||||||
{
|
{
|
||||||
/* No errors have been reported so increment the loop counter so the
|
/* No errors have been reported so increment the loop counter so the
|
||||||
check task knows this task is still running. */
|
* check task knows this task is still running. */
|
||||||
ulLoopCounter++;
|
ulLoopCounter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -786,25 +791,26 @@ void vTimerPeriodicISRTests( void )
|
||||||
static TickType_t uxTick = ( TickType_t ) -1;
|
static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
|
|
||||||
#if ( configTIMER_TASK_PRIORITY != ( configMAX_PRIORITIES - 1 ) )
|
#if ( configTIMER_TASK_PRIORITY != ( configMAX_PRIORITIES - 1 ) )
|
||||||
/* The timer service task is not the highest priority task, so it cannot
|
|
||||||
be assumed that timings will be exact. Timers should never call their
|
|
||||||
callback before their expiry time, but a margin is permissible for calling
|
|
||||||
their callback after their expiry time. If exact timing is required then
|
|
||||||
configTIMER_TASK_PRIORITY must be set to ensure the timer service task
|
|
||||||
is the highest priority task in the system.
|
|
||||||
|
|
||||||
This function is called from the tick hook. The tick hook is called
|
/* The timer service task is not the highest priority task, so it cannot
|
||||||
even when the scheduler is suspended. Therefore it is possible that the
|
* be assumed that timings will be exact. Timers should never call their
|
||||||
uxTick count maintained in this function is temporarily ahead of the tick
|
* callback before their expiry time, but a margin is permissible for calling
|
||||||
count maintained by the kernel. When this is the case a message posted from
|
* their callback after their expiry time. If exact timing is required then
|
||||||
this function will assume a time stamp in advance of the real time stamp,
|
* configTIMER_TASK_PRIORITY must be set to ensure the timer service task
|
||||||
which can result in a timer being processed before this function expects it
|
* is the highest priority task in the system.
|
||||||
to. For example, if the kernel's tick count was 100, and uxTick was 102,
|
*
|
||||||
then this function will not expect the timer to have expired until the
|
* This function is called from the tick hook. The tick hook is called
|
||||||
kernel's tick count is (102 + xBasePeriod), whereas in reality the timer
|
* even when the scheduler is suspended. Therefore it is possible that the
|
||||||
will expire when the kernel's tick count is (100 + xBasePeriod). For this
|
* uxTick count maintained in this function is temporarily ahead of the tick
|
||||||
reason xMargin is used as an allowable margin for premature timer expires
|
* count maintained by the kernel. When this is the case a message posted from
|
||||||
as well as late timer expires. */
|
* this function will assume a time stamp in advance of the real time stamp,
|
||||||
|
* which can result in a timer being processed before this function expects it
|
||||||
|
* to. For example, if the kernel's tick count was 100, and uxTick was 102,
|
||||||
|
* then this function will not expect the timer to have expired until the
|
||||||
|
* kernel's tick count is (102 + xBasePeriod), whereas in reality the timer
|
||||||
|
* will expire when the kernel's tick count is (100 + xBasePeriod). For this
|
||||||
|
* reason xMargin is used as an allowable margin for premature timer expires
|
||||||
|
* as well as late timer expires. */
|
||||||
#ifdef _WINDOWS_
|
#ifdef _WINDOWS_
|
||||||
/* Windows is not real real time. */
|
/* Windows is not real real time. */
|
||||||
const TickType_t xMargin = 20;
|
const TickType_t xMargin = 20;
|
||||||
|
|
@ -818,7 +824,7 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
#else
|
#else
|
||||||
const TickType_t xMargin = 4;
|
const TickType_t xMargin = 4;
|
||||||
#endif /* _WINDOWS_ */
|
#endif /* _WINDOWS_ */
|
||||||
#endif
|
#endif /* if ( configTIMER_TASK_PRIORITY != ( configMAX_PRIORITIES - 1 ) ) */
|
||||||
|
|
||||||
|
|
||||||
uxTick++;
|
uxTick++;
|
||||||
|
|
@ -826,13 +832,13 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
if( uxTick == 0 )
|
if( uxTick == 0 )
|
||||||
{
|
{
|
||||||
/* The timers will have been created, but not started. Start them now
|
/* The timers will have been created, but not started. Start them now
|
||||||
by setting their period. */
|
* by setting their period. */
|
||||||
ucISRAutoReloadTimerCounter = 0;
|
ucISRAutoReloadTimerCounter = 0;
|
||||||
ucISROneShotTimerCounter = 0;
|
ucISROneShotTimerCounter = 0;
|
||||||
|
|
||||||
/* It is possible that the timer task has not yet made room in the
|
/* It is possible that the timer task has not yet made room in the
|
||||||
timer queue. If the timers cannot be started then reset uxTick so
|
* timer queue. If the timers cannot be started then reset uxTick so
|
||||||
another attempt is made later. */
|
* another attempt is made later. */
|
||||||
uxTick = ( TickType_t ) -1;
|
uxTick = ( TickType_t ) -1;
|
||||||
|
|
||||||
/* Try starting first timer. */
|
/* Try starting first timer. */
|
||||||
|
|
@ -842,13 +848,13 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
if( xTimerChangePeriodFromISR( xISROneShotTimer, xBasePeriod, NULL ) == pdPASS )
|
if( xTimerChangePeriodFromISR( xISROneShotTimer, xBasePeriod, NULL ) == pdPASS )
|
||||||
{
|
{
|
||||||
/* Both timers were started, so set the uxTick back to its
|
/* Both timers were started, so set the uxTick back to its
|
||||||
proper value. */
|
* proper value. */
|
||||||
uxTick = 0;
|
uxTick = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Second timer could not be started, so stop the first one
|
/* Second timer could not be started, so stop the first one
|
||||||
again. */
|
* again. */
|
||||||
xTimerStopFromISR( xISRAutoReloadTimer, NULL );
|
xTimerStopFromISR( xISRAutoReloadTimer, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -865,7 +871,7 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( xBasePeriod + xMargin ) )
|
else if( uxTick == ( xBasePeriod + xMargin ) )
|
||||||
{
|
{
|
||||||
/* Both timers should now have expired once. The auto-reload timer will
|
/* Both timers should now have expired once. The auto-reload timer will
|
||||||
still be active, but the one-shot timer should now have stopped. */
|
* still be active, but the one-shot timer should now have stopped. */
|
||||||
if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) )
|
if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -875,8 +881,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 2 * xBasePeriod ) - xMargin ) )
|
else if( uxTick == ( ( 2 * xBasePeriod ) - xMargin ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer will still be active, but the one-shot timer
|
/* The auto-reload timer will still be active, but the one-shot timer
|
||||||
should now have stopped - however, at this time neither of the timers
|
* should now have stopped - however, at this time neither of the timers
|
||||||
should have expired again since the last test. */
|
* should have expired again since the last test. */
|
||||||
if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) )
|
if( ( ucISRAutoReloadTimerCounter != 1 ) || ( ucISROneShotTimerCounter != 1 ) )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -886,8 +892,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 2 * xBasePeriod ) + xMargin ) )
|
else if( uxTick == ( ( 2 * xBasePeriod ) + xMargin ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer will still be active, but the one-shot timer
|
/* The auto-reload timer will still be active, but the one-shot timer
|
||||||
should now have stopped. At this time the auto-reload timer should have
|
* should now have stopped. At this time the auto-reload timer should have
|
||||||
expired again, but the one-shot timer count should not have changed. */
|
* expired again, but the one-shot timer count should not have changed. */
|
||||||
if( ucISRAutoReloadTimerCounter != 2 )
|
if( ucISRAutoReloadTimerCounter != 2 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -903,8 +909,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 2 * xBasePeriod ) + ( xBasePeriod >> ( TickType_t ) 2U ) ) )
|
else if( uxTick == ( ( 2 * xBasePeriod ) + ( xBasePeriod >> ( TickType_t ) 2U ) ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer will still be active, but the one-shot timer
|
/* The auto-reload timer will still be active, but the one-shot timer
|
||||||
should now have stopped. Again though, at this time, neither timer call
|
* should now have stopped. Again though, at this time, neither timer call
|
||||||
back should have been called since the last test. */
|
* back should have been called since the last test. */
|
||||||
if( ucISRAutoReloadTimerCounter != 2 )
|
if( ucISRAutoReloadTimerCounter != 2 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -925,8 +931,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 3 * xBasePeriod ) + xMargin ) )
|
else if( uxTick == ( ( 3 * xBasePeriod ) + xMargin ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer and one-shot timer will be active. At
|
/* The auto-reload timer and one-shot timer will be active. At
|
||||||
this time the auto-reload timer should have expired again, but the one
|
* this time the auto-reload timer should have expired again, but the one
|
||||||
shot timer count should not have changed yet. */
|
* shot timer count should not have changed yet. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -940,14 +946,14 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now stop the auto-reload timer. The one-shot timer was started
|
/* Now stop the auto-reload timer. The one-shot timer was started
|
||||||
a few ticks ago. */
|
* a few ticks ago. */
|
||||||
xTimerStopFromISR( xISRAutoReloadTimer, NULL );
|
xTimerStopFromISR( xISRAutoReloadTimer, NULL );
|
||||||
}
|
}
|
||||||
else if( uxTick == ( 4 * ( xBasePeriod - xMargin ) ) )
|
else if( uxTick == ( 4 * ( xBasePeriod - xMargin ) ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer is now stopped, and the one-shot timer is
|
/* The auto-reload timer is now stopped, and the one-shot timer is
|
||||||
active, but at this time neither timer should have expired since the
|
* active, but at this time neither timer should have expired since the
|
||||||
last test. */
|
* last test. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -963,8 +969,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 4 * xBasePeriod ) + xMargin ) )
|
else if( uxTick == ( ( 4 * xBasePeriod ) + xMargin ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer is now stopped, and the one-shot timer is
|
/* The auto-reload timer is now stopped, and the one-shot timer is
|
||||||
active. The one-shot timer should have expired again, but the auto
|
* active. The one-shot timer should have expired again, but the auto
|
||||||
reload timer should not have executed its callback. */
|
* reload timer should not have executed its callback. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -980,8 +986,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( 8 * xBasePeriod ) )
|
else if( uxTick == ( 8 * xBasePeriod ) )
|
||||||
{
|
{
|
||||||
/* The auto-reload timer is now stopped, and the one-shot timer has
|
/* The auto-reload timer is now stopped, and the one-shot timer has
|
||||||
already expired and then stopped itself. Both callback counters should
|
* already expired and then stopped itself. Both callback counters should
|
||||||
not have incremented since the last test. */
|
* not have incremented since the last test. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -1000,8 +1006,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 9 * xBasePeriod ) - xMargin ) )
|
else if( uxTick == ( ( 9 * xBasePeriod ) - xMargin ) )
|
||||||
{
|
{
|
||||||
/* Only the one-shot timer should be running, but it should not have
|
/* Only the one-shot timer should be running, but it should not have
|
||||||
expired since the last test. Check the callback counters have not
|
* expired since the last test. Check the callback counters have not
|
||||||
incremented, then reset the one-shot timer again. */
|
* incremented, then reset the one-shot timer again. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -1019,8 +1025,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 10 * xBasePeriod ) - ( 2 * xMargin ) ) )
|
else if( uxTick == ( ( 10 * xBasePeriod ) - ( 2 * xMargin ) ) )
|
||||||
{
|
{
|
||||||
/* Only the one-shot timer should be running, but it should not have
|
/* Only the one-shot timer should be running, but it should not have
|
||||||
expired since the last test. Check the callback counters have not
|
* expired since the last test. Check the callback counters have not
|
||||||
incremented, then reset the one-shot timer again. */
|
* incremented, then reset the one-shot timer again. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -1038,8 +1044,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 11 * xBasePeriod ) - ( 3 * xMargin ) ) )
|
else if( uxTick == ( ( 11 * xBasePeriod ) - ( 3 * xMargin ) ) )
|
||||||
{
|
{
|
||||||
/* Only the one-shot timer should be running, but it should not have
|
/* Only the one-shot timer should be running, but it should not have
|
||||||
expired since the last test. Check the callback counters have not
|
* expired since the last test. Check the callback counters have not
|
||||||
incremented, then reset the one-shot timer once again. */
|
* incremented, then reset the one-shot timer once again. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -1057,10 +1063,10 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( ( 12 * xBasePeriod ) - ( 2 * xMargin ) ) )
|
else if( uxTick == ( ( 12 * xBasePeriod ) - ( 2 * xMargin ) ) )
|
||||||
{
|
{
|
||||||
/* Only the one-shot timer should have been running and this time it
|
/* Only the one-shot timer should have been running and this time it
|
||||||
should have expired. Check its callback count has been incremented.
|
* should have expired. Check its callback count has been incremented.
|
||||||
The auto-reload timer is still not running so should still have the same
|
* The auto-reload timer is still not running so should still have the same
|
||||||
count value. This time the one-shot timer is not reset so should not
|
* count value. This time the one-shot timer is not reset so should not
|
||||||
restart from its expiry period again. */
|
* restart from its expiry period again. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -1076,8 +1082,8 @@ static TickType_t uxTick = ( TickType_t ) -1;
|
||||||
else if( uxTick == ( 15 * xBasePeriod ) )
|
else if( uxTick == ( 15 * xBasePeriod ) )
|
||||||
{
|
{
|
||||||
/* Neither timer should be running now. Check neither callback count
|
/* Neither timer should be running now. Check neither callback count
|
||||||
has incremented, then go back to the start to run these tests all
|
* has incremented, then go back to the start to run these tests all
|
||||||
over again. */
|
* over again. */
|
||||||
if( ucISRAutoReloadTimerCounter != 3 )
|
if( ucISRAutoReloadTimerCounter != 3 )
|
||||||
{
|
{
|
||||||
xTestStatus = pdFAIL;
|
xTestStatus = pdFAIL;
|
||||||
|
|
@ -1102,6 +1108,7 @@ static void prvAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer )
|
||||||
size_t uxTimerID;
|
size_t uxTimerID;
|
||||||
|
|
||||||
uxTimerID = ( size_t ) pvTimerGetTimerID( pxExpiredTimer );
|
uxTimerID = ( size_t ) pvTimerGetTimerID( pxExpiredTimer );
|
||||||
|
|
||||||
if( uxTimerID <= ( configTIMER_QUEUE_LENGTH + 1 ) )
|
if( uxTimerID <= ( configTIMER_QUEUE_LENGTH + 1 ) )
|
||||||
{
|
{
|
||||||
( ucAutoReloadTimerCounters[ uxTimerID ] )++;
|
( ucAutoReloadTimerCounters[ uxTimerID ] )++;
|
||||||
|
|
@ -1125,18 +1132,18 @@ size_t uxTimerID;
|
||||||
static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer )
|
static void prvOneShotTimerCallback( TimerHandle_t pxExpiredTimer )
|
||||||
{
|
{
|
||||||
/* A count is kept of the number of times this callback function is executed.
|
/* A count is kept of the number of times this callback function is executed.
|
||||||
The count is stored as the timer's ID. This is only done to test the
|
* The count is stored as the timer's ID. This is only done to test the
|
||||||
vTimerSetTimerID() function. */
|
* vTimerSetTimerID() function. */
|
||||||
static size_t uxCallCount = 0;
|
static size_t uxCallCount = 0;
|
||||||
size_t uxLastCallCount;
|
size_t uxLastCallCount;
|
||||||
|
|
||||||
/* Obtain the timer's ID, which should be a count of the number of times
|
/* Obtain the timer's ID, which should be a count of the number of times
|
||||||
this callback function has been executed. */
|
* this callback function has been executed. */
|
||||||
uxLastCallCount = ( size_t ) pvTimerGetTimerID( pxExpiredTimer );
|
uxLastCallCount = ( size_t ) pvTimerGetTimerID( pxExpiredTimer );
|
||||||
configASSERT( uxLastCallCount == uxCallCount );
|
configASSERT( uxLastCallCount == uxCallCount );
|
||||||
|
|
||||||
/* Increment the call count, then save it back as the timer's ID. This is
|
/* Increment the call count, then save it back as the timer's ID. This is
|
||||||
only done to test the vTimerSetTimerID() API function. */
|
* only done to test the vTimerSetTimerID() API function. */
|
||||||
uxLastCallCount++;
|
uxLastCallCount++;
|
||||||
vTimerSetTimerID( pxExpiredTimer, ( void * ) uxLastCallCount );
|
vTimerSetTimerID( pxExpiredTimer, ( void * ) uxLastCallCount );
|
||||||
uxCallCount++;
|
uxCallCount++;
|
||||||
|
|
@ -1148,7 +1155,7 @@ size_t uxLastCallCount;
|
||||||
static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer )
|
static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer )
|
||||||
{
|
{
|
||||||
/* The parameter is not used in this case as only one timer uses this
|
/* The parameter is not used in this case as only one timer uses this
|
||||||
callback function. */
|
* callback function. */
|
||||||
( void ) pxExpiredTimer;
|
( void ) pxExpiredTimer;
|
||||||
|
|
||||||
ucISRAutoReloadTimerCounter++;
|
ucISRAutoReloadTimerCounter++;
|
||||||
|
|
@ -1158,13 +1165,9 @@ static void prvISRAutoReloadTimerCallback( TimerHandle_t pxExpiredTimer )
|
||||||
static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer )
|
static void prvISROneShotTimerCallback( TimerHandle_t pxExpiredTimer )
|
||||||
{
|
{
|
||||||
/* The parameter is not used in this case as only one timer uses this
|
/* The parameter is not used in this case as only one timer uses this
|
||||||
callback function. */
|
* callback function. */
|
||||||
( void ) pxExpiredTimer;
|
( void ) pxExpiredTimer;
|
||||||
|
|
||||||
ucISROneShotTimerCounter++;
|
ucISROneShotTimerCounter++;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 )
|
#define bktRUN_INDICATOR ( ( UBaseType_t ) 0x55 )
|
||||||
|
|
||||||
/* In case the demo does not have software timers enabled, as this file uses
|
/* In case the demo does not have software timers enabled, as this file uses
|
||||||
the configTIMER_TASK_PRIORITY setting. */
|
* the configTIMER_TASK_PRIORITY setting. */
|
||||||
#ifndef configTIMER_TASK_PRIORITY
|
#ifndef configTIMER_TASK_PRIORITY
|
||||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -86,7 +86,7 @@ static void prvBasicDelayTests( void );
|
||||||
static QueueHandle_t xTestQueue;
|
static QueueHandle_t xTestQueue;
|
||||||
|
|
||||||
/* Handle to the secondary task is required by the primary task for calls
|
/* Handle to the secondary task is required by the primary task for calls
|
||||||
to vTaskSuspend/Resume(). */
|
* to vTaskSuspend/Resume(). */
|
||||||
static TaskHandle_t xSecondary;
|
static TaskHandle_t xSecondary;
|
||||||
|
|
||||||
/* Used to ensure that tasks are still executing without error. */
|
/* Used to ensure that tasks are still executing without error. */
|
||||||
|
|
@ -94,7 +94,7 @@ static volatile BaseType_t xPrimaryCycles = 0, xSecondaryCycles = 0;
|
||||||
static volatile BaseType_t xErrorOccurred = pdFALSE;
|
static volatile BaseType_t xErrorOccurred = pdFALSE;
|
||||||
|
|
||||||
/* Provides a simple mechanism for the primary task to know when the
|
/* Provides a simple mechanism for the primary task to know when the
|
||||||
secondary task has executed. */
|
* secondary task has executed. */
|
||||||
static volatile UBaseType_t xRunIndicator;
|
static volatile UBaseType_t xRunIndicator;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -107,11 +107,11 @@ void vCreateBlockTimeTasks( void )
|
||||||
if( xTestQueue != NULL )
|
if( xTestQueue != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one
|
||||||
is in use. The queue registry is provided as a means for kernel aware
|
* is in use. The queue registry is provided as a means for kernel aware
|
||||||
debuggers to locate queues and has no purpose if a kernel aware
|
* debuggers to locate queues and has no purpose if a kernel aware
|
||||||
debugger is not being used. The call to vQueueAddToRegistry() will be
|
* debugger is not being used. The call to vQueueAddToRegistry() will be
|
||||||
removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
* removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
||||||
defined or is defined to be less than 1. */
|
* defined or is defined to be less than 1. */
|
||||||
vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" );
|
vQueueAddToRegistry( xTestQueue, "Block_Time_Queue" );
|
||||||
|
|
||||||
/* Create the two test tasks. */
|
/* Create the two test tasks. */
|
||||||
|
|
@ -132,26 +132,25 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 0
|
* Test 0
|
||||||
|
*
|
||||||
Basic vTaskDelay() and vTaskDelayUntil() tests. */
|
* Basic vTaskDelay() and vTaskDelayUntil() tests. */
|
||||||
prvBasicDelayTests();
|
prvBasicDelayTests();
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 1
|
* Test 1
|
||||||
|
*
|
||||||
Simple block time wakeup test on queue receives. */
|
* Simple block time wakeup test on queue receives. */
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
||||||
{
|
{
|
||||||
/* The queue is empty. Attempt to read from the queue using a block
|
/* The queue is empty. Attempt to read from the queue using a block
|
||||||
time. When we wake, ensure the delta in time is as expected. */
|
* time. When we wake, ensure the delta in time is as expected. */
|
||||||
xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
|
xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
|
||||||
|
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
/* We should unblock after xTimeToBlock having not received
|
/* We should unblock after xTimeToBlock having not received
|
||||||
anything on the queue. */
|
* anything on the queue. */
|
||||||
if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
|
if( xQueueReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -169,18 +168,18 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
|
if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
|
||||||
{
|
{
|
||||||
/* Should not have blocked for longer than we requested,
|
/* Should not have blocked for longer than we requested,
|
||||||
although we would not necessarily run as soon as we were
|
* although we would not necessarily run as soon as we were
|
||||||
unblocked so a margin is allowed. */
|
* unblocked so a margin is allowed. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 2
|
* Test 2
|
||||||
|
*
|
||||||
Simple block time wakeup test on queue sends.
|
* Simple block time wakeup test on queue sends.
|
||||||
|
*
|
||||||
First fill the queue. It should be empty so all sends should pass. */
|
* First fill the queue. It should be empty so all sends should pass. */
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
||||||
{
|
{
|
||||||
if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
||||||
|
|
@ -196,13 +195,13 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
||||||
{
|
{
|
||||||
/* The queue is full. Attempt to write to the queue using a block
|
/* The queue is full. Attempt to write to the queue using a block
|
||||||
time. When we wake, ensure the delta in time is as expected. */
|
* time. When we wake, ensure the delta in time is as expected. */
|
||||||
xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
|
xTimeToBlock = ( TickType_t ) ( bktPRIMARY_BLOCK_TIME << xItem );
|
||||||
|
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
/* We should unblock after xTimeToBlock having not received
|
/* We should unblock after xTimeToBlock having not received
|
||||||
anything on the queue. */
|
* anything on the queue. */
|
||||||
if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
|
if( xQueueSend( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -220,24 +219,24 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
|
if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) )
|
||||||
{
|
{
|
||||||
/* Should not have blocked for longer than we requested,
|
/* Should not have blocked for longer than we requested,
|
||||||
although we would not necessarily run as soon as we were
|
* although we would not necessarily run as soon as we were
|
||||||
unblocked so a margin is allowed. */
|
* unblocked so a margin is allowed. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 3
|
* Test 3
|
||||||
|
*
|
||||||
Wake the other task, it will block attempting to post to the queue.
|
* Wake the other task, it will block attempting to post to the queue.
|
||||||
When we read from the queue the other task will wake, but before it
|
* When we read from the queue the other task will wake, but before it
|
||||||
can run we will post to the queue again. When the other task runs it
|
* can run we will post to the queue again. When the other task runs it
|
||||||
will find the queue still full, even though it was woken. It should
|
* will find the queue still full, even though it was woken. It should
|
||||||
recognise that its block time has not expired and return to block for
|
* recognise that its block time has not expired and return to block for
|
||||||
the remains of its block time.
|
* the remains of its block time.
|
||||||
|
*
|
||||||
Wake the other task so it blocks attempting to post to the already
|
* Wake the other task so it blocks attempting to post to the already
|
||||||
full queue. */
|
* full queue. */
|
||||||
xRunIndicator = 0;
|
xRunIndicator = 0;
|
||||||
vTaskResume( xSecondary );
|
vTaskResume( xSecondary );
|
||||||
|
|
||||||
|
|
@ -247,6 +246,7 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
/* The other task has not yet executed. */
|
/* The other task has not yet executed. */
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the other task is blocked on the queue. */
|
/* Make sure the other task is blocked on the queue. */
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
xRunIndicator = 0;
|
xRunIndicator = 0;
|
||||||
|
|
@ -254,15 +254,15 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
||||||
{
|
{
|
||||||
/* Now when we make space on the queue the other task should wake
|
/* Now when we make space on the queue the other task should wake
|
||||||
but not execute as this task has higher priority. */
|
* but not execute as this task has higher priority. */
|
||||||
if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now fill the queue again before the other task gets a chance to
|
/* Now fill the queue again before the other task gets a chance to
|
||||||
execute. If the other task had executed we would find the queue
|
* execute. If the other task had executed we would find the queue
|
||||||
full ourselves, and the other task have set xRunIndicator. */
|
* full ourselves, and the other task have set xRunIndicator. */
|
||||||
if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -275,15 +275,15 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Raise the priority of the other task so it executes and blocks
|
/* Raise the priority of the other task so it executes and blocks
|
||||||
on the queue again. */
|
* on the queue again. */
|
||||||
vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
|
vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
|
||||||
|
|
||||||
/* The other task should now have re-blocked without exiting the
|
/* The other task should now have re-blocked without exiting the
|
||||||
queue function. */
|
* queue function. */
|
||||||
if( xRunIndicator == bktRUN_INDICATOR )
|
if( xRunIndicator == bktRUN_INDICATOR )
|
||||||
{
|
{
|
||||||
/* The other task should not have executed outside of the
|
/* The other task should not have executed outside of the
|
||||||
queue function. */
|
* queue function. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,22 +292,22 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the other task timeout. When it unblockes it will check that it
|
/* Let the other task timeout. When it unblockes it will check that it
|
||||||
unblocked at the correct time, then suspend itself. */
|
* unblocked at the correct time, then suspend itself. */
|
||||||
while( xRunIndicator != bktRUN_INDICATOR )
|
while( xRunIndicator != bktRUN_INDICATOR )
|
||||||
{
|
{
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
xRunIndicator = 0;
|
xRunIndicator = 0;
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 4
|
* Test 4
|
||||||
|
*
|
||||||
As per test 3 - but with the send and receive the other way around.
|
* As per test 3 - but with the send and receive the other way around.
|
||||||
The other task blocks attempting to read from the queue.
|
* The other task blocks attempting to read from the queue.
|
||||||
|
*
|
||||||
Empty the queue. We should find that it is full. */
|
* Empty the queue. We should find that it is full. */
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
||||||
{
|
{
|
||||||
if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
||||||
|
|
@ -317,7 +317,7 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wake the other task so it blocks attempting to read from the
|
/* Wake the other task so it blocks attempting to read from the
|
||||||
already empty queue. */
|
* already empty queue. */
|
||||||
vTaskResume( xSecondary );
|
vTaskResume( xSecondary );
|
||||||
|
|
||||||
/* We need to wait a little to ensure the other task executes. */
|
/* We need to wait a little to ensure the other task executes. */
|
||||||
|
|
@ -325,21 +325,22 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
{
|
{
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
xRunIndicator = 0;
|
xRunIndicator = 0;
|
||||||
|
|
||||||
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ )
|
||||||
{
|
{
|
||||||
/* Now when we place an item on the queue the other task should
|
/* Now when we place an item on the queue the other task should
|
||||||
wake but not execute as this task has higher priority. */
|
* wake but not execute as this task has higher priority. */
|
||||||
if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
if( xQueueSend( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now empty the queue again before the other task gets a chance to
|
/* Now empty the queue again before the other task gets a chance to
|
||||||
execute. If the other task had executed we would find the queue
|
* execute. If the other task had executed we would find the queue
|
||||||
empty ourselves, and the other task would be suspended. */
|
* empty ourselves, and the other task would be suspended. */
|
||||||
if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
if( xQueueReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -352,26 +353,28 @@ TickType_t xTimeToBlock, xBlockedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Raise the priority of the other task so it executes and blocks
|
/* Raise the priority of the other task so it executes and blocks
|
||||||
on the queue again. */
|
* on the queue again. */
|
||||||
vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
|
vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 );
|
||||||
|
|
||||||
/* The other task should now have re-blocked without exiting the
|
/* The other task should now have re-blocked without exiting the
|
||||||
queue function. */
|
* queue function. */
|
||||||
if( xRunIndicator == bktRUN_INDICATOR )
|
if( xRunIndicator == bktRUN_INDICATOR )
|
||||||
{
|
{
|
||||||
/* The other task should not have executed outside of the
|
/* The other task should not have executed outside of the
|
||||||
queue function. */
|
* queue function. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
|
vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the other task timeout. When it unblockes it will check that it
|
/* Let the other task timeout. When it unblockes it will check that it
|
||||||
unblocked at the correct time, then suspend itself. */
|
* unblocked at the correct time, then suspend itself. */
|
||||||
while( xRunIndicator != bktRUN_INDICATOR )
|
while( xRunIndicator != bktRUN_INDICATOR )
|
||||||
{
|
{
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelay( bktSHORT_WAIT );
|
vTaskDelay( bktSHORT_WAIT );
|
||||||
|
|
||||||
xPrimaryCycles++;
|
xPrimaryCycles++;
|
||||||
|
|
@ -389,23 +392,24 @@ BaseType_t xData;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 0, 1 and 2
|
* Test 0, 1 and 2
|
||||||
|
*
|
||||||
This task does not participate in these tests. */
|
* This task does not participate in these tests. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 3
|
* Test 3
|
||||||
|
*
|
||||||
The first thing we do is attempt to read from the queue. It should be
|
* The first thing we do is attempt to read from the queue. It should be
|
||||||
full so we block. Note the time before we block so we can check the
|
* full so we block. Note the time before we block so we can check the
|
||||||
wake time is as per that expected. */
|
* wake time is as per that expected. */
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
/* We should unblock after bktTIME_TO_BLOCK having not sent anything to
|
/* We should unblock after bktTIME_TO_BLOCK having not sent anything to
|
||||||
the queue. */
|
* the queue. */
|
||||||
xData = 0;
|
xData = 0;
|
||||||
xRunIndicator = bktRUN_INDICATOR;
|
xRunIndicator = bktRUN_INDICATOR;
|
||||||
|
|
||||||
if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
|
if( xQueueSend( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -421,8 +425,8 @@ BaseType_t xData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
|
/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
|
||||||
either. A margin is permitted as we would not necessarily run as
|
* either. A margin is permitted as we would not necessarily run as
|
||||||
soon as we unblocked. */
|
* soon as we unblocked. */
|
||||||
if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
|
if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -433,14 +437,15 @@ BaseType_t xData;
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Test 4
|
* Test 4
|
||||||
|
*
|
||||||
As per test three, but with the send and receive reversed. */
|
* As per test three, but with the send and receive reversed. */
|
||||||
xTimeWhenBlocking = xTaskGetTickCount();
|
xTimeWhenBlocking = xTaskGetTickCount();
|
||||||
|
|
||||||
/* We should unblock after bktTIME_TO_BLOCK having not received
|
/* We should unblock after bktTIME_TO_BLOCK having not received
|
||||||
anything on the queue. */
|
* anything on the queue. */
|
||||||
xRunIndicator = bktRUN_INDICATOR;
|
xRunIndicator = bktRUN_INDICATOR;
|
||||||
|
|
||||||
if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
|
if( xQueueReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -455,8 +460,8 @@ BaseType_t xData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
|
/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
|
||||||
either. A margin is permitted as we would not necessarily run as soon
|
* either. A margin is permitted as we would not necessarily run as soon
|
||||||
as we unblocked. */
|
* as we unblocked. */
|
||||||
if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
|
if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -476,17 +481,17 @@ const TickType_t xPeriod = 75, xCycles = 5, xAllowableMargin = ( bktALLOWABLE_MA
|
||||||
BaseType_t xDidBlock;
|
BaseType_t xDidBlock;
|
||||||
|
|
||||||
/* Temporarily increase priority so the timing is more accurate, but not so
|
/* Temporarily increase priority so the timing is more accurate, but not so
|
||||||
high as to disrupt the timer tests. */
|
* high as to disrupt the timer tests. */
|
||||||
vTaskPrioritySet( NULL, configTIMER_TASK_PRIORITY - 1 );
|
vTaskPrioritySet( NULL, configTIMER_TASK_PRIORITY - 1 );
|
||||||
|
|
||||||
/* Crude check to too see that vTaskDelay() blocks for the expected
|
/* Crude check to too see that vTaskDelay() blocks for the expected
|
||||||
period. */
|
* period. */
|
||||||
xPreTime = xTaskGetTickCount();
|
xPreTime = xTaskGetTickCount();
|
||||||
vTaskDelay( bktTIME_TO_BLOCK );
|
vTaskDelay( bktTIME_TO_BLOCK );
|
||||||
xPostTime = xTaskGetTickCount();
|
xPostTime = xTaskGetTickCount();
|
||||||
|
|
||||||
/* The priority is higher, so the allowable margin is halved when compared
|
/* The priority is higher, so the allowable margin is halved when compared
|
||||||
to the other tests in this file. */
|
* to the other tests in this file. */
|
||||||
if( ( xPostTime - xPreTime ) > ( bktTIME_TO_BLOCK + xAllowableMargin ) )
|
if( ( xPostTime - xPreTime ) > ( bktTIME_TO_BLOCK + xAllowableMargin ) )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -499,7 +504,7 @@ BaseType_t xDidBlock;
|
||||||
for( x = 0; x < xCycles; x++ )
|
for( x = 0; x < xCycles; x++ )
|
||||||
{
|
{
|
||||||
/* Calculate the next expected unblock time from the time taken before
|
/* Calculate the next expected unblock time from the time taken before
|
||||||
this loop was entered. */
|
* this loop was entered. */
|
||||||
xExpectedUnblockTime = xPostTime + ( x * xPeriod );
|
xExpectedUnblockTime = xPostTime + ( x * xPeriod );
|
||||||
|
|
||||||
vTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
vTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
||||||
|
|
@ -513,26 +518,29 @@ BaseType_t xDidBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Crude tests for return value of xTaskDelayUntil(). First a standard block
|
/* Crude tests for return value of xTaskDelayUntil(). First a standard block
|
||||||
should return that the task does block. */
|
* should return that the task does block. */
|
||||||
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
||||||
|
|
||||||
if( xDidBlock != pdTRUE )
|
if( xDidBlock != pdTRUE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now delay a few ticks so repeating the above block period will not block for
|
/* Now delay a few ticks so repeating the above block period will not block for
|
||||||
the full amount of time, but will still block. */
|
* the full amount of time, but will still block. */
|
||||||
vTaskDelay( xHalfPeriod );
|
vTaskDelay( xHalfPeriod );
|
||||||
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
||||||
|
|
||||||
if( xDidBlock != pdTRUE )
|
if( xDidBlock != pdTRUE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This time block for longer than xPeriod before calling xTaskDelayUntil() so
|
/* This time block for longer than xPeriod before calling xTaskDelayUntil() so
|
||||||
the call to xTaskDelayUntil() should not block. */
|
* the call to xTaskDelayUntil() should not block. */
|
||||||
vTaskDelay( xPeriod );
|
vTaskDelay( xPeriod );
|
||||||
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
||||||
|
|
||||||
if( xDidBlock != pdFALSE )
|
if( xDidBlock != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -540,15 +548,17 @@ BaseType_t xDidBlock;
|
||||||
|
|
||||||
/* Catch up. */
|
/* Catch up. */
|
||||||
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
||||||
|
|
||||||
if( xDidBlock != pdTRUE )
|
if( xDidBlock != pdTRUE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Again block for slightly longer than a period so ensure the time is in the
|
/* Again block for slightly longer than a period so ensure the time is in the
|
||||||
past next time xTaskDelayUntil() gets called. */
|
* past next time xTaskDelayUntil() gets called. */
|
||||||
vTaskDelay( xPeriod + xAllowableMargin );
|
vTaskDelay( xPeriod + xAllowableMargin );
|
||||||
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
xDidBlock = xTaskDelayUntil( &xLastUnblockTime, xPeriod );
|
||||||
|
|
||||||
if( xDidBlock != pdFALSE )
|
if( xDidBlock != pdFALSE )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -565,7 +575,7 @@ static BaseType_t xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
|
||||||
BaseType_t xReturn = pdPASS;
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
/* Have both tasks performed at least one cycle since this function was
|
/* Have both tasks performed at least one cycle since this function was
|
||||||
last called? */
|
* last called? */
|
||||||
if( xPrimaryCycles == xLastPrimaryCycleCount )
|
if( xPrimaryCycles == xLastPrimaryCycleCount )
|
||||||
{
|
{
|
||||||
xReturn = pdFAIL;
|
xReturn = pdFAIL;
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,13 @@
|
||||||
#define comTOTAL_PERMISSIBLE_ERRORS ( 2 )
|
#define comTOTAL_PERMISSIBLE_ERRORS ( 2 )
|
||||||
|
|
||||||
/* The Tx task will transmit the sequence of characters at a pseudo random
|
/* The Tx task will transmit the sequence of characters at a pseudo random
|
||||||
interval. This is the maximum and minimum block time between sends. */
|
* interval. This is the maximum and minimum block time between sends. */
|
||||||
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 )
|
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 )
|
||||||
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 )
|
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 )
|
||||||
#define comOFFSET_TIME ( ( TickType_t ) 3 )
|
#define comOFFSET_TIME ( ( TickType_t ) 3 )
|
||||||
|
|
||||||
/* We should find that each character can be queued for Tx immediately and we
|
/* We should find that each character can be queued for Tx immediately and we
|
||||||
don't have to block to send. */
|
* don't have to block to send. */
|
||||||
#define comNO_BLOCK ( ( TickType_t ) 0 )
|
#define comNO_BLOCK ( ( TickType_t ) 0 )
|
||||||
|
|
||||||
/* The Rx task will block on the Rx queue for a long period. */
|
/* The Rx task will block on the Rx queue for a long period. */
|
||||||
|
|
@ -102,18 +102,20 @@ static portTASK_FUNCTION_PROTO( vComTxTask, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vComRxTask, pvParameters );
|
static portTASK_FUNCTION_PROTO( vComRxTask, pvParameters );
|
||||||
|
|
||||||
/* The LED that should be toggled by the Rx and Tx tasks. The Rx task will
|
/* The LED that should be toggled by the Rx and Tx tasks. The Rx task will
|
||||||
toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task will toggle LED
|
* toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task will toggle LED
|
||||||
( uxBaseLED + comTX_LED_OFFSET ). */
|
* ( uxBaseLED + comTX_LED_OFFSET ). */
|
||||||
static UBaseType_t uxBaseLED = 0;
|
static UBaseType_t uxBaseLED = 0;
|
||||||
|
|
||||||
/* Check variable used to ensure no error have occurred. The Rx task will
|
/* Check variable used to ensure no error have occurred. The Rx task will
|
||||||
increment this variable after every successfully received sequence. If at any
|
* increment this variable after every successfully received sequence. If at any
|
||||||
time the sequence is incorrect the the variable will stop being incremented. */
|
* time the sequence is incorrect the the variable will stop being incremented. */
|
||||||
static volatile UBaseType_t uxRxLoops = comINITIAL_RX_COUNT_VALUE;
|
static volatile UBaseType_t uxRxLoops = comINITIAL_RX_COUNT_VALUE;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED )
|
void vAltStartComTestTasks( UBaseType_t uxPriority,
|
||||||
|
uint32_t ulBaudRate,
|
||||||
|
UBaseType_t uxLED )
|
||||||
{
|
{
|
||||||
/* Initialise the com port then spawn the Rx and Tx tasks. */
|
/* Initialise the com port then spawn the Rx and Tx tasks. */
|
||||||
uxBaseLED = uxLED;
|
uxBaseLED = uxLED;
|
||||||
|
|
@ -136,7 +138,7 @@ TickType_t xTimeToWait;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Simply transmit a sequence of characters from comFIRST_BYTE to
|
/* Simply transmit a sequence of characters from comFIRST_BYTE to
|
||||||
comLAST_BYTE. */
|
* comLAST_BYTE. */
|
||||||
for( cByteToSend = comFIRST_BYTE; cByteToSend <= comLAST_BYTE; cByteToSend++ )
|
for( cByteToSend = comFIRST_BYTE; cByteToSend <= comLAST_BYTE; cByteToSend++ )
|
||||||
{
|
{
|
||||||
if( xSerialPutChar( xPort, cByteToSend, comNO_BLOCK ) == pdPASS )
|
if( xSerialPutChar( xPort, cByteToSend, comNO_BLOCK ) == pdPASS )
|
||||||
|
|
@ -149,8 +151,8 @@ TickType_t xTimeToWait;
|
||||||
vParTestSetLED( uxBaseLED + comTX_LED_OFFSET, pdFALSE );
|
vParTestSetLED( uxBaseLED + comTX_LED_OFFSET, pdFALSE );
|
||||||
|
|
||||||
/* We have posted all the characters in the string - wait before
|
/* We have posted all the characters in the string - wait before
|
||||||
re-sending. Wait a pseudo-random time as this will provide a better
|
* re-sending. Wait a pseudo-random time as this will provide a better
|
||||||
test. */
|
* test. */
|
||||||
xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME;
|
xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME;
|
||||||
|
|
||||||
/* Make sure we don't wait too long... */
|
/* Make sure we don't wait too long... */
|
||||||
|
|
@ -178,16 +180,16 @@ BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* We expect to receive the characters from comFIRST_BYTE to
|
/* We expect to receive the characters from comFIRST_BYTE to
|
||||||
comLAST_BYTE in an incrementing order. Loop to receive each byte. */
|
* comLAST_BYTE in an incrementing order. Loop to receive each byte. */
|
||||||
for( cExpectedByte = comFIRST_BYTE; cExpectedByte <= comLAST_BYTE; cExpectedByte++ )
|
for( cExpectedByte = comFIRST_BYTE; cExpectedByte <= comLAST_BYTE; cExpectedByte++ )
|
||||||
{
|
{
|
||||||
/* Block on the queue that contains received bytes until a byte is
|
/* Block on the queue that contains received bytes until a byte is
|
||||||
available. */
|
* available. */
|
||||||
if( xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ) )
|
if( xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ) )
|
||||||
{
|
{
|
||||||
/* Was this the byte we were expecting? If so, toggle the LED,
|
/* Was this the byte we were expecting? If so, toggle the LED,
|
||||||
otherwise we are out on sync and should break out of the loop
|
* otherwise we are out on sync and should break out of the loop
|
||||||
until the expected character sequence is about to restart. */
|
* until the expected character sequence is about to restart. */
|
||||||
if( cByteRxed == cExpectedByte )
|
if( cByteRxed == cExpectedByte )
|
||||||
{
|
{
|
||||||
vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET );
|
vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET );
|
||||||
|
|
@ -204,8 +206,8 @@ BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE;
|
||||||
vParTestSetLED( uxBaseLED + comRX_LED_OFFSET, pdFALSE );
|
vParTestSetLED( uxBaseLED + comRX_LED_OFFSET, pdFALSE );
|
||||||
|
|
||||||
/* Did we break out of the loop because the characters were received in
|
/* Did we break out of the loop because the characters were received in
|
||||||
an unexpected order? If so wait here until the character sequence is
|
* an unexpected order? If so wait here until the character sequence is
|
||||||
about to restart. */
|
* about to restart. */
|
||||||
if( xResyncRequired == pdTRUE )
|
if( xResyncRequired == pdTRUE )
|
||||||
{
|
{
|
||||||
while( cByteRxed != comLAST_BYTE )
|
while( cByteRxed != comLAST_BYTE )
|
||||||
|
|
@ -215,9 +217,9 @@ BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that an error occurred which caused us to have to resync.
|
/* Note that an error occurred which caused us to have to resync.
|
||||||
We use this to stop incrementing the loop counter so
|
* We use this to stop incrementing the loop counter so
|
||||||
sAreComTestTasksStillRunning() will return false - indicating an
|
* sAreComTestTasksStillRunning() will return false - indicating an
|
||||||
error. */
|
* error. */
|
||||||
xErrorOccurred++;
|
xErrorOccurred++;
|
||||||
|
|
||||||
/* We have now resynced with the Tx task and can continue. */
|
/* We have now resynced with the Tx task and can continue. */
|
||||||
|
|
@ -228,11 +230,11 @@ BaseType_t xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE;
|
||||||
if( xErrorOccurred < comTOTAL_PERMISSIBLE_ERRORS )
|
if( xErrorOccurred < comTOTAL_PERMISSIBLE_ERRORS )
|
||||||
{
|
{
|
||||||
/* Increment the count of successful loops. As error
|
/* Increment the count of successful loops. As error
|
||||||
occurring (i.e. an unexpected character being received) will
|
* occurring (i.e. an unexpected character being received) will
|
||||||
prevent this counter being incremented for the rest of the
|
* prevent this counter being incremented for the rest of the
|
||||||
execution. Don't worry about mutual exclusion on this
|
* execution. Don't worry about mutual exclusion on this
|
||||||
variable - it doesn't really matter as we just want it
|
* variable - it doesn't really matter as we just want it
|
||||||
to change. */
|
* to change. */
|
||||||
uxRxLoops++;
|
uxRxLoops++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -245,8 +247,8 @@ BaseType_t xAreComTestTasksStillRunning( void )
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
|
|
||||||
/* If the count of successful reception loops has not changed than at
|
/* If the count of successful reception loops has not changed than at
|
||||||
some time an error occurred (i.e. a character was received out of sequence)
|
* some time an error occurred (i.e. a character was received out of sequence)
|
||||||
and we will return false. */
|
* and we will return false. */
|
||||||
if( uxRxLoops == comINITIAL_RX_COUNT_VALUE )
|
if( uxRxLoops == comINITIAL_RX_COUNT_VALUE )
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
|
|
@ -257,9 +259,8 @@ BaseType_t xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the count of successful Rx loops. When this function is called
|
/* Reset the count of successful Rx loops. When this function is called
|
||||||
again we expect this to have been incremented. */
|
* again we expect this to have been incremented. */
|
||||||
uxRxLoops = comINITIAL_RX_COUNT_VALUE;
|
uxRxLoops = comINITIAL_RX_COUNT_VALUE;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,8 @@
|
||||||
#define comRX_LED_OFFSET ( 1 )
|
#define comRX_LED_OFFSET ( 1 )
|
||||||
|
|
||||||
/* The Tx timer transmits the sequence of characters at a pseudo random
|
/* The Tx timer transmits the sequence of characters at a pseudo random
|
||||||
interval that is capped between comTX_MAX_BLOCK_TIME and
|
* interval that is capped between comTX_MAX_BLOCK_TIME and
|
||||||
comTX_MIN_BLOCK_TIME. */
|
* comTX_MIN_BLOCK_TIME. */
|
||||||
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 )
|
#define comTX_MAX_BLOCK_TIME ( ( TickType_t ) 0x96 )
|
||||||
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 )
|
#define comTX_MIN_BLOCK_TIME ( ( TickType_t ) 0x32 )
|
||||||
#define comOFFSET_TIME ( ( TickType_t ) 3 )
|
#define comOFFSET_TIME ( ( TickType_t ) 3 )
|
||||||
|
|
@ -89,10 +89,10 @@ comTX_MIN_BLOCK_TIME. */
|
||||||
#define comtstWAITING_END_OF_STRING 1
|
#define comtstWAITING_END_OF_STRING 1
|
||||||
|
|
||||||
/* A short delay in ticks - this delay is used to allow the Rx queue to fill up
|
/* A short delay in ticks - this delay is used to allow the Rx queue to fill up
|
||||||
a bit so more than one character can be processed at a time. This is relative
|
* a bit so more than one character can be processed at a time. This is relative
|
||||||
to comTX_MIN_BLOCK_TIME to ensure it is never longer than the shortest gap
|
* to comTX_MIN_BLOCK_TIME to ensure it is never longer than the shortest gap
|
||||||
between transmissions. It could be worked out more scientifically from the
|
* between transmissions. It could be worked out more scientifically from the
|
||||||
baud rate being used. */
|
* baud rate being used. */
|
||||||
#define comSHORT_DELAY ( comTX_MIN_BLOCK_TIME >> ( TickType_t ) 2 )
|
#define comSHORT_DELAY ( comTX_MIN_BLOCK_TIME >> ( TickType_t ) 2 )
|
||||||
|
|
||||||
/* The string that is transmitted and received. */
|
/* The string that is transmitted and received. */
|
||||||
|
|
@ -105,50 +105,52 @@ baud rate being used. */
|
||||||
static xComPortHandle xPort = NULL;
|
static xComPortHandle xPort = NULL;
|
||||||
|
|
||||||
/* The callback function allocated to the transmit timer, as described in the
|
/* The callback function allocated to the transmit timer, as described in the
|
||||||
comments at the top of this file. */
|
* comments at the top of this file. */
|
||||||
static void prvComTxTimerCallback( TimerHandle_t xTimer );
|
static void prvComTxTimerCallback( TimerHandle_t xTimer );
|
||||||
|
|
||||||
/* The receive task as described in the comments at the top of this file. */
|
/* The receive task as described in the comments at the top of this file. */
|
||||||
static void vComRxTask( void * pvParameters );
|
static void vComRxTask( void * pvParameters );
|
||||||
|
|
||||||
/* The Rx task will toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task
|
/* The Rx task will toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task
|
||||||
will toggle LED ( uxBaseLED + comTX_LED_OFFSET ). */
|
* will toggle LED ( uxBaseLED + comTX_LED_OFFSET ). */
|
||||||
static UBaseType_t uxBaseLED = 0;
|
static UBaseType_t uxBaseLED = 0;
|
||||||
|
|
||||||
/* The Rx task toggles uxRxLoops on each successful iteration of its defined
|
/* The Rx task toggles uxRxLoops on each successful iteration of its defined
|
||||||
function - provided no errors have ever been latched. If this variable stops
|
* function - provided no errors have ever been latched. If this variable stops
|
||||||
incrementing, then an error has occurred. */
|
* incrementing, then an error has occurred. */
|
||||||
static volatile UBaseType_t uxRxLoops = 0UL;
|
static volatile UBaseType_t uxRxLoops = 0UL;
|
||||||
|
|
||||||
/* The timer used to periodically transmit the string. This is the timer that
|
/* The timer used to periodically transmit the string. This is the timer that
|
||||||
has prvComTxTimerCallback allocated to it as its callback function. */
|
* has prvComTxTimerCallback allocated to it as its callback function. */
|
||||||
static TimerHandle_t xTxTimer = NULL;
|
static TimerHandle_t xTxTimer = NULL;
|
||||||
|
|
||||||
/* The string length is held at file scope so the Tx timer does not need to
|
/* The string length is held at file scope so the Tx timer does not need to
|
||||||
calculate it each time it executes. */
|
* calculate it each time it executes. */
|
||||||
static size_t xStringLength = 0U;
|
static size_t xStringLength = 0U;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED )
|
void vStartComTestStringsTasks( UBaseType_t uxPriority,
|
||||||
|
uint32_t ulBaudRate,
|
||||||
|
UBaseType_t uxLED )
|
||||||
{
|
{
|
||||||
/* Store values that are used at run time. */
|
/* Store values that are used at run time. */
|
||||||
uxBaseLED = uxLED;
|
uxBaseLED = uxLED;
|
||||||
|
|
||||||
/* Calculate the string length here, rather than each time the Tx timer
|
/* Calculate the string length here, rather than each time the Tx timer
|
||||||
executes. */
|
* executes. */
|
||||||
xStringLength = strlen( comTRANSACTED_STRING );
|
xStringLength = strlen( comTRANSACTED_STRING );
|
||||||
|
|
||||||
/* Include the null terminator in the string length as this is used to
|
/* Include the null terminator in the string length as this is used to
|
||||||
detect the end of the string in the Rx task. */
|
* detect the end of the string in the Rx task. */
|
||||||
xStringLength++;
|
xStringLength++;
|
||||||
|
|
||||||
/* Initialise the com port, then spawn the Rx task and create the Tx
|
/* Initialise the com port, then spawn the Rx task and create the Tx
|
||||||
timer. */
|
* timer. */
|
||||||
xSerialPortInitMinimal( ulBaudRate, ( xStringLength * 2U ) );
|
xSerialPortInitMinimal( ulBaudRate, ( xStringLength * 2U ) );
|
||||||
|
|
||||||
/* Create the Rx task and the Tx timer. The timer is started from the
|
/* Create the Rx task and the Tx timer. The timer is started from the
|
||||||
Rx task. */
|
* Rx task. */
|
||||||
xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
xTxTimer = xTimerCreate( "TxTimer", comTX_MIN_BLOCK_TIME, pdFALSE, NULL, prvComTxTimerCallback );
|
xTxTimer = xTimerCreate( "TxTimer", comTX_MIN_BLOCK_TIME, pdFALSE, NULL, prvComTxTimerCallback );
|
||||||
configASSERT( xTxTimer );
|
configASSERT( xTxTimer );
|
||||||
|
|
@ -163,13 +165,13 @@ TickType_t xTimeToWait;
|
||||||
( void ) xTimer;
|
( void ) xTimer;
|
||||||
|
|
||||||
/* Send the string. How this is actually performed depends on the
|
/* Send the string. How this is actually performed depends on the
|
||||||
sample driver provided with this demo. However - as this is a timer,
|
* sample driver provided with this demo. However - as this is a timer,
|
||||||
it executes in the context of the timer task and therefore must not
|
* it executes in the context of the timer task and therefore must not
|
||||||
block. */
|
* block. */
|
||||||
vSerialPutString( xPort, comTRANSACTED_STRING, xStringLength );
|
vSerialPutString( xPort, comTRANSACTED_STRING, xStringLength );
|
||||||
|
|
||||||
/* Toggle an LED to give a visible indication that another transmission
|
/* Toggle an LED to give a visible indication that another transmission
|
||||||
has been performed. */
|
* has been performed. */
|
||||||
vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET );
|
vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET );
|
||||||
|
|
||||||
/* Wait a pseudo random time before sending the string again. */
|
/* Wait a pseudo random time before sending the string again. */
|
||||||
|
|
@ -185,8 +187,8 @@ TickType_t xTimeToWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the timer to run again xTimeToWait ticks from now. This function
|
/* Reset the timer to run again xTimeToWait ticks from now. This function
|
||||||
is called from the context of the timer task, so the block time must not
|
* is called from the context of the timer task, so the block time must not
|
||||||
be anything other than zero. */
|
* be anything other than zero. */
|
||||||
xTimerChangePeriod( xTxTimer, xTimeToWait, comtstDONT_BLOCK );
|
xTimerChangePeriod( xTxTimer, xTimeToWait, comtstDONT_BLOCK );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -201,11 +203,11 @@ const xComPortHandle xPort = NULL;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Start the Tx timer. This only needs to be started once, as it will
|
/* Start the Tx timer. This only needs to be started once, as it will
|
||||||
reset itself thereafter. */
|
* reset itself thereafter. */
|
||||||
xTimerStart( xTxTimer, portMAX_DELAY );
|
xTimerStart( xTxTimer, portMAX_DELAY );
|
||||||
|
|
||||||
/* The first expected Rx character is the first in the string that is
|
/* The first expected Rx character is the first in the string that is
|
||||||
transmitted. */
|
* transmitted. */
|
||||||
pcExpectedByte = comTRANSACTED_STRING;
|
pcExpectedByte = comTRANSACTED_STRING;
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
|
|
@ -214,47 +216,50 @@ const xComPortHandle xPort = NULL;
|
||||||
if( xSerialGetChar( xPort, &cRxedChar, ( comTX_MAX_BLOCK_TIME * 2 ) ) == pdFALSE )
|
if( xSerialGetChar( xPort, &cRxedChar, ( comTX_MAX_BLOCK_TIME * 2 ) ) == pdFALSE )
|
||||||
{
|
{
|
||||||
/* A character definitely should have been received by now. As a
|
/* A character definitely should have been received by now. As a
|
||||||
character was not received an error must have occurred (which might
|
* character was not received an error must have occurred (which might
|
||||||
just be that the loopback connector is not fitted). */
|
* just be that the loopback connector is not fitted). */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( xState )
|
switch( xState )
|
||||||
{
|
{
|
||||||
case comtstWAITING_START_OF_STRING:
|
case comtstWAITING_START_OF_STRING:
|
||||||
|
|
||||||
if( cRxedChar == *pcExpectedByte )
|
if( cRxedChar == *pcExpectedByte )
|
||||||
{
|
{
|
||||||
/* The received character was the first character of the
|
/* The received character was the first character of the
|
||||||
string. Move to the next state to check each character
|
* string. Move to the next state to check each character
|
||||||
as it comes in until the entire string has been received. */
|
* as it comes in until the entire string has been received. */
|
||||||
xState = comtstWAITING_END_OF_STRING;
|
xState = comtstWAITING_END_OF_STRING;
|
||||||
pcExpectedByte++;
|
pcExpectedByte++;
|
||||||
|
|
||||||
/* Block for a short period. This just allows the Rx queue
|
/* Block for a short period. This just allows the Rx queue
|
||||||
to contain more than one character, and therefore prevent
|
* to contain more than one character, and therefore prevent
|
||||||
thrashing reads to the queue, and repetitive context
|
* thrashing reads to the queue, and repetitive context
|
||||||
switches as each character is received. */
|
* switches as each character is received. */
|
||||||
vTaskDelay( comSHORT_DELAY );
|
vTaskDelay( comSHORT_DELAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case comtstWAITING_END_OF_STRING:
|
case comtstWAITING_END_OF_STRING:
|
||||||
|
|
||||||
if( cRxedChar == *pcExpectedByte )
|
if( cRxedChar == *pcExpectedByte )
|
||||||
{
|
{
|
||||||
/* The received character was the expected character. Was
|
/* The received character was the expected character. Was
|
||||||
it the last character in the string - i.e. the null
|
* it the last character in the string - i.e. the null
|
||||||
terminator? */
|
* terminator? */
|
||||||
if( cRxedChar == 0x00 )
|
if( cRxedChar == 0x00 )
|
||||||
{
|
{
|
||||||
/* The entire string has been received. If no errors
|
/* The entire string has been received. If no errors
|
||||||
have been latched, then increment the loop counter to
|
* have been latched, then increment the loop counter to
|
||||||
show this task is still healthy. */
|
* show this task is still healthy. */
|
||||||
if( xErrorOccurred == pdFALSE )
|
if( xErrorOccurred == pdFALSE )
|
||||||
{
|
{
|
||||||
uxRxLoops++;
|
uxRxLoops++;
|
||||||
|
|
||||||
/* Toggle an LED to give a visible sign that a
|
/* Toggle an LED to give a visible sign that a
|
||||||
complete string has been received. */
|
* complete string has been received. */
|
||||||
vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET );
|
vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,11 +278,13 @@ const xComPortHandle xPort = NULL;
|
||||||
/* The character received was not that expected. */
|
/* The character received was not that expected. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* Should not get here. Stop the Rx loop counter from
|
/* Should not get here. Stop the Rx loop counter from
|
||||||
incrementing to latch the error. */
|
* incrementing to latch the error. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -290,8 +297,8 @@ BaseType_t xAreComTestTasksStillRunning( void )
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
|
|
||||||
/* If the count of successful reception loops has not changed than at
|
/* If the count of successful reception loops has not changed than at
|
||||||
some time an error occurred (i.e. a character was received out of sequence)
|
* some time an error occurred (i.e. a character was received out of sequence)
|
||||||
and false is returned. */
|
* and false is returned. */
|
||||||
if( uxRxLoops == 0UL )
|
if( uxRxLoops == 0UL )
|
||||||
{
|
{
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
|
|
@ -302,9 +309,8 @@ BaseType_t xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the count of successful Rx loops. When this function is called
|
/* Reset the count of successful Rx loops. When this function is called
|
||||||
again it should have been incremented again. */
|
* again it should have been incremented again. */
|
||||||
uxRxLoops = 0UL;
|
uxRxLoops = 0UL;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,21 +42,21 @@
|
||||||
#define countMAX_COUNT_VALUE ( 200 )
|
#define countMAX_COUNT_VALUE ( 200 )
|
||||||
|
|
||||||
/* Constants used to indicate whether or not the semaphore should have been
|
/* Constants used to indicate whether or not the semaphore should have been
|
||||||
created with its maximum count value, or its minimum count value. These
|
* created with its maximum count value, or its minimum count value. These
|
||||||
numbers are used to ensure that the pointers passed in as the task parameters
|
* numbers are used to ensure that the pointers passed in as the task parameters
|
||||||
are valid. */
|
* are valid. */
|
||||||
#define countSTART_AT_MAX_COUNT ( 0xaa )
|
#define countSTART_AT_MAX_COUNT ( 0xaa )
|
||||||
#define countSTART_AT_ZERO ( 0x55 )
|
#define countSTART_AT_ZERO ( 0x55 )
|
||||||
|
|
||||||
/* Two tasks are created for the test. One uses a semaphore created with its
|
/* Two tasks are created for the test. One uses a semaphore created with its
|
||||||
count value set to the maximum, and one with the count value set to zero. */
|
* count value set to the maximum, and one with the count value set to zero. */
|
||||||
#define countNUM_TEST_TASKS ( 2 )
|
#define countNUM_TEST_TASKS ( 2 )
|
||||||
#define countDONT_BLOCK ( 0 )
|
#define countDONT_BLOCK ( 0 )
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
detected in any of the tasks. */
|
* detected in any of the tasks. */
|
||||||
static volatile BaseType_t xErrorDetected = pdFALSE;
|
static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -73,13 +73,15 @@ static void prvCountingSemaphoreTask( void *pvParameters );
|
||||||
* Utility function to increment the semaphore count value up from zero to
|
* Utility function to increment the semaphore count value up from zero to
|
||||||
* countMAX_COUNT_VALUE.
|
* countMAX_COUNT_VALUE.
|
||||||
*/
|
*/
|
||||||
static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, volatile UBaseType_t *puxLoopCounter );
|
static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore,
|
||||||
|
volatile UBaseType_t * puxLoopCounter );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Utility function to decrement the semaphore count value up from
|
* Utility function to decrement the semaphore count value up from
|
||||||
* countMAX_COUNT_VALUE to zero.
|
* countMAX_COUNT_VALUE to zero.
|
||||||
*/
|
*/
|
||||||
static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, volatile UBaseType_t *puxLoopCounter );
|
static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore,
|
||||||
|
volatile UBaseType_t * puxLoopCounter );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
@ -90,12 +92,12 @@ typedef struct COUNT_SEM_STRUCT
|
||||||
SemaphoreHandle_t xSemaphore;
|
SemaphoreHandle_t xSemaphore;
|
||||||
|
|
||||||
/* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with
|
/* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with
|
||||||
its count value set to its max count value, or countSTART_AT_ZERO if it
|
* its count value set to its max count value, or countSTART_AT_ZERO if it
|
||||||
should have been created with its count value set to 0. */
|
* should have been created with its count value set to 0. */
|
||||||
UBaseType_t uxExpectedStartCount;
|
UBaseType_t uxExpectedStartCount;
|
||||||
|
|
||||||
/* Incremented on each cycle of the demo task. Used to detect a stalled
|
/* Incremented on each cycle of the demo task. Used to detect a stalled
|
||||||
task. */
|
* task. */
|
||||||
volatile UBaseType_t uxLoopCounter;
|
volatile UBaseType_t uxLoopCounter;
|
||||||
} xCountSemStruct;
|
} xCountSemStruct;
|
||||||
|
|
||||||
|
|
@ -107,8 +109,8 @@ static xCountSemStruct xParameters[ countNUM_TEST_TASKS ];
|
||||||
void vStartCountingSemaphoreTasks( void )
|
void vStartCountingSemaphoreTasks( void )
|
||||||
{
|
{
|
||||||
/* Create the semaphores that we are going to use for the test/demo. The
|
/* Create the semaphores that we are going to use for the test/demo. The
|
||||||
first should be created such that it starts at its maximum count value,
|
* first should be created such that it starts at its maximum count value,
|
||||||
the second should be created such that it starts with a count value of zero. */
|
* the second should be created such that it starts with a count value of zero. */
|
||||||
xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE );
|
xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE );
|
||||||
xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT;
|
xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT;
|
||||||
xParameters[ 0 ].uxLoopCounter = 0;
|
xParameters[ 0 ].uxLoopCounter = 0;
|
||||||
|
|
@ -121,11 +123,11 @@ void vStartCountingSemaphoreTasks( void )
|
||||||
if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) )
|
if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the semaphore to the registry, if one is
|
/* vQueueAddToRegistry() adds the semaphore to the registry, if one is
|
||||||
in use. The registry is provided as a means for kernel aware
|
* in use. The registry is provided as a means for kernel aware
|
||||||
debuggers to locate semaphores and has no purpose if a kernel aware
|
* debuggers to locate semaphores and has no purpose if a kernel aware
|
||||||
debugger is not being used. The call to vQueueAddToRegistry() will be
|
* debugger is not being used. The call to vQueueAddToRegistry() will be
|
||||||
removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
* removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
||||||
defined or is defined to be less than 1. */
|
* defined or is defined to be less than 1. */
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 0 ].xSemaphore, "Counting_Sem_1" );
|
vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 0 ].xSemaphore, "Counting_Sem_1" );
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 1 ].xSemaphore, "Counting_Sem_2" );
|
vQueueAddToRegistry( ( QueueHandle_t ) xParameters[ 1 ].xSemaphore, "Counting_Sem_2" );
|
||||||
|
|
||||||
|
|
@ -136,12 +138,13 @@ void vStartCountingSemaphoreTasks( void )
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore, volatile UBaseType_t *puxLoopCounter )
|
static void prvDecrementSemaphoreCount( SemaphoreHandle_t xSemaphore,
|
||||||
|
volatile UBaseType_t * puxLoopCounter )
|
||||||
{
|
{
|
||||||
UBaseType_t ux;
|
UBaseType_t ux;
|
||||||
|
|
||||||
/* If the semaphore count is at its maximum then we should not be able to
|
/* If the semaphore count is at its maximum then we should not be able to
|
||||||
'give' the semaphore. */
|
* 'give' the semaphore. */
|
||||||
if( xSemaphoreGive( xSemaphore ) == pdPASS )
|
if( xSemaphoreGive( xSemaphore ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -166,8 +169,9 @@ UBaseType_t ux;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the semaphore count is zero then we should not be able to 'take'
|
/* If the semaphore count is zero then we should not be able to 'take'
|
||||||
the semaphore. */
|
* the semaphore. */
|
||||||
configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
|
configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
|
||||||
|
|
||||||
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
|
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -175,12 +179,13 @@ UBaseType_t ux;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore, volatile UBaseType_t *puxLoopCounter )
|
static void prvIncrementSemaphoreCount( SemaphoreHandle_t xSemaphore,
|
||||||
|
volatile UBaseType_t * puxLoopCounter )
|
||||||
{
|
{
|
||||||
UBaseType_t ux;
|
UBaseType_t ux;
|
||||||
|
|
||||||
/* If the semaphore count is zero then we should not be able to 'take'
|
/* If the semaphore count is zero then we should not be able to 'take'
|
||||||
the semaphore. */
|
* the semaphore. */
|
||||||
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
|
if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -205,7 +210,7 @@ UBaseType_t ux;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the semaphore count is at its maximum then we should not be able to
|
/* If the semaphore count is at its maximum then we should not be able to
|
||||||
'give' the semaphore. */
|
* 'give' the semaphore. */
|
||||||
if( xSemaphoreGive( xSemaphore ) == pdPASS )
|
if( xSemaphoreGive( xSemaphore ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -230,14 +235,14 @@ xCountSemStruct *pxParameter;
|
||||||
pxParameter = ( xCountSemStruct * ) pvParameters;
|
pxParameter = ( xCountSemStruct * ) pvParameters;
|
||||||
|
|
||||||
/* Did we expect to find the semaphore already at its max count value, or
|
/* Did we expect to find the semaphore already at its max count value, or
|
||||||
at zero? */
|
* at zero? */
|
||||||
if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT )
|
if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT )
|
||||||
{
|
{
|
||||||
prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
|
prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we expect the semaphore count to be 0, so this time there is an
|
/* Now we expect the semaphore count to be 0, so this time there is an
|
||||||
error if we can take the semaphore. */
|
* error if we can take the semaphore. */
|
||||||
if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS )
|
if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorDetected = pdTRUE;
|
xErrorDetected = pdTRUE;
|
||||||
|
|
@ -257,7 +262,7 @@ static UBaseType_t uxLastCount0 = 0, uxLastCount1 = 0;
|
||||||
BaseType_t xReturn = pdPASS;
|
BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
/* Return fail if any 'give' or 'take' did not result in the expected
|
/* Return fail if any 'give' or 'take' did not result in the expected
|
||||||
behaviour. */
|
* behaviour. */
|
||||||
if( xErrorDetected != pdFALSE )
|
if( xErrorDetected != pdFALSE )
|
||||||
{
|
{
|
||||||
xReturn = pdFAIL;
|
xReturn = pdFAIL;
|
||||||
|
|
@ -284,5 +289,3 @@ BaseType_t xReturn = pdPASS;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
#include "crflash.h"
|
#include "crflash.h"
|
||||||
|
|
||||||
/* The queue should only need to be of length 1. See the description at the
|
/* The queue should only need to be of length 1. See the description at the
|
||||||
top of the file. */
|
* top of the file. */
|
||||||
#define crfQUEUE_LENGTH 1
|
#define crfQUEUE_LENGTH 1
|
||||||
|
|
||||||
#define crfFIXED_DELAY_PRIORITY 0
|
#define crfFIXED_DELAY_PRIORITY 0
|
||||||
|
|
@ -71,7 +71,7 @@ top of the file. */
|
||||||
#define crfFLASH_INDEX 0
|
#define crfFLASH_INDEX 0
|
||||||
|
|
||||||
/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be
|
/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be
|
||||||
created. */
|
* created. */
|
||||||
#define crfMAX_FLASH_TASKS 8
|
#define crfMAX_FLASH_TASKS 8
|
||||||
|
|
||||||
/* We don't want to block when posting to the queue. */
|
/* We don't want to block when posting to the queue. */
|
||||||
|
|
@ -80,15 +80,17 @@ created. */
|
||||||
/*
|
/*
|
||||||
* The 'fixed delay' co-routine as described at the top of the file.
|
* The 'fixed delay' co-routine as described at the top of the file.
|
||||||
*/
|
*/
|
||||||
static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
|
static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The 'flash' co-routine as described at the top of the file.
|
* The 'flash' co-routine as described at the top of the file.
|
||||||
*/
|
*/
|
||||||
static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
|
static void prvFlashCoRoutine( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex );
|
||||||
|
|
||||||
/* The queue used to pass data between the 'fixed delay' co-routines and the
|
/* The queue used to pass data between the 'fixed delay' co-routines and the
|
||||||
'flash' co-routine. */
|
* 'flash' co-routine. */
|
||||||
static QueueHandle_t xFlashQueue;
|
static QueueHandle_t xFlashQueue;
|
||||||
|
|
||||||
/* This will be set to pdFALSE if we detect an error. */
|
/* This will be set to pdFALSE if we detect an error. */
|
||||||
|
|
@ -125,21 +127,26 @@ UBaseType_t uxIndex;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
static void prvFixedDelayCoRoutine( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex )
|
||||||
{
|
{
|
||||||
/* Even though this is a co-routine the xResult variable does not need to be
|
/* Even though this is a co-routine the xResult variable does not need to be
|
||||||
static as we do not need it to maintain its state between blocks. */
|
* static as we do not need it to maintain its state between blocks. */
|
||||||
BaseType_t xResult;
|
BaseType_t xResult;
|
||||||
|
|
||||||
/* The uxIndex parameter of the co-routine function is used as an index into
|
/* The uxIndex parameter of the co-routine function is used as an index into
|
||||||
the xFlashRates array to obtain the delay period to use. */
|
* the xFlashRates array to obtain the delay period to use. */
|
||||||
static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PERIOD_MS,
|
static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] =
|
||||||
|
{
|
||||||
|
150 / portTICK_PERIOD_MS,
|
||||||
200 / portTICK_PERIOD_MS,
|
200 / portTICK_PERIOD_MS,
|
||||||
250 / portTICK_PERIOD_MS,
|
250 / portTICK_PERIOD_MS,
|
||||||
300 / portTICK_PERIOD_MS,
|
300 / portTICK_PERIOD_MS,
|
||||||
350 / portTICK_PERIOD_MS,
|
350 / portTICK_PERIOD_MS,
|
||||||
400 / portTICK_PERIOD_MS,
|
400 / portTICK_PERIOD_MS,
|
||||||
450 / portTICK_PERIOD_MS,
|
450 / portTICK_PERIOD_MS,
|
||||||
500 / portTICK_PERIOD_MS };
|
500 / portTICK_PERIOD_MS
|
||||||
|
};
|
||||||
|
|
||||||
/* Co-routines MUST start with a call to crSTART. */
|
/* Co-routines MUST start with a call to crSTART. */
|
||||||
crSTART( xHandle );
|
crSTART( xHandle );
|
||||||
|
|
@ -147,14 +154,14 @@ static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PER
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Post our uxIndex value onto the queue. This is used as the LED to
|
/* Post our uxIndex value onto the queue. This is used as the LED to
|
||||||
flash. */
|
* flash. */
|
||||||
crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult );
|
crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult );
|
||||||
|
|
||||||
if( xResult != pdPASS )
|
if( xResult != pdPASS )
|
||||||
{
|
{
|
||||||
/* For the reasons stated at the top of the file we should always
|
/* For the reasons stated at the top of the file we should always
|
||||||
find that we can post to the queue. If we could not then an error
|
* find that we can post to the queue. If we could not then an error
|
||||||
has occurred. */
|
* has occurred. */
|
||||||
xCoRoutineFlashStatus = pdFAIL;
|
xCoRoutineFlashStatus = pdFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,10 +173,11 @@ static const TickType_t xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_PER
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
static void prvFlashCoRoutine( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex )
|
||||||
{
|
{
|
||||||
/* Even though this is a co-routine the variable do not need to be
|
/* Even though this is a co-routine the variable do not need to be
|
||||||
static as we do not need it to maintain their state between blocks. */
|
* static as we do not need it to maintain their state between blocks. */
|
||||||
BaseType_t xResult;
|
BaseType_t xResult;
|
||||||
UBaseType_t uxLEDToFlash;
|
UBaseType_t uxLEDToFlash;
|
||||||
|
|
||||||
|
|
@ -202,7 +210,6 @@ UBaseType_t uxLEDToFlash;
|
||||||
BaseType_t xAreFlashCoRoutinesStillRunning( void )
|
BaseType_t xAreFlashCoRoutinesStillRunning( void )
|
||||||
{
|
{
|
||||||
/* Return pdPASS or pdFAIL depending on whether an error has been detected
|
/* Return pdPASS or pdFAIL depending on whether an error has been detected
|
||||||
or not. */
|
* or not. */
|
||||||
return xCoRoutineFlashStatus;
|
return xCoRoutineFlashStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
#define hookNUM_HOOK_CO_ROUTINES ( 4 )
|
#define hookNUM_HOOK_CO_ROUTINES ( 4 )
|
||||||
|
|
||||||
/* The number of times the tick hook should be called before a character is
|
/* The number of times the tick hook should be called before a character is
|
||||||
posted to the 'hook' co-routines. */
|
* posted to the 'hook' co-routines. */
|
||||||
#define hookTICK_CALLS_BEFORE_POST ( 500 )
|
#define hookTICK_CALLS_BEFORE_POST ( 500 )
|
||||||
|
|
||||||
/* There should never be more than one item in any queue at any time. */
|
/* There should never be more than one item in any queue at any time. */
|
||||||
|
|
@ -70,14 +70,15 @@ posted to the 'hook' co-routines. */
|
||||||
#define hookNO_BLOCK_TIME ( 0 )
|
#define hookNO_BLOCK_TIME ( 0 )
|
||||||
|
|
||||||
/* The priority relative to other co-routines (rather than tasks) that the
|
/* The priority relative to other co-routines (rather than tasks) that the
|
||||||
'hook' co-routines should take. */
|
* 'hook' co-routines should take. */
|
||||||
#define mainHOOK_CR_PRIORITY ( 1 )
|
#define mainHOOK_CR_PRIORITY ( 1 )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The co-routine function itself.
|
* The co-routine function itself.
|
||||||
*/
|
*/
|
||||||
static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex );
|
static void prvHookCoRoutine( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex );
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -90,13 +91,13 @@ void vApplicationTickHook( void );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Queues used to send data FROM a co-routine TO the tick hook function.
|
/* Queues used to send data FROM a co-routine TO the tick hook function.
|
||||||
The hook functions received (Rx's) on these queues. One queue per
|
* The hook functions received (Rx's) on these queues. One queue per
|
||||||
'hook' co-routine. */
|
* 'hook' co-routine. */
|
||||||
static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];
|
static QueueHandle_t xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ];
|
||||||
|
|
||||||
/* Queues used to send data FROM the tick hook TO a co-routine function.
|
/* Queues used to send data FROM the tick hook TO a co-routine function.
|
||||||
The hood function transmits (Tx's) on these queues. One queue per
|
* The hood function transmits (Tx's) on these queues. One queue per
|
||||||
'hook' co-routine. */
|
* 'hook' co-routine. */
|
||||||
static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];
|
static QueueHandle_t xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ];
|
||||||
|
|
||||||
/* Set to true if an error is detected at any time. */
|
/* Set to true if an error is detected at any time. */
|
||||||
|
|
@ -111,12 +112,12 @@ UBaseType_t uxIndex, uxValueToPost = 0;
|
||||||
for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )
|
for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ )
|
||||||
{
|
{
|
||||||
/* Create a queue to transmit to and receive from each 'hook'
|
/* Create a queue to transmit to and receive from each 'hook'
|
||||||
co-routine. */
|
* co-routine. */
|
||||||
xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
|
xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
|
||||||
xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
|
xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( UBaseType_t ) );
|
||||||
|
|
||||||
/* To start things off the tick hook function expects the queue it
|
/* To start things off the tick hook function expects the queue it
|
||||||
uses to receive data to contain a value. */
|
* uses to receive data to contain a value. */
|
||||||
xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );
|
xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME );
|
||||||
|
|
||||||
/* Create the 'hook' co-routine itself. */
|
/* Create the 'hook' co-routine itself. */
|
||||||
|
|
@ -133,6 +134,7 @@ BaseType_t xIndex, xCoRoutineWoken;
|
||||||
|
|
||||||
/* Is it time to talk to the 'hook' co-routines again? */
|
/* Is it time to talk to the 'hook' co-routines again? */
|
||||||
uxCallCounter++;
|
uxCallCounter++;
|
||||||
|
|
||||||
if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )
|
if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST )
|
||||||
{
|
{
|
||||||
uxCallCounter = 0;
|
uxCallCounter = 0;
|
||||||
|
|
@ -140,16 +142,17 @@ BaseType_t xIndex, xCoRoutineWoken;
|
||||||
for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )
|
for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ )
|
||||||
{
|
{
|
||||||
xCoRoutineWoken = pdFALSE;
|
xCoRoutineWoken = pdFALSE;
|
||||||
|
|
||||||
if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )
|
if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS )
|
||||||
{
|
{
|
||||||
/* There is no reason why we would not expect the queue to
|
/* There is no reason why we would not expect the queue to
|
||||||
contain a value. */
|
* contain a value. */
|
||||||
xCoRoutineErrorDetected = pdTRUE;
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Each queue used to receive data from the 'hook' co-routines
|
/* Each queue used to receive data from the 'hook' co-routines
|
||||||
should contain the number we last posted to the same co-routine. */
|
* should contain the number we last posted to the same co-routine. */
|
||||||
if( uxReceivedNumber != uxNumberToPost )
|
if( uxReceivedNumber != uxNumberToPost )
|
||||||
{
|
{
|
||||||
xCoRoutineErrorDetected = pdTRUE;
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
|
@ -171,7 +174,7 @@ BaseType_t xIndex, xCoRoutineWoken;
|
||||||
if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )
|
if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE )
|
||||||
{
|
{
|
||||||
/* Posting to the queue should have woken the co-routine that
|
/* Posting to the queue should have woken the co-routine that
|
||||||
was blocked on the queue. */
|
* was blocked on the queue. */
|
||||||
xCoRoutineErrorDetected = pdTRUE;
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +182,8 @@ BaseType_t xIndex, xCoRoutineWoken;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvHookCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
static void prvHookCoRoutine( CoRoutineHandle_t xHandle,
|
||||||
|
UBaseType_t uxIndex )
|
||||||
{
|
{
|
||||||
static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];
|
static UBaseType_t uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ];
|
||||||
BaseType_t xResult;
|
BaseType_t xResult;
|
||||||
|
|
@ -194,7 +198,7 @@ BaseType_t xResult;
|
||||||
crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );
|
crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult );
|
||||||
|
|
||||||
/* There is no reason why we should not have received something on
|
/* There is no reason why we should not have received something on
|
||||||
the queue. */
|
* the queue. */
|
||||||
if( xResult != pdPASS )
|
if( xResult != pdPASS )
|
||||||
{
|
{
|
||||||
xCoRoutineErrorDetected = pdTRUE;
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
|
|
@ -203,10 +207,11 @@ BaseType_t xResult;
|
||||||
/* Send the same number back to the idle hook so it can verify it. */
|
/* Send the same number back to the idle hook so it can verify it. */
|
||||||
xResult = pdFAIL;
|
xResult = pdFAIL;
|
||||||
crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );
|
crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult );
|
||||||
|
|
||||||
if( xResult != pdPASS )
|
if( xResult != pdPASS )
|
||||||
{
|
{
|
||||||
/* There is no reason why we should not have been able to post to
|
/* There is no reason why we should not have been able to post to
|
||||||
the queue. */
|
* the queue. */
|
||||||
xCoRoutineErrorDetected = pdTRUE;
|
xCoRoutineErrorDetected = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -227,6 +232,3 @@ BaseType_t xAreHookCoRoutinesStillRunning( void )
|
||||||
return pdTRUE;
|
return pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,30 +57,30 @@
|
||||||
#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 )
|
#define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 )
|
||||||
|
|
||||||
/* The task originally created which is responsible for periodically dynamically
|
/* The task originally created which is responsible for periodically dynamically
|
||||||
creating another four tasks. */
|
* creating another four tasks. */
|
||||||
static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters );
|
||||||
|
|
||||||
/* The task function of the dynamically created tasks. */
|
/* The task function of the dynamically created tasks. */
|
||||||
static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters );
|
static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters );
|
||||||
|
|
||||||
/* A variable which is incremented every time the dynamic tasks are created. This
|
/* A variable which is incremented every time the dynamic tasks are created. This
|
||||||
is used to check that the task is still running. */
|
* is used to check that the task is still running. */
|
||||||
static volatile uint16_t usCreationCount = 0;
|
static volatile uint16_t usCreationCount = 0;
|
||||||
|
|
||||||
/* Used to store the number of tasks that were originally running so the creator
|
/* Used to store the number of tasks that were originally running so the creator
|
||||||
task can tell if any of the suicidal tasks have failed to die.
|
* task can tell if any of the suicidal tasks have failed to die.
|
||||||
*/
|
*/
|
||||||
static volatile UBaseType_t uxTasksRunningAtStart = 0;
|
static volatile UBaseType_t uxTasksRunningAtStart = 0;
|
||||||
|
|
||||||
/* When a task deletes itself, it stack and TCB are cleaned up by the Idle task.
|
/* When a task deletes itself, it stack and TCB are cleaned up by the Idle task.
|
||||||
Under heavy load the idle task might not get much processing time, so it would
|
* Under heavy load the idle task might not get much processing time, so it would
|
||||||
be legitimate for several tasks to remain undeleted for a short period. There
|
* be legitimate for several tasks to remain undeleted for a short period. There
|
||||||
may also be a few other unexpected tasks if, for example, the tasks that test
|
* may also be a few other unexpected tasks if, for example, the tasks that test
|
||||||
static allocation are also being used. */
|
* static allocation are also being used. */
|
||||||
static const UBaseType_t uxMaxNumberOfExtraTasksRunning = 3;
|
static const UBaseType_t uxMaxNumberOfExtraTasksRunning = 3;
|
||||||
|
|
||||||
/* Used to store a handle to the task that should be killed by a suicidal task,
|
/* Used to store a handle to the task that should be killed by a suicidal task,
|
||||||
before it kills itself. */
|
* before it kills itself. */
|
||||||
TaskHandle_t xCreatedTask;
|
TaskHandle_t xCreatedTask;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -103,8 +103,8 @@ const TickType_t xDelay = pdMS_TO_TICKS( ( TickType_t ) 200 );
|
||||||
if( pvParameters != NULL )
|
if( pvParameters != NULL )
|
||||||
{
|
{
|
||||||
/* This task is periodically created four times. Two created tasks are
|
/* This task is periodically created four times. Two created tasks are
|
||||||
passed a handle to the other task so it can kill it before killing itself.
|
* passed a handle to the other task so it can kill it before killing itself.
|
||||||
The other task is passed in null. */
|
* The other task is passed in null. */
|
||||||
xTaskToKill = *( TaskHandle_t * ) pvParameters;
|
xTaskToKill = *( TaskHandle_t * ) pvParameters;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -144,7 +144,7 @@ UBaseType_t uxPriority;
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
/* Delay at the start to ensure tasks created by other demos have been
|
/* Delay at the start to ensure tasks created by other demos have been
|
||||||
created before storing the current number of tasks. */
|
* created before storing the current number of tasks. */
|
||||||
vTaskDelay( xDelay );
|
vTaskDelay( xDelay );
|
||||||
uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks();
|
uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks();
|
||||||
|
|
||||||
|
|
@ -166,7 +166,7 @@ UBaseType_t uxPriority;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* This is called to check that the creator task is still running and that there
|
/* This is called to check that the creator task is still running and that there
|
||||||
are not any more than four extra tasks. */
|
* are not any more than four extra tasks. */
|
||||||
BaseType_t xIsCreateTaskStillRunning( void )
|
BaseType_t xIsCreateTaskStillRunning( void )
|
||||||
{
|
{
|
||||||
static uint16_t usLastCreationCount = 0xfff;
|
static uint16_t usLastCreationCount = 0xfff;
|
||||||
|
|
@ -199,5 +199,3 @@ static UBaseType_t uxTasksRunningNow;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,17 +118,17 @@ static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Handles to the two counter tasks. These could be passed in as parameters
|
/* Handles to the two counter tasks. These could be passed in as parameters
|
||||||
to the controller task to prevent them having to be file scope. */
|
* to the controller task to prevent them having to be file scope. */
|
||||||
static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle;
|
static TaskHandle_t xContinuousIncrementHandle, xLimitedIncrementHandle;
|
||||||
|
|
||||||
/* The shared counter variable. This is passed in as a parameter to the two
|
/* The shared counter variable. This is passed in as a parameter to the two
|
||||||
counter variables for demonstration purposes. */
|
* counter variables for demonstration purposes. */
|
||||||
static uint32_t ulCounter;
|
static uint32_t ulCounter;
|
||||||
|
|
||||||
/* Variables used to check that the tasks are still operating without error.
|
/* Variables used to check that the tasks are still operating without error.
|
||||||
Each complete iteration of the controller task increments this variable
|
* Each complete iteration of the controller task increments this variable
|
||||||
provided no errors have been found. The variable maintaining the same value
|
* provided no errors have been found. The variable maintaining the same value
|
||||||
is therefore indication of an error. */
|
* is therefore indication of an error. */
|
||||||
static volatile uint16_t usCheckVariable = ( uint16_t ) 0;
|
static volatile uint16_t usCheckVariable = ( uint16_t ) 0;
|
||||||
static volatile BaseType_t xSuspendedQueueSendError = pdFALSE;
|
static volatile BaseType_t xSuspendedQueueSendError = pdFALSE;
|
||||||
static volatile BaseType_t xSuspendedQueueReceiveError = pdFALSE;
|
static volatile BaseType_t xSuspendedQueueReceiveError = pdFALSE;
|
||||||
|
|
@ -137,11 +137,12 @@ static volatile BaseType_t xSuspendedQueueReceiveError = pdFALSE;
|
||||||
QueueHandle_t xSuspendedTestQueue;
|
QueueHandle_t xSuspendedTestQueue;
|
||||||
|
|
||||||
/* The value the queue receive task expects to receive next. This is file
|
/* The value the queue receive task expects to receive next. This is file
|
||||||
scope so xAreDynamicPriorityTasksStillRunning() can ensure it is still
|
* scope so xAreDynamicPriorityTasksStillRunning() can ensure it is still
|
||||||
incrementing. */
|
* incrementing. */
|
||||||
static uint32_t ulExpectedValue = ( uint32_t ) 0;
|
static uint32_t ulExpectedValue = ( uint32_t ) 0;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the three tasks as described at the top of the file.
|
* Start the three tasks as described at the top of the file.
|
||||||
* Note that the limited count task is given a higher priority.
|
* Note that the limited count task is given a higher priority.
|
||||||
|
|
@ -153,11 +154,11 @@ void vStartDynamicPriorityTasks( void )
|
||||||
if( xSuspendedTestQueue != NULL )
|
if( xSuspendedTestQueue != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
|
||||||
in use. The queue registry is provided as a means for kernel aware
|
* in use. The queue registry is provided as a means for kernel aware
|
||||||
debuggers to locate queues and has no purpose if a kernel aware debugger
|
* debuggers to locate queues and has no purpose if a kernel aware debugger
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
* is not being used. The call to vQueueAddToRegistry() will be removed
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
* by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
||||||
defined to be less than 1. */
|
* defined to be less than 1. */
|
||||||
vQueueAddToRegistry( xSuspendedTestQueue, "Suspended_Test_Queue" );
|
vQueueAddToRegistry( xSuspendedTestQueue, "Suspended_Test_Queue" );
|
||||||
|
|
||||||
xTaskCreate( vContinuousIncrementTask, "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle );
|
xTaskCreate( vContinuousIncrementTask, "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle );
|
||||||
|
|
@ -178,11 +179,11 @@ static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters )
|
||||||
volatile uint32_t * pulCounter;
|
volatile uint32_t * pulCounter;
|
||||||
|
|
||||||
/* Take a pointer to the shared variable from the parameters passed into
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
the task. */
|
* the task. */
|
||||||
pulCounter = ( volatile uint32_t * ) pvParameters;
|
pulCounter = ( volatile uint32_t * ) pvParameters;
|
||||||
|
|
||||||
/* This will run before the control task, so the first thing it does is
|
/* This will run before the control task, so the first thing it does is
|
||||||
suspend - the control task will resume it when ready. */
|
* suspend - the control task will resume it when ready. */
|
||||||
vTaskSuspend( NULL );
|
vTaskSuspend( NULL );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
|
|
@ -208,17 +209,17 @@ volatile uint32_t *pulCounter;
|
||||||
UBaseType_t uxOurPriority;
|
UBaseType_t uxOurPriority;
|
||||||
|
|
||||||
/* Take a pointer to the shared variable from the parameters passed into
|
/* Take a pointer to the shared variable from the parameters passed into
|
||||||
the task. */
|
* the task. */
|
||||||
pulCounter = ( volatile uint32_t * ) pvParameters;
|
pulCounter = ( volatile uint32_t * ) pvParameters;
|
||||||
|
|
||||||
/* Query our priority so we can raise it when exclusive access to the
|
/* Query our priority so we can raise it when exclusive access to the
|
||||||
shared variable is required. */
|
* shared variable is required. */
|
||||||
uxOurPriority = uxTaskPriorityGet( NULL );
|
uxOurPriority = uxTaskPriorityGet( NULL );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Raise the priority above the controller task to ensure a context
|
/* Raise the priority above the controller task to ensure a context
|
||||||
switch does not occur while the variable is being accessed. */
|
* switch does not occur while the variable is being accessed. */
|
||||||
vTaskPrioritySet( NULL, uxOurPriority + 1 );
|
vTaskPrioritySet( NULL, uxOurPriority + 1 );
|
||||||
{
|
{
|
||||||
configASSERT( ( uxTaskPriorityGet( NULL ) == ( uxOurPriority + 1 ) ) );
|
configASSERT( ( uxTaskPriorityGet( NULL ) == ( uxOurPriority + 1 ) ) );
|
||||||
|
|
@ -258,9 +259,9 @@ short sError = pdFALSE;
|
||||||
for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
|
for( sLoops = 0; sLoops < priLOOPS; sLoops++ )
|
||||||
{
|
{
|
||||||
/* Suspend the continuous count task so we can take a mirror of the
|
/* Suspend the continuous count task so we can take a mirror of the
|
||||||
shared variable without risk of corruption. This is not really
|
* shared variable without risk of corruption. This is not really
|
||||||
needed as the other task raises its priority above this task's
|
* needed as the other task raises its priority above this task's
|
||||||
priority. */
|
* priority. */
|
||||||
vTaskSuspend( xContinuousIncrementHandle );
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
{
|
{
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
|
|
@ -287,14 +288,14 @@ short sError = pdFALSE;
|
||||||
vTaskDelay( priSLEEP_TIME );
|
vTaskDelay( priSLEEP_TIME );
|
||||||
|
|
||||||
/* Check the shared variable again. This time to ensure mutual
|
/* Check the shared variable again. This time to ensure mutual
|
||||||
exclusion the whole scheduler will be locked. This is just for
|
* exclusion the whole scheduler will be locked. This is just for
|
||||||
demo purposes! */
|
* demo purposes! */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
if( ulLastCounter == ulCounter )
|
if( ulLastCounter == ulCounter )
|
||||||
{
|
{
|
||||||
/* The shared variable has not changed. There is a problem
|
/* The shared variable has not changed. There is a problem
|
||||||
with the continuous count task so flag an error. */
|
* with the continuous count task so flag an error. */
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -304,7 +305,7 @@ short sError = pdFALSE;
|
||||||
/* Second section: */
|
/* Second section: */
|
||||||
|
|
||||||
/* Suspend the continuous counter task so it stops accessing the shared
|
/* Suspend the continuous counter task so it stops accessing the shared
|
||||||
variable. */
|
* variable. */
|
||||||
vTaskSuspend( xContinuousIncrementHandle );
|
vTaskSuspend( xContinuousIncrementHandle );
|
||||||
|
|
||||||
/* Reset the variable. */
|
/* Reset the variable. */
|
||||||
|
|
@ -317,8 +318,8 @@ short sError = pdFALSE;
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
/* Resume the limited count task which has a higher priority than us.
|
/* Resume the limited count task which has a higher priority than us.
|
||||||
We should therefore not return from this call until the limited count
|
* We should therefore not return from this call until the limited count
|
||||||
task has suspended itself with a known value in the counter variable. */
|
* task has suspended itself with a known value in the counter variable. */
|
||||||
vTaskResume( xLimitedIncrementHandle );
|
vTaskResume( xLimitedIncrementHandle );
|
||||||
|
|
||||||
#if ( configUSE_PREEMPTION == 0 )
|
#if ( configUSE_PREEMPTION == 0 )
|
||||||
|
|
@ -326,7 +327,7 @@ short sError = pdFALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This task should not run again until xLimitedIncrementHandle has
|
/* This task should not run again until xLimitedIncrementHandle has
|
||||||
suspended itself. */
|
* suspended itself. */
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended );
|
configASSERT( eTaskGetState( xLimitedIncrementHandle ) == eSuspended );
|
||||||
|
|
@ -396,16 +397,17 @@ BaseType_t xGotValue;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Suspending the scheduler here is fairly pointless and
|
/* Suspending the scheduler here is fairly pointless and
|
||||||
undesirable for a normal application. It is done here purely
|
* undesirable for a normal application. It is done here purely
|
||||||
to test the scheduler. The inner xTaskResumeAll() should
|
* to test the scheduler. The inner xTaskResumeAll() should
|
||||||
never return pdTRUE as the scheduler is still locked by the
|
* never return pdTRUE as the scheduler is still locked by the
|
||||||
outer call. */
|
* outer call. */
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
vTaskSuspendAll();
|
vTaskSuspendAll();
|
||||||
{
|
{
|
||||||
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
|
xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xTaskResumeAll() != pdFALSE )
|
if( xTaskResumeAll() != pdFALSE )
|
||||||
{
|
{
|
||||||
xSuspendedQueueReceiveError = pdTRUE;
|
xSuspendedQueueReceiveError = pdTRUE;
|
||||||
|
|
@ -418,7 +420,6 @@ BaseType_t xGotValue;
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} while( xGotValue == pdFALSE );
|
} while( xGotValue == pdFALSE );
|
||||||
|
|
||||||
if( ulReceivedValue != ulExpectedValue )
|
if( ulReceivedValue != ulExpectedValue )
|
||||||
|
|
@ -429,8 +430,8 @@ BaseType_t xGotValue;
|
||||||
if( xSuspendedQueueReceiveError != pdTRUE )
|
if( xSuspendedQueueReceiveError != pdTRUE )
|
||||||
{
|
{
|
||||||
/* Only increment the variable if an error has not occurred. This
|
/* Only increment the variable if an error has not occurred. This
|
||||||
allows xAreDynamicPriorityTasksStillRunning() to check for stalled
|
* allows xAreDynamicPriorityTasksStillRunning() to check for stalled
|
||||||
tasks as well as explicit errors. */
|
* tasks as well as explicit errors. */
|
||||||
++ulExpectedValue;
|
++ulExpectedValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -441,13 +442,13 @@ BaseType_t xGotValue;
|
||||||
BaseType_t xAreDynamicPriorityTasksStillRunning( void )
|
BaseType_t xAreDynamicPriorityTasksStillRunning( void )
|
||||||
{
|
{
|
||||||
/* Keep a history of the check variables so we know if it has been incremented
|
/* Keep a history of the check variables so we know if it has been incremented
|
||||||
since the last call. */
|
* since the last call. */
|
||||||
static uint16_t usLastTaskCheck = ( uint16_t ) 0;
|
static uint16_t usLastTaskCheck = ( uint16_t ) 0;
|
||||||
static uint32_t ulLastExpectedValue = ( uint32_t ) 0U;
|
static uint32_t ulLastExpectedValue = ( uint32_t ) 0U;
|
||||||
BaseType_t xReturn = pdTRUE;
|
BaseType_t xReturn = pdTRUE;
|
||||||
|
|
||||||
/* Check the tasks are still running by ensuring the check variable
|
/* Check the tasks are still running by ensuring the check variable
|
||||||
is still incrementing. */
|
* is still incrementing. */
|
||||||
|
|
||||||
if( usCheckVariable == usLastTaskCheck )
|
if( usCheckVariable == usLastTaskCheck )
|
||||||
{
|
{
|
||||||
|
|
@ -458,7 +459,7 @@ BaseType_t xReturn = pdTRUE;
|
||||||
if( ulExpectedValue == ulLastExpectedValue )
|
if( ulExpectedValue == ulLastExpectedValue )
|
||||||
{
|
{
|
||||||
/* The value being received by the queue receive task has not
|
/* The value being received by the queue receive task has not
|
||||||
incremented so an error exists. */
|
* incremented so an error exists. */
|
||||||
xReturn = pdFALSE;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
#define ledFLASH_RATE_BASE ( ( TickType_t ) 333 )
|
#define ledFLASH_RATE_BASE ( ( TickType_t ) 333 )
|
||||||
|
|
||||||
/* Variable used by the created tasks to calculate the LED number to use, and
|
/* Variable used by the created tasks to calculate the LED number to use, and
|
||||||
the rate at which they should flash the LED. */
|
* the rate at which they should flash the LED. */
|
||||||
static volatile UBaseType_t uxFlashTaskNumber = 0;
|
static volatile UBaseType_t uxFlashTaskNumber = 0;
|
||||||
|
|
||||||
/* The task that is created three times. */
|
/* The task that is created three times. */
|
||||||
|
|
@ -98,11 +98,11 @@ UBaseType_t uxLED;
|
||||||
xFlashRate /= portTICK_PERIOD_MS;
|
xFlashRate /= portTICK_PERIOD_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
|
||||||
delay is only half the total period. */
|
* delay is only half the total period. */
|
||||||
xFlashRate /= ( TickType_t ) 2;
|
xFlashRate /= ( TickType_t ) 2;
|
||||||
|
|
||||||
/* We need to initialise xLastFlashTime prior to the first call to
|
/* We need to initialise xLastFlashTime prior to the first call to
|
||||||
vTaskDelayUntil(). */
|
* vTaskDelayUntil(). */
|
||||||
xLastFlashTime = xTaskGetTickCount();
|
xLastFlashTime = xTaskGetTickCount();
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
|
|
@ -116,4 +116,3 @@ UBaseType_t uxLED;
|
||||||
vParTestToggleLED( uxLED );
|
vParTestToggleLED( uxLED );
|
||||||
}
|
}
|
||||||
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */
|
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,10 +72,10 @@ TimerHandle_t xTimer;
|
||||||
);
|
);
|
||||||
|
|
||||||
/* If the timer was created successfully, attempt to start it. If the
|
/* If the timer was created successfully, attempt to start it. If the
|
||||||
scheduler has not yet been started then the timer command queue must
|
* scheduler has not yet been started then the timer command queue must
|
||||||
be long enough to hold each command sent to it until such time that the
|
* be long enough to hold each command sent to it until such time that the
|
||||||
scheduler is started. The timer command queue length is set by
|
* scheduler is started. The timer command queue length is set by
|
||||||
configTIMER_QUEUE_LENGTH in FreeRTOSConfig.h. */
|
* configTIMER_QUEUE_LENGTH in FreeRTOSConfig.h. */
|
||||||
if( xTimer != NULL )
|
if( xTimer != NULL )
|
||||||
{
|
{
|
||||||
xTimerStart( xTimer, ledDONT_BLOCK );
|
xTimerStart( xTimer, ledDONT_BLOCK );
|
||||||
|
|
@ -89,10 +89,8 @@ static void prvLEDTimerCallback( TimerHandle_t xTimer )
|
||||||
BaseType_t xTimerID;
|
BaseType_t xTimerID;
|
||||||
|
|
||||||
/* The timer ID is used to identify the timer that has actually expired as
|
/* The timer ID is used to identify the timer that has actually expired as
|
||||||
each timer uses the same callback. The ID is then also used as the number
|
* each timer uses the same callback. The ID is then also used as the number
|
||||||
of the LED that is to be toggled. */
|
* of the LED that is to be toggled. */
|
||||||
xTimerID = ( BaseType_t ) pvTimerGetTimerID( xTimer );
|
xTimerID = ( BaseType_t ) pvTimerGetTimerID( xTimer );
|
||||||
vParTestToggleLED( xTimerID );
|
vParTestToggleLED( xTimerID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,14 +56,14 @@
|
||||||
#define mathNUMBER_OF_TASKS ( 4 )
|
#define mathNUMBER_OF_TASKS ( 4 )
|
||||||
|
|
||||||
/* Four tasks, each of which performs a different floating point calculation.
|
/* Four tasks, each of which performs a different floating point calculation.
|
||||||
Each of the four is created twice. */
|
* Each of the four is created twice. */
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
|
||||||
|
|
||||||
/* These variables are used to check that all the tasks are still running. If a
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
task gets a calculation wrong it will stop setting its check variable. */
|
* task gets a calculation wrong it will stop setting its check variable. */
|
||||||
static uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
static uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -85,8 +85,8 @@ volatile portDOUBLE dAnswer;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
|
|
||||||
/* Some ports require that tasks that use a hardware floating point unit
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
tell the kernel that they require a floating point context before any
|
* tell the kernel that they require a floating point context before any
|
||||||
floating point instructions are executed. */
|
* floating point instructions are executed. */
|
||||||
portTASK_USES_FLOATING_POINT();
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
d1 = 123.4567;
|
d1 = 123.4567;
|
||||||
|
|
@ -96,7 +96,7 @@ short sError = pdFALSE;
|
||||||
dAnswer = ( d1 + d2 ) * d3;
|
dAnswer = ( d1 + d2 ) * d3;
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -113,7 +113,7 @@ short sError = pdFALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( fabs( d4 - dAnswer ) > 0.001 )
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -122,15 +122,14 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct then set set the check
|
/* If the calculation has always been correct then set set the check
|
||||||
variable. The check variable will get set to pdFALSE each time
|
* variable. The check variable will get set to pdFALSE each time
|
||||||
xAreMathsTaskStillRunning() is executed. */
|
* xAreMathsTaskStillRunning() is executed. */
|
||||||
( *pusTaskCheckVariable ) = pdTRUE;
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
#if configUSE_PREEMPTION == 0
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -143,8 +142,8 @@ volatile portDOUBLE dAnswer;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
|
|
||||||
/* Some ports require that tasks that use a hardware floating point unit
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
tell the kernel that they require a floating point context before any
|
* tell the kernel that they require a floating point context before any
|
||||||
floating point instructions are executed. */
|
* floating point instructions are executed. */
|
||||||
portTASK_USES_FLOATING_POINT();
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
d1 = -389.38;
|
d1 = -389.38;
|
||||||
|
|
@ -155,7 +154,7 @@ short sError = pdFALSE;
|
||||||
|
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -172,7 +171,7 @@ short sError = pdFALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( fabs( d4 - dAnswer ) > 0.001 )
|
if( fabs( d4 - dAnswer ) > 0.001 )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -181,8 +180,8 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct then set set the check
|
/* If the calculation has always been correct then set set the check
|
||||||
variable. The check variable will get set to pdFALSE each time
|
* variable. The check variable will get set to pdFALSE each time
|
||||||
xAreMathsTaskStillRunning() is executed. */
|
* xAreMathsTaskStillRunning() is executed. */
|
||||||
( *pusTaskCheckVariable ) = pdTRUE;
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,19 +201,19 @@ size_t xPosition;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
|
|
||||||
/* Some ports require that tasks that use a hardware floating point unit
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
tell the kernel that they require a floating point context before any
|
* tell the kernel that they require a floating point context before any
|
||||||
floating point instructions are executed. */
|
* floating point instructions are executed. */
|
||||||
portTASK_USES_FLOATING_POINT();
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
||||||
|
|
||||||
pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
|
pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
/* Keep filling an array, keeping a running total of the values placed in the
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
dTotal1 = 0.0;
|
dTotal1 = 0.0;
|
||||||
|
|
@ -236,6 +235,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dDifference = dTotal1 - dTotal2;
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
|
||||||
if( fabs( dDifference ) > 0.001 )
|
if( fabs( dDifference ) > 0.001 )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -248,8 +248,8 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct then set set the check
|
/* If the calculation has always been correct then set set the check
|
||||||
variable. The check variable will get set to pdFALSE each time
|
* variable. The check variable will get set to pdFALSE each time
|
||||||
xAreMathsTaskStillRunning() is executed. */
|
* xAreMathsTaskStillRunning() is executed. */
|
||||||
( *pusTaskCheckVariable ) = pdTRUE;
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,19 +265,19 @@ size_t xPosition;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
|
|
||||||
/* Some ports require that tasks that use a hardware floating point unit
|
/* Some ports require that tasks that use a hardware floating point unit
|
||||||
tell the kernel that they require a floating point context before any
|
* tell the kernel that they require a floating point context before any
|
||||||
floating point instructions are executed. */
|
* floating point instructions are executed. */
|
||||||
portTASK_USES_FLOATING_POINT();
|
portTASK_USES_FLOATING_POINT();
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( volatile uint16_t * ) pvParameters;
|
||||||
|
|
||||||
pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
|
pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) );
|
||||||
|
|
||||||
/* Keep filling an array, keeping a running total of the values placed in the
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
dTotal1 = 0.0;
|
dTotal1 = 0.0;
|
||||||
|
|
@ -299,6 +299,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dDifference = dTotal1 - dTotal2;
|
dDifference = dTotal1 - dTotal2;
|
||||||
|
|
||||||
if( fabs( dDifference ) > 0.001 )
|
if( fabs( dDifference ) > 0.001 )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -311,8 +312,8 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct then set set the check
|
/* If the calculation has always been correct then set set the check
|
||||||
variable. The check variable will get set to pdFALSE each time
|
* variable. The check variable will get set to pdFALSE each time
|
||||||
xAreMathsTaskStillRunning() is executed. */
|
* xAreMathsTaskStillRunning() is executed. */
|
||||||
( *pusTaskCheckVariable ) = pdTRUE;
|
( *pusTaskCheckVariable ) = pdTRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -325,25 +326,22 @@ BaseType_t xAreMathsTaskStillRunning( void )
|
||||||
BaseType_t xReturn = pdPASS, xTask;
|
BaseType_t xReturn = pdPASS, xTask;
|
||||||
|
|
||||||
/* Check the maths tasks are still running by ensuring their check variables
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
have been set to pdPASS. */
|
* have been set to pdPASS. */
|
||||||
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
||||||
{
|
{
|
||||||
if( usTaskCheck[ xTask ] != pdTRUE )
|
if( usTaskCheck[ xTask ] != pdTRUE )
|
||||||
{
|
{
|
||||||
/* The check has not been set so the associated task has either
|
/* The check has not been set so the associated task has either
|
||||||
stalled or detected an error. */
|
* stalled or detected an error. */
|
||||||
xReturn = pdFAIL;
|
xReturn = pdFAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Reset the variable so it can be checked again the next time this
|
/* Reset the variable so it can be checked again the next time this
|
||||||
function is executed. */
|
* function is executed. */
|
||||||
usTaskCheck[ xTask ] = pdFALSE;
|
usTaskCheck[ xTask ] = pdFALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,14 @@
|
||||||
#define intgNUMBER_OF_TASKS ( 1 )
|
#define intgNUMBER_OF_TASKS ( 1 )
|
||||||
|
|
||||||
/* The task function. Repeatedly performs a 32 bit calculation, checking the
|
/* The task function. Repeatedly performs a 32 bit calculation, checking the
|
||||||
result against the expected result. If the result is incorrect then the
|
* result against the expected result. If the result is incorrect then the
|
||||||
context switch must have caused some corruption. */
|
* context switch must have caused some corruption. */
|
||||||
static portTASK_FUNCTION_PROTO( vCompeteingIntMathTask, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompeteingIntMathTask, pvParameters );
|
||||||
|
|
||||||
/* Variables that are set to true within the calculation task to indicate
|
/* Variables that are set to true within the calculation task to indicate
|
||||||
that the task is still executing. The check task sets the variable back to
|
* that the task is still executing. The check task sets the variable back to
|
||||||
false, flagging an error if the variable is still false the next time it
|
* false, flagging an error if the variable is still false the next time it
|
||||||
is called. */
|
* is called. */
|
||||||
static BaseType_t xTaskCheck[ intgNUMBER_OF_TASKS ] = { ( BaseType_t ) pdFALSE };
|
static BaseType_t xTaskCheck[ intgNUMBER_OF_TASKS ] = { ( BaseType_t ) pdFALSE };
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -80,21 +80,21 @@ short sTask;
|
||||||
static portTASK_FUNCTION( vCompeteingIntMathTask, pvParameters )
|
static portTASK_FUNCTION( vCompeteingIntMathTask, pvParameters )
|
||||||
{
|
{
|
||||||
/* These variables are all effectively set to constants so they are volatile to
|
/* These variables are all effectively set to constants so they are volatile to
|
||||||
ensure the compiler does not just get rid of them. */
|
* ensure the compiler does not just get rid of them. */
|
||||||
volatile long lValue;
|
volatile long lValue;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
volatile BaseType_t * pxTaskHasExecuted;
|
volatile BaseType_t * pxTaskHasExecuted;
|
||||||
|
|
||||||
/* Set a pointer to the variable we are going to set to true each
|
/* Set a pointer to the variable we are going to set to true each
|
||||||
iteration. This is also a good test of the parameter passing mechanism
|
* iteration. This is also a good test of the parameter passing mechanism
|
||||||
within each port. */
|
* within each port. */
|
||||||
pxTaskHasExecuted = ( volatile BaseType_t * ) pvParameters;
|
pxTaskHasExecuted = ( volatile BaseType_t * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Perform the calculation. This will store partial value in
|
/* Perform the calculation. This will store partial value in
|
||||||
registers, resulting in a good test of the context switch mechanism. */
|
* registers, resulting in a good test of the context switch mechanism. */
|
||||||
lValue = intgCONST1;
|
lValue = intgCONST1;
|
||||||
lValue += intgCONST2;
|
lValue += intgCONST2;
|
||||||
|
|
||||||
|
|
@ -110,8 +110,8 @@ volatile BaseType_t *pxTaskHasExecuted;
|
||||||
lValue /= intgCONST4;
|
lValue /= intgCONST4;
|
||||||
|
|
||||||
/* If the calculation is found to be incorrect we stop setting the
|
/* If the calculation is found to be incorrect we stop setting the
|
||||||
TaskHasExecuted variable so the check task can see an error has
|
* TaskHasExecuted variable so the check task can see an error has
|
||||||
occurred. */
|
* occurred. */
|
||||||
if( lValue != intgEXPECTED_ANSWER ) /*lint !e774 volatile used to prevent this being optimised out. */
|
if( lValue != intgEXPECTED_ANSWER ) /*lint !e774 volatile used to prevent this being optimised out. */
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -120,8 +120,8 @@ volatile BaseType_t *pxTaskHasExecuted;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* We have not encountered any errors, so set the flag that show
|
/* We have not encountered any errors, so set the flag that show
|
||||||
we are still executing. This will be periodically cleared by
|
* we are still executing. This will be periodically cleared by
|
||||||
the check task. */
|
* the check task. */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
*pxTaskHasExecuted = pdTRUE;
|
*pxTaskHasExecuted = pdTRUE;
|
||||||
portEXIT_CRITICAL();
|
portEXIT_CRITICAL();
|
||||||
|
|
@ -144,7 +144,7 @@ BaseType_t xReturn = pdTRUE;
|
||||||
short sTask;
|
short sTask;
|
||||||
|
|
||||||
/* Check the maths tasks are still running by ensuring their check variables
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
are still being set to true. */
|
* are still being set to true. */
|
||||||
for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ )
|
for( sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++ )
|
||||||
{
|
{
|
||||||
if( xTaskCheck[ sTask ] == pdFALSE )
|
if( xTaskCheck[ sTask ] == pdFALSE )
|
||||||
|
|
@ -154,10 +154,9 @@ short sTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the check variable so we can tell if it has been set by
|
/* Reset the check variable so we can tell if it has been set by
|
||||||
the next time around. */
|
* the next time around. */
|
||||||
xTaskCheck[ sTask ] = pdFALSE;
|
xTaskCheck[ sTask ] = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,39 +26,39 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The tasks defined on this page demonstrate the use of recursive mutexes.
|
* The tasks defined on this page demonstrate the use of recursive mutexes.
|
||||||
|
*
|
||||||
For recursive mutex functionality the created mutex should be created using
|
* For recursive mutex functionality the created mutex should be created using
|
||||||
xSemaphoreCreateRecursiveMutex(), then be manipulated
|
* xSemaphoreCreateRecursiveMutex(), then be manipulated
|
||||||
using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API
|
* using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API
|
||||||
functions.
|
* functions.
|
||||||
|
*
|
||||||
This demo creates three tasks all of which access the same recursive mutex:
|
* This demo creates three tasks all of which access the same recursive mutex:
|
||||||
|
*
|
||||||
prvRecursiveMutexControllingTask() has the highest priority so executes
|
* prvRecursiveMutexControllingTask() has the highest priority so executes
|
||||||
first and grabs the mutex. It then performs some recursive accesses -
|
* first and grabs the mutex. It then performs some recursive accesses -
|
||||||
between each of which it sleeps for a short period to let the lower
|
* between each of which it sleeps for a short period to let the lower
|
||||||
priority tasks execute. When it has completed its demo functionality
|
* priority tasks execute. When it has completed its demo functionality
|
||||||
it gives the mutex back before suspending itself.
|
* it gives the mutex back before suspending itself.
|
||||||
|
*
|
||||||
prvRecursiveMutexBlockingTask() attempts to access the mutex by performing
|
* prvRecursiveMutexBlockingTask() attempts to access the mutex by performing
|
||||||
a blocking 'take'. The blocking task has a lower priority than the
|
* a blocking 'take'. The blocking task has a lower priority than the
|
||||||
controlling task so by the time it executes the mutex has already been
|
* controlling task so by the time it executes the mutex has already been
|
||||||
taken by the controlling task, causing the blocking task to block. It
|
* taken by the controlling task, causing the blocking task to block. It
|
||||||
does not unblock until the controlling task has given the mutex back,
|
* does not unblock until the controlling task has given the mutex back,
|
||||||
and it does not actually run until the controlling task has suspended
|
* and it does not actually run until the controlling task has suspended
|
||||||
itself (due to the relative priorities). When it eventually does obtain
|
* itself (due to the relative priorities). When it eventually does obtain
|
||||||
the mutex all it does is give the mutex back prior to also suspending
|
* the mutex all it does is give the mutex back prior to also suspending
|
||||||
itself. At this point both the controlling task and the blocking task are
|
* itself. At this point both the controlling task and the blocking task are
|
||||||
suspended.
|
* suspended.
|
||||||
|
*
|
||||||
prvRecursiveMutexPollingTask() runs at the idle priority. It spins round
|
* prvRecursiveMutexPollingTask() runs at the idle priority. It spins round
|
||||||
a tight loop attempting to obtain the mutex with a non-blocking call. As
|
* a tight loop attempting to obtain the mutex with a non-blocking call. As
|
||||||
the lowest priority task it will not successfully obtain the mutex until
|
* the lowest priority task it will not successfully obtain the mutex until
|
||||||
both the controlling and blocking tasks are suspended. Once it eventually
|
* both the controlling and blocking tasks are suspended. Once it eventually
|
||||||
does obtain the mutex it first unsuspends both the controlling task and
|
* does obtain the mutex it first unsuspends both the controlling task and
|
||||||
blocking task prior to giving the mutex back - resulting in the polling
|
* blocking task prior to giving the mutex back - resulting in the polling
|
||||||
task temporarily inheriting the controlling tasks priority.
|
* task temporarily inheriting the controlling tasks priority.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Scheduler include files. */
|
/* Scheduler include files. */
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
#include "recmutex.h"
|
#include "recmutex.h"
|
||||||
|
|
||||||
/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can
|
/* Priorities assigned to the three tasks. recmuCONTROLLING_TASK_PRIORITY can
|
||||||
be overridden by a definition in FreeRTOSConfig.h. */
|
* be overridden by a definition in FreeRTOSConfig.h. */
|
||||||
#ifndef recmuCONTROLLING_TASK_PRIORITY
|
#ifndef recmuCONTROLLING_TASK_PRIORITY
|
||||||
#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -102,7 +102,7 @@ static volatile BaseType_t xErrorOccurred = pdFALSE, xControllingIsSuspended = p
|
||||||
static volatile UBaseType_t uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0;
|
static volatile UBaseType_t uxControllingCycles = 0, uxBlockingCycles = 0, uxPollingCycles = 0;
|
||||||
|
|
||||||
/* Handles of the two higher priority tasks, required so they can be resumed
|
/* Handles of the two higher priority tasks, required so they can be resumed
|
||||||
(unsuspended). */
|
* (unsuspended). */
|
||||||
static TaskHandle_t xControllingTaskHandle, xBlockingTaskHandle;
|
static TaskHandle_t xControllingTaskHandle, xBlockingTaskHandle;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -116,11 +116,11 @@ void vStartRecursiveMutexTasks( void )
|
||||||
if( xMutex != NULL )
|
if( xMutex != NULL )
|
||||||
{
|
{
|
||||||
/* vQueueAddToRegistry() adds the mutex to the registry, if one is
|
/* vQueueAddToRegistry() adds the mutex to the registry, if one is
|
||||||
in use. The registry is provided as a means for kernel aware
|
* in use. The registry is provided as a means for kernel aware
|
||||||
debuggers to locate mutex and has no purpose if a kernel aware debugger
|
* debuggers to locate mutex and has no purpose if a kernel aware debugger
|
||||||
is not being used. The call to vQueueAddToRegistry() will be removed
|
* is not being used. The call to vQueueAddToRegistry() will be removed
|
||||||
by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
* by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
|
||||||
defined to be less than 1. */
|
* defined to be less than 1. */
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Recursive_Mutex" );
|
vQueueAddToRegistry( ( QueueHandle_t ) xMutex, "Recursive_Mutex" );
|
||||||
|
|
||||||
xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", recmuRECURSIVE_MUTEX_TEST_TASK_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );
|
xTaskCreate( prvRecursiveMutexControllingTask, "Rec1", recmuRECURSIVE_MUTEX_TEST_TASK_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle );
|
||||||
|
|
@ -140,9 +140,9 @@ UBaseType_t ux;
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Should not be able to 'give' the mutex, as we have not yet 'taken'
|
/* Should not be able to 'give' the mutex, as we have not yet 'taken'
|
||||||
it. The first time through, the mutex will not have been used yet,
|
* it. The first time through, the mutex will not have been used yet,
|
||||||
subsequent times through, at this point the mutex will be held by the
|
* subsequent times through, at this point the mutex will be held by the
|
||||||
polling task. */
|
* polling task. */
|
||||||
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
|
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -151,24 +151,24 @@ UBaseType_t ux;
|
||||||
for( ux = 0; ux < recmuMAX_COUNT; ux++ )
|
for( ux = 0; ux < recmuMAX_COUNT; ux++ )
|
||||||
{
|
{
|
||||||
/* We should now be able to take the mutex as many times as
|
/* We should now be able to take the mutex as many times as
|
||||||
we like.
|
* we like.
|
||||||
|
*
|
||||||
The first time through the mutex will be immediately available, on
|
* The first time through the mutex will be immediately available, on
|
||||||
subsequent times through the mutex will be held by the polling task
|
* subsequent times through the mutex will be held by the polling task
|
||||||
at this point and this Take will cause the polling task to inherit
|
* at this point and this Take will cause the polling task to inherit
|
||||||
the priority of this task. In this case the block time must be
|
* the priority of this task. In this case the block time must be
|
||||||
long enough to ensure the polling task will execute again before the
|
* long enough to ensure the polling task will execute again before the
|
||||||
block time expires. If the block time does expire then the error
|
* block time expires. If the block time does expire then the error
|
||||||
flag will be set here. */
|
* flag will be set here. */
|
||||||
if( xSemaphoreTakeRecursive( xMutex, recmu15ms_DELAY ) != pdPASS )
|
if( xSemaphoreTakeRecursive( xMutex, recmu15ms_DELAY ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the other task attempting to access the mutex (and the
|
/* Ensure the other task attempting to access the mutex (and the
|
||||||
other demo tasks) are able to execute to ensure they either block
|
* other demo tasks) are able to execute to ensure they either block
|
||||||
(where a block time is specified) or return an error (where no
|
* (where a block time is specified) or return an error (where no
|
||||||
block time is specified) as the mutex is held by this task. */
|
* block time is specified) as the mutex is held by this task. */
|
||||||
vTaskDelay( recmuSHORT_DELAY );
|
vTaskDelay( recmuSHORT_DELAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,14 +176,14 @@ UBaseType_t ux;
|
||||||
for( ux = 0; ux < recmuMAX_COUNT; ux++ )
|
for( ux = 0; ux < recmuMAX_COUNT; ux++ )
|
||||||
{
|
{
|
||||||
/* Ensure the other task attempting to access the mutex (and the
|
/* Ensure the other task attempting to access the mutex (and the
|
||||||
other demo tasks) are able to execute. */
|
* other demo tasks) are able to execute. */
|
||||||
vTaskDelay( recmuSHORT_DELAY );
|
vTaskDelay( recmuSHORT_DELAY );
|
||||||
|
|
||||||
/* We should now be able to give the mutex as many times as we
|
/* We should now be able to give the mutex as many times as we
|
||||||
took it. When the mutex is available again the Blocking task
|
* took it. When the mutex is available again the Blocking task
|
||||||
should be unblocked but not run because it has a lower priority
|
* should be unblocked but not run because it has a lower priority
|
||||||
than this task. The polling task should also not run at this point
|
* than this task. The polling task should also not run at this point
|
||||||
as it too has a lower priority than this task. */
|
* as it too has a lower priority than this task. */
|
||||||
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -195,14 +195,14 @@ UBaseType_t ux;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Having given it back the same number of times as it was taken, we
|
/* Having given it back the same number of times as it was taken, we
|
||||||
should no longer be the mutex owner, so the next give should fail. */
|
* should no longer be the mutex owner, so the next give should fail. */
|
||||||
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
|
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep count of the number of cycles this task has performed so a
|
/* Keep count of the number of cycles this task has performed so a
|
||||||
stall can be detected. */
|
* stall can be detected. */
|
||||||
uxControllingCycles++;
|
uxControllingCycles++;
|
||||||
|
|
||||||
/* Suspend ourselves so the blocking task can execute. */
|
/* Suspend ourselves so the blocking task can execute. */
|
||||||
|
|
@ -221,24 +221,24 @@ static void prvRecursiveMutexBlockingTask( void *pvParameters )
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* This task will run while the controlling task is blocked, and the
|
/* This task will run while the controlling task is blocked, and the
|
||||||
controlling task will block only once it has the mutex - therefore
|
* controlling task will block only once it has the mutex - therefore
|
||||||
this call should block until the controlling task has given up the
|
* this call should block until the controlling task has given up the
|
||||||
mutex, and not actually execute past this call until the controlling
|
* mutex, and not actually execute past this call until the controlling
|
||||||
task is suspended. portMAX_DELAY - 1 is used instead of portMAX_DELAY
|
* task is suspended. portMAX_DELAY - 1 is used instead of portMAX_DELAY
|
||||||
to ensure the task's state is reported as Blocked and not Suspended in
|
* to ensure the task's state is reported as Blocked and not Suspended in
|
||||||
a later call to configASSERT() (within the polling task). */
|
* a later call to configASSERT() (within the polling task). */
|
||||||
if( xSemaphoreTakeRecursive( xMutex, ( portMAX_DELAY - 1 ) ) == pdPASS )
|
if( xSemaphoreTakeRecursive( xMutex, ( portMAX_DELAY - 1 ) ) == pdPASS )
|
||||||
{
|
{
|
||||||
if( xControllingIsSuspended != pdTRUE )
|
if( xControllingIsSuspended != pdTRUE )
|
||||||
{
|
{
|
||||||
/* Did not expect to execute until the controlling task was
|
/* Did not expect to execute until the controlling task was
|
||||||
suspended. */
|
* suspended. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Give the mutex back before suspending ourselves to allow
|
/* Give the mutex back before suspending ourselves to allow
|
||||||
the polling task to obtain the mutex. */
|
* the polling task to obtain the mutex. */
|
||||||
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -252,7 +252,7 @@ static void prvRecursiveMutexBlockingTask( void *pvParameters )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We should not leave the xSemaphoreTakeRecursive() function
|
/* We should not leave the xSemaphoreTakeRecursive() function
|
||||||
until the mutex was obtained. */
|
* until the mutex was obtained. */
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,7 +263,7 @@ static void prvRecursiveMutexBlockingTask( void *pvParameters )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep count of the number of cycles this task has performed so a
|
/* Keep count of the number of cycles this task has performed so a
|
||||||
stall can be detected. */
|
* stall can be detected. */
|
||||||
uxBlockingCycles++;
|
uxBlockingCycles++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -277,8 +277,8 @@ static void prvRecursiveMutexPollingTask( void *pvParameters )
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
/* Keep attempting to obtain the mutex. It should only be obtained when
|
/* Keep attempting to obtain the mutex. It should only be obtained when
|
||||||
the blocking task has suspended itself, which in turn should only
|
* the blocking task has suspended itself, which in turn should only
|
||||||
happen when the controlling task is also suspended. */
|
* happen when the controlling task is also suspended. */
|
||||||
if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )
|
if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )
|
||||||
{
|
{
|
||||||
#if ( INCLUDE_eTaskGetState == 1 )
|
#if ( INCLUDE_eTaskGetState == 1 )
|
||||||
|
|
@ -296,18 +296,18 @@ static void prvRecursiveMutexPollingTask( void *pvParameters )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Keep count of the number of cycles this task has performed
|
/* Keep count of the number of cycles this task has performed
|
||||||
so a stall can be detected. */
|
* so a stall can be detected. */
|
||||||
uxPollingCycles++;
|
uxPollingCycles++;
|
||||||
|
|
||||||
/* We can resume the other tasks here even though they have a
|
/* We can resume the other tasks here even though they have a
|
||||||
higher priority than the polling task. When they execute they
|
* higher priority than the polling task. When they execute they
|
||||||
will attempt to obtain the mutex but fail because the polling
|
* will attempt to obtain the mutex but fail because the polling
|
||||||
task is still the mutex holder. The polling task (this task)
|
* task is still the mutex holder. The polling task (this task)
|
||||||
will then inherit the higher priority. The Blocking task will
|
* will then inherit the higher priority. The Blocking task will
|
||||||
block indefinitely when it attempts to obtain the mutex, the
|
* block indefinitely when it attempts to obtain the mutex, the
|
||||||
Controlling task will only block for a fixed period and an
|
* Controlling task will only block for a fixed period and an
|
||||||
error will be latched if the polling task has not returned the
|
* error will be latched if the polling task has not returned the
|
||||||
mutex by the time this fixed period has expired. */
|
* mutex by the time this fixed period has expired. */
|
||||||
vTaskResume( xBlockingTaskHandle );
|
vTaskResume( xBlockingTaskHandle );
|
||||||
#if ( configUSE_PREEMPTION == 0 )
|
#if ( configUSE_PREEMPTION == 0 )
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
|
|
@ -319,7 +319,7 @@ static void prvRecursiveMutexPollingTask( void *pvParameters )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The other two tasks should now have executed and no longer
|
/* The other two tasks should now have executed and no longer
|
||||||
be suspended. */
|
* be suspended. */
|
||||||
if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) )
|
if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) )
|
||||||
{
|
{
|
||||||
xErrorOccurred = pdTRUE;
|
xErrorOccurred = pdTRUE;
|
||||||
|
|
@ -410,7 +410,3 @@ static UBaseType_t uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLast
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,18 +117,19 @@ const TickType_t xBlockTime = ( TickType_t ) 100;
|
||||||
xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL );
|
xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( TaskHandle_t * ) NULL );
|
||||||
|
|
||||||
/* vQueueAddToRegistry() adds the semaphore to the registry, if one
|
/* vQueueAddToRegistry() adds the semaphore to the registry, if one
|
||||||
is in use. The registry is provided as a means for kernel aware
|
* is in use. The registry is provided as a means for kernel aware
|
||||||
debuggers to locate semaphores and has no purpose if a kernel aware
|
* debuggers to locate semaphores and has no purpose if a kernel aware
|
||||||
debugger is not being used. The call to vQueueAddToRegistry() will
|
* debugger is not being used. The call to vQueueAddToRegistry() will
|
||||||
be removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
* be removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
||||||
defined or is defined to be less than 1. */
|
* defined or is defined to be less than 1. */
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) pxFirstSemaphoreParameters->xSemaphore, "Counting_Sem_1" );
|
vQueueAddToRegistry( ( QueueHandle_t ) pxFirstSemaphoreParameters->xSemaphore, "Counting_Sem_1" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do exactly the same to create the second set of tasks, only this time
|
/* Do exactly the same to create the second set of tasks, only this time
|
||||||
provide a block time for the semaphore calls. */
|
* provide a block time for the semaphore calls. */
|
||||||
pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) );
|
||||||
|
|
||||||
if( pxSecondSemaphoreParameters != NULL )
|
if( pxSecondSemaphoreParameters != NULL )
|
||||||
{
|
{
|
||||||
pxSecondSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary();
|
pxSecondSemaphoreParameters->xSemaphore = xSemaphoreCreateBinary();
|
||||||
|
|
@ -145,11 +146,11 @@ const TickType_t xBlockTime = ( TickType_t ) 100;
|
||||||
xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( TaskHandle_t * ) NULL );
|
||||||
|
|
||||||
/* vQueueAddToRegistry() adds the semaphore to the registry, if one
|
/* vQueueAddToRegistry() adds the semaphore to the registry, if one
|
||||||
is in use. The registry is provided as a means for kernel aware
|
* is in use. The registry is provided as a means for kernel aware
|
||||||
debuggers to locate semaphores and has no purpose if a kernel aware
|
* debuggers to locate semaphores and has no purpose if a kernel aware
|
||||||
debugger is not being used. The call to vQueueAddToRegistry() will
|
* debugger is not being used. The call to vQueueAddToRegistry() will
|
||||||
be removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
* be removed by the pre-processor if configQUEUE_REGISTRY_SIZE is not
|
||||||
defined or is defined to be less than 1. */
|
* defined or is defined to be less than 1. */
|
||||||
vQueueAddToRegistry( ( QueueHandle_t ) pxSecondSemaphoreParameters->xSemaphore, "Counting_Sem_2" );
|
vQueueAddToRegistry( ( QueueHandle_t ) pxSecondSemaphoreParameters->xSemaphore, "Counting_Sem_2" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -164,19 +165,19 @@ uint32_t ulCounter;
|
||||||
short sError = pdFALSE, sCheckVariableToUse;
|
short sError = pdFALSE, sCheckVariableToUse;
|
||||||
|
|
||||||
/* See which check variable to use. sNextCheckVariable is not semaphore
|
/* See which check variable to use. sNextCheckVariable is not semaphore
|
||||||
protected! */
|
* protected! */
|
||||||
portENTER_CRITICAL();
|
portENTER_CRITICAL();
|
||||||
sCheckVariableToUse = sNextCheckVariable;
|
sCheckVariableToUse = sNextCheckVariable;
|
||||||
sNextCheckVariable++;
|
sNextCheckVariable++;
|
||||||
portEXIT_CRITICAL();
|
portEXIT_CRITICAL();
|
||||||
|
|
||||||
/* A structure is passed in as the parameter. This contains the shared
|
/* A structure is passed in as the parameter. This contains the shared
|
||||||
variable being guarded. */
|
* variable being guarded. */
|
||||||
pxParameters = ( xSemaphoreParameters * ) pvParameters;
|
pxParameters = ( xSemaphoreParameters * ) pvParameters;
|
||||||
pulSharedVariable = pxParameters->pulSharedVariable;
|
pulSharedVariable = pxParameters->pulSharedVariable;
|
||||||
|
|
||||||
/* If we are blocking we use a much higher count to ensure loads of context
|
/* If we are blocking we use a much higher count to ensure loads of context
|
||||||
switches occur during the count. */
|
* switches occur during the count. */
|
||||||
if( pxParameters->xBlockTime > ( TickType_t ) 0 )
|
if( pxParameters->xBlockTime > ( TickType_t ) 0 )
|
||||||
{
|
{
|
||||||
ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
|
ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
|
||||||
|
|
@ -192,19 +193,20 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
|
if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS )
|
||||||
{
|
{
|
||||||
/* We have the semaphore and so expect any other tasks using the
|
/* We have the semaphore and so expect any other tasks using the
|
||||||
shared variable to have left it in the state we expect to find
|
* shared variable to have left it in the state we expect to find
|
||||||
it. */
|
* it. */
|
||||||
if( *pulSharedVariable != ulExpectedValue )
|
if( *pulSharedVariable != ulExpectedValue )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the variable, then count it back up to the expected value
|
/* Clear the variable, then count it back up to the expected value
|
||||||
before releasing the semaphore. Would expect a context switch or
|
* before releasing the semaphore. Would expect a context switch or
|
||||||
two during this time. */
|
* two during this time. */
|
||||||
for( ulCounter = ( uint32_t ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
|
for( ulCounter = ( uint32_t ) 0; ulCounter <= ulExpectedValue; ulCounter++ )
|
||||||
{
|
{
|
||||||
*pulSharedVariable = ulCounter;
|
*pulSharedVariable = ulCounter;
|
||||||
|
|
||||||
if( *pulSharedVariable != ulCounter )
|
if( *pulSharedVariable != ulCounter )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -212,7 +214,7 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the semaphore, and if no errors have occurred increment the check
|
/* Release the semaphore, and if no errors have occurred increment the check
|
||||||
variable. */
|
* variable. */
|
||||||
if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
|
if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -227,23 +229,22 @@ short sError = pdFALSE, sCheckVariableToUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have a block time then we are running at a priority higher
|
/* If we have a block time then we are running at a priority higher
|
||||||
than the idle priority. This task takes a long time to complete
|
* than the idle priority. This task takes a long time to complete
|
||||||
a cycle (deliberately so to test the guarding) so will be starving
|
* a cycle (deliberately so to test the guarding) so will be starving
|
||||||
out lower priority tasks. Block for some time to allow give lower
|
* out lower priority tasks. Block for some time to allow give lower
|
||||||
priority tasks some processor time. */
|
* priority tasks some processor time. */
|
||||||
if( pxParameters->xBlockTime != ( TickType_t ) 0 )
|
if( pxParameters->xBlockTime != ( TickType_t ) 0 )
|
||||||
{
|
{
|
||||||
vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
|
vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( pxParameters->xBlockTime == ( TickType_t ) 0 )
|
if( pxParameters->xBlockTime == ( TickType_t ) 0 )
|
||||||
{
|
{
|
||||||
/* We have not got the semaphore yet, so no point using the
|
/* We have not got the semaphore yet, so no point using the
|
||||||
processor. We are not blocking when attempting to obtain the
|
* processor. We are not blocking when attempting to obtain the
|
||||||
semaphore. */
|
* semaphore. */
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -269,4 +270,3 @@ BaseType_t xTask, xReturn = pdTRUE;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,15 +52,15 @@
|
||||||
#define mathNUMBER_OF_TASKS ( 8 )
|
#define mathNUMBER_OF_TASKS ( 8 )
|
||||||
|
|
||||||
/* Four tasks, each of which performs a different floating point calculation.
|
/* Four tasks, each of which performs a different floating point calculation.
|
||||||
Each of the four is created twice. */
|
* Each of the four is created twice. */
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters );
|
||||||
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
|
static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters );
|
||||||
|
|
||||||
/* These variables are used to check that all the tasks are still running. If a
|
/* These variables are used to check that all the tasks are still running. If a
|
||||||
task gets a calculation wrong it will
|
* task gets a calculation wrong it will
|
||||||
stop incrementing its check variable. */
|
* stop incrementing its check variable. */
|
||||||
static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
static volatile uint16_t usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -92,7 +92,7 @@ short sError = pdFALSE;
|
||||||
fAnswer = ( f1 + f2 ) * f3;
|
fAnswer = ( f1 + f2 ) * f3;
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -109,7 +109,7 @@ short sError = pdFALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( fabs( f4 - fAnswer ) > 0.001F )
|
if( fabs( f4 - fAnswer ) > 0.001F )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -118,14 +118,13 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if configUSE_PREEMPTION == 0
|
#if configUSE_PREEMPTION == 0
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
@ -145,7 +144,7 @@ short sError = pdFALSE;
|
||||||
|
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
/* Keep performing a calculation and checking the result against a constant. */
|
/* Keep performing a calculation and checking the result against a constant. */
|
||||||
|
|
@ -162,7 +161,7 @@ short sError = pdFALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the calculation does not match the expected constant, stop the
|
/* If the calculation does not match the expected constant, stop the
|
||||||
increment of the check variable. */
|
* increment of the check variable. */
|
||||||
if( fabs( f4 - fAnswer ) > 0.001F )
|
if( fabs( f4 - fAnswer ) > 0.001F )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -171,8 +170,8 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know
|
* variable so we know
|
||||||
this task is still running okay. */
|
* this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,14 +191,14 @@ size_t xPosition;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );
|
pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );
|
||||||
|
|
||||||
/* Keep filling an array, keeping a running total of the values placed in the
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
fTotal1 = 0.0F;
|
fTotal1 = 0.0F;
|
||||||
|
|
@ -222,6 +221,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fDifference = fTotal1 - fTotal2;
|
fDifference = fTotal1 - fTotal2;
|
||||||
|
|
||||||
if( fabs( fDifference ) > 0.001F )
|
if( fabs( fDifference ) > 0.001F )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -234,7 +234,7 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -250,14 +250,14 @@ size_t xPosition;
|
||||||
short sError = pdFALSE;
|
short sError = pdFALSE;
|
||||||
|
|
||||||
/* The variable this task increments to show it is still running is passed in
|
/* The variable this task increments to show it is still running is passed in
|
||||||
as the parameter. */
|
* as the parameter. */
|
||||||
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
pusTaskCheckVariable = ( uint16_t * ) pvParameters;
|
||||||
|
|
||||||
pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );
|
pfArray = ( float * ) pvPortMalloc( xArraySize * sizeof( float ) );
|
||||||
|
|
||||||
/* Keep filling an array, keeping a running total of the values placed in the
|
/* Keep filling an array, keeping a running total of the values placed in the
|
||||||
array. Then run through the array adding up all the values. If the two totals
|
* array. Then run through the array adding up all the values. If the two totals
|
||||||
do not match, stop the check variable from incrementing. */
|
* do not match, stop the check variable from incrementing. */
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
fTotal1 = 0.0F;
|
fTotal1 = 0.0F;
|
||||||
|
|
@ -280,6 +280,7 @@ short sError = pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fDifference = fTotal1 - fTotal2;
|
fDifference = fTotal1 - fTotal2;
|
||||||
|
|
||||||
if( fabs( fDifference ) > 0.001F )
|
if( fabs( fDifference ) > 0.001F )
|
||||||
{
|
{
|
||||||
sError = pdTRUE;
|
sError = pdTRUE;
|
||||||
|
|
@ -292,7 +293,7 @@ short sError = pdFALSE;
|
||||||
if( sError == pdFALSE )
|
if( sError == pdFALSE )
|
||||||
{
|
{
|
||||||
/* If the calculation has always been correct, increment the check
|
/* If the calculation has always been correct, increment the check
|
||||||
variable so we know this task is still running okay. */
|
* variable so we know this task is still running okay. */
|
||||||
( *pusTaskCheckVariable )++;
|
( *pusTaskCheckVariable )++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -303,12 +304,12 @@ short sError = pdFALSE;
|
||||||
BaseType_t xAreMathsTaskStillRunning( void )
|
BaseType_t xAreMathsTaskStillRunning( void )
|
||||||
{
|
{
|
||||||
/* Keep a history of the check variables so we know if they have been incremented
|
/* Keep a history of the check variables so we know if they have been incremented
|
||||||
since the last call. */
|
* since the last call. */
|
||||||
static uint16_t usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
static uint16_t usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( uint16_t ) 0 };
|
||||||
BaseType_t xReturn = pdTRUE, xTask;
|
BaseType_t xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
/* Check the maths tasks are still running by ensuring their check variables
|
/* Check the maths tasks are still running by ensuring their check variables
|
||||||
are still incrementing. */
|
* are still incrementing. */
|
||||||
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ )
|
||||||
{
|
{
|
||||||
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] )
|
||||||
|
|
@ -322,6 +323,3 @@ BaseType_t xReturn = pdTRUE, xTask;
|
||||||
|
|
||||||
return xReturn;
|
return xReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vCreateAbortDelayTasks( void );
|
||||||
BaseType_t xAreAbortDelayTestTasksStillRunning( void );
|
BaseType_t xAreAbortDelayTestTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vStartBlockingQueueTasks( UBaseType_t uxPriority );
|
||||||
BaseType_t xAreBlockingQueuesStillRunning( void );
|
BaseType_t xAreBlockingQueuesStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,3 @@ BaseType_t xAreEventGroupTasksStillRunning( void );
|
||||||
void vPeriodicEventGroupsProcessing( void );
|
void vPeriodicEventGroupsProcessing( void );
|
||||||
|
|
||||||
#endif /* EVENT_GROUPS_DEMO_H */
|
#endif /* EVENT_GROUPS_DEMO_H */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ BaseType_t xAreGenericQueueTasksStillRunning( void );
|
||||||
void vMutexISRInteractionTest( void );
|
void vMutexISRInteractionTest( void );
|
||||||
|
|
||||||
#endif /* GEN_Q_TEST_H */
|
#endif /* GEN_Q_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,3 @@ BaseType_t xFirstTimerHandler( void );
|
||||||
BaseType_t xSecondTimerHandler( void );
|
BaseType_t xSecondTimerHandler( void );
|
||||||
|
|
||||||
#endif /* QUEUE_ACCESS_TEST */
|
#endif /* QUEUE_ACCESS_TEST */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ BaseType_t xAreInterruptSemaphoreTasksStillRunning( void );
|
||||||
void vInterruptSemaphorePeriodicTest( void );
|
void vInterruptSemaphorePeriodicTest( void );
|
||||||
|
|
||||||
#endif /* INT_SEM_TEST_H */
|
#endif /* INT_SEM_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,3 @@ void vStartMessageBufferTasks( configSTACK_DEPTH_TYPE xStackSize );
|
||||||
BaseType_t xAreMessageBufferTasksStillRunning( void );
|
BaseType_t xAreMessageBufferTasksStillRunning( void );
|
||||||
|
|
||||||
#endif /* MESSAGE_BUFFER_TEST_H */
|
#endif /* MESSAGE_BUFFER_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vStartPolledQueueTasks( UBaseType_t uxPriority );
|
||||||
BaseType_t xArePollingQueuesStillRunning( void );
|
BaseType_t xArePollingQueuesStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,3 @@ void vStartQueuePeekTasks( void );
|
||||||
BaseType_t xAreQueuePeekTasksStillRunning( void );
|
BaseType_t xAreQueuePeekTasksStillRunning( void );
|
||||||
|
|
||||||
#endif /* Q_PEEK_TEST_H */
|
#endif /* Q_PEEK_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,3 @@ BaseType_t xIsQueueOverwriteTaskStillRunning( void );
|
||||||
void vQueueOverwritePeriodicISRDemo( void );
|
void vQueueOverwritePeriodicISRDemo( void );
|
||||||
|
|
||||||
#endif /* QUEUE_OVERWRITE_H */
|
#endif /* QUEUE_OVERWRITE_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,3 @@ BaseType_t xAreQueueSetTasksStillRunning( void );
|
||||||
void vQueueSetAccessQueueSetFromISR( void );
|
void vQueueSetAccessQueueSetFromISR( void );
|
||||||
|
|
||||||
#endif /* QUEUE_WAIT_MULTIPLE_H */
|
#endif /* QUEUE_WAIT_MULTIPLE_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,3 @@ BaseType_t xAreQueueSetPollTasksStillRunning( void );
|
||||||
void vQueueSetPollingInterruptAccess( void );
|
void vQueueSetPollingInterruptAccess( void );
|
||||||
|
|
||||||
#endif /* QUEUE_SET_POLLING_H */
|
#endif /* QUEUE_SET_POLLING_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,3 @@ void vStartStaticallyAllocatedTasks( void );
|
||||||
BaseType_t xAreStaticAllocationTasksStillRunning( void );
|
BaseType_t xAreStaticAllocationTasksStillRunning( void );
|
||||||
|
|
||||||
#endif /* STATIC_ALLOCATION_H */
|
#endif /* STATIC_ALLOCATION_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ BaseType_t xAreStreamBufferTasksStillRunning( void );
|
||||||
void vPeriodicStreamBufferProcessing( void );
|
void vPeriodicStreamBufferProcessing( void );
|
||||||
|
|
||||||
#endif /* STREAM_BUFFER_TEST_H */
|
#endif /* STREAM_BUFFER_TEST_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ BaseType_t xAreTaskNotificationTasksStillRunning( void );
|
||||||
void xNotifyTaskFromISR( void );
|
void xNotifyTaskFromISR( void );
|
||||||
|
|
||||||
#endif /* TASK_NOTIFY_H */
|
#endif /* TASK_NOTIFY_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ BaseType_t xAreTaskNotificationArrayTasksStillRunning( void );
|
||||||
void xNotifyArrayTaskFromISR( void );
|
void xNotifyArrayTaskFromISR( void );
|
||||||
|
|
||||||
#endif /* TASK_NOTIFY_ARRAY_H */
|
#endif /* TASK_NOTIFY_ARRAY_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,3 @@ void vTimerPeriodicISRTests( void );
|
||||||
void vTimerDemoIncludeBacklogTests( BaseType_t includeBacklogTests );
|
void vTimerDemoIncludeBacklogTests( BaseType_t includeBacklogTests );
|
||||||
|
|
||||||
#endif /* TIMER_DEMO_H */
|
#endif /* TIMER_DEMO_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vCreateBlockTimeTasks( void );
|
||||||
BaseType_t xAreBlockTimeTestTasksStillRunning( void );
|
BaseType_t xAreBlockTimeTestTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,13 @@
|
||||||
#ifndef COMTEST_H
|
#ifndef COMTEST_H
|
||||||
#define COMTEST_H
|
#define COMTEST_H
|
||||||
|
|
||||||
void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED );
|
void vAltStartComTestTasks( UBaseType_t uxPriority,
|
||||||
void vStartComTestTasks( UBaseType_t uxPriority, eCOMPort ePort, eBaud eBaudRate );
|
uint32_t ulBaudRate,
|
||||||
|
UBaseType_t uxLED );
|
||||||
|
void vStartComTestTasks( UBaseType_t uxPriority,
|
||||||
|
eCOMPort ePort,
|
||||||
|
eBaud eBaudRate );
|
||||||
BaseType_t xAreComTestTasksStillRunning( void );
|
BaseType_t xAreComTestTasksStillRunning( void );
|
||||||
void vComTestUnsuspendTask( void );
|
void vComTestUnsuspendTask( void );
|
||||||
|
|
||||||
#endif
|
#endif /* ifndef COMTEST_H */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@
|
||||||
#ifndef COMTEST_H
|
#ifndef COMTEST_H
|
||||||
#define COMTEST_H
|
#define COMTEST_H
|
||||||
|
|
||||||
void vAltStartComTestTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED );
|
void vAltStartComTestTasks( UBaseType_t uxPriority,
|
||||||
|
uint32_t ulBaudRate,
|
||||||
|
UBaseType_t uxLED );
|
||||||
BaseType_t xAreComTestTasksStillRunning( void );
|
BaseType_t xAreComTestTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@
|
||||||
#ifndef COMTEST_STRINGS_H
|
#ifndef COMTEST_STRINGS_H
|
||||||
#define COMTEST_STRINGS_H
|
#define COMTEST_STRINGS_H
|
||||||
|
|
||||||
void vStartComTestStringsTasks( UBaseType_t uxPriority, uint32_t ulBaudRate, UBaseType_t uxLED );
|
void vStartComTestStringsTasks( UBaseType_t uxPriority,
|
||||||
|
uint32_t ulBaudRate,
|
||||||
|
UBaseType_t uxLED );
|
||||||
BaseType_t xAreComTestTasksStillRunning( void );
|
BaseType_t xAreComTestTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,3 @@ void vStartCountingSemaphoreTasks( void );
|
||||||
BaseType_t xAreCountingSemaphoreTasksStillRunning( void );
|
BaseType_t xAreCountingSemaphoreTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,3 @@ void vStartFlashCoRoutines( UBaseType_t uxPriority );
|
||||||
BaseType_t xAreFlashCoRoutinesStillRunning( void );
|
BaseType_t xAreFlashCoRoutinesStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,3 @@ void vStartHookCoRoutines( void );
|
||||||
BaseType_t xAreHookCoRoutinesStillRunning( void );
|
BaseType_t xAreHookCoRoutinesStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vCreateSuicidalTasks( UBaseType_t uxPriority );
|
||||||
BaseType_t xIsCreateTaskStillRunning( void );
|
BaseType_t xIsCreateTaskStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vStartDynamicPriorityTasks( void );
|
||||||
BaseType_t xAreDynamicPriorityTasksStillRunning( void );
|
BaseType_t xAreDynamicPriorityTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
void vDisplayMessage( const char * const pcMessageToPrint );
|
void vDisplayMessage( const char * const pcMessageToPrint );
|
||||||
void vWriteMessageToDisk( const char * const pcMessage );
|
void vWriteMessageToDisk( const char * const pcMessage );
|
||||||
void vWriteBufferToDisk( const char * const pcBuffer, uint32_t ulBufferLength );
|
void vWriteBufferToDisk( const char * const pcBuffer,
|
||||||
|
uint32_t ulBufferLength );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,3 @@
|
||||||
void vStartLEDFlashTasks( UBaseType_t uxPriority );
|
void vStartLEDFlashTasks( UBaseType_t uxPriority );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vStartMathTasks( UBaseType_t uxPriority );
|
||||||
BaseType_t xAreMathsTaskStillRunning( void );
|
BaseType_t xAreMathsTaskStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vStartIntegerMathTasks( UBaseType_t uxPriority );
|
||||||
BaseType_t xAreIntegerMathsTaskStillRunning( void );
|
BaseType_t xAreIntegerMathsTaskStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ void vStartMultiEventTasks( void );
|
||||||
BaseType_t xAreMultiEventTasksStillRunning( void );
|
BaseType_t xAreMultiEventTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@
|
||||||
#define partstDEFAULT_PORT_ADDRESS ( ( uint16_t ) 0x378 )
|
#define partstDEFAULT_PORT_ADDRESS ( ( uint16_t ) 0x378 )
|
||||||
|
|
||||||
void vParTestInitialise( void );
|
void vParTestInitialise( void );
|
||||||
void vParTestSetLED( UBaseType_t uxLED, BaseType_t xValue );
|
void vParTestSetLED( UBaseType_t uxLED,
|
||||||
|
BaseType_t xValue );
|
||||||
void vParTestToggleLED( UBaseType_t uxLED );
|
void vParTestToggleLED( UBaseType_t uxLED );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,3 @@ void vPrintDisplayMessage( const char * const * pcMessageToSend );
|
||||||
const char * pcPrintGetNextMessage( TickType_t xPrintRate );
|
const char * pcPrintGetNextMessage( TickType_t xPrintRate );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,3 @@ void vStartRecursiveMutexTasks( void );
|
||||||
BaseType_t xAreRecursiveMutexTasksStillRunning( void );
|
BaseType_t xAreRecursiveMutexTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,3 @@ void vStartSemaphoreTasks( UBaseType_t uxPriority );
|
||||||
BaseType_t xAreSemaphoreTasksStillRunning( void );
|
BaseType_t xAreSemaphoreTasksStillRunning( void );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,13 +86,24 @@ typedef enum
|
||||||
ser115200
|
ser115200
|
||||||
} eBaud;
|
} eBaud;
|
||||||
|
|
||||||
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength );
|
xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud,
|
||||||
xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength );
|
unsigned portBASE_TYPE uxQueueLength );
|
||||||
void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength );
|
xComPortHandle xSerialPortInit( eCOMPort ePort,
|
||||||
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime );
|
eBaud eWantedBaud,
|
||||||
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime );
|
eParity eWantedParity,
|
||||||
|
eDataBits eWantedDataBits,
|
||||||
|
eStopBits eWantedStopBits,
|
||||||
|
unsigned portBASE_TYPE uxBufferLength );
|
||||||
|
void vSerialPutString( xComPortHandle pxPort,
|
||||||
|
const signed char * const pcString,
|
||||||
|
unsigned short usStringLength );
|
||||||
|
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort,
|
||||||
|
signed char * pcRxedChar,
|
||||||
|
TickType_t xBlockTime );
|
||||||
|
signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort,
|
||||||
|
signed char cOutChar,
|
||||||
|
TickType_t xBlockTime );
|
||||||
portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort );
|
portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort );
|
||||||
void vSerialClose( xComPortHandle xPort );
|
void vSerialClose( xComPortHandle xPort );
|
||||||
|
|
||||||
#endif
|
#endif /* ifndef SERIAL_COMMS_H */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
eFrameProcessingResult_t publicProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer ) {
|
eFrameProcessingResult_t publicProcessIPPacket( IPPacket_t * const pxIPPacket,
|
||||||
|
NetworkBufferDescriptor_t * const pxNetworkBuffer )
|
||||||
|
{
|
||||||
prvProcessIPPacket( pxIPPacket, pxNetworkBuffer );
|
prvProcessIPPacket( pxIPPacket, pxNetworkBuffer );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,20 @@
|
||||||
int32_t publicTCPPrepareSend( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer, UBaseType_t uxOptionsLength ) {
|
int32_t publicTCPPrepareSend( FreeRTOS_Socket_t * pxSocket,
|
||||||
|
NetworkBufferDescriptor_t ** ppxNetworkBuffer,
|
||||||
|
UBaseType_t uxOptionsLength )
|
||||||
|
{
|
||||||
prvTCPPrepareSend( pxSocket, ppxNetworkBuffer, uxOptionsLength );
|
prvTCPPrepareSend( pxSocket, ppxNetworkBuffer, uxOptionsLength );
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType_t publicTCPHandleState( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer ) {
|
BaseType_t publicTCPHandleState( FreeRTOS_Socket_t * pxSocket,
|
||||||
|
NetworkBufferDescriptor_t ** ppxNetworkBuffer )
|
||||||
|
{
|
||||||
prvTCPHandleState( pxSocket, ppxNetworkBuffer );
|
prvTCPHandleState( pxSocket, ppxNetworkBuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
void publicTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,
|
void publicTCPReturnPacket( FreeRTOS_Socket_t * pxSocket,
|
||||||
uint32_t ulLen, BaseType_t xReleaseAfterSend ) {
|
NetworkBufferDescriptor_t * pxNetworkBuffer,
|
||||||
|
uint32_t ulLen,
|
||||||
|
BaseType_t xReleaseAfterSend )
|
||||||
|
{
|
||||||
prvTCPReturnPacket( pxSocket, pxNetworkBuffer, ulLen, xReleaseAfterSend );
|
prvTCPReturnPacket( pxSocket, pxNetworkBuffer, ulLen, xReleaseAfterSend );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,28 +11,36 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Using prvCopyDataToQueue together with prvNotifyQueueSetContainer
|
/* Using prvCopyDataToQueue together with prvNotifyQueueSetContainer
|
||||||
leads to a problem space explosion. Therefore, we use this stub
|
* leads to a problem space explosion. Therefore, we use this stub
|
||||||
and a sepearted proof on prvCopyDataToQueue to deal with it.
|
* and a sepearted proof on prvCopyDataToQueue to deal with it.
|
||||||
As prvNotifyQueueSetContainer is disabled if configUSE_QUEUE_SETS != 1,
|
* As prvNotifyQueueSetContainer is disabled if configUSE_QUEUE_SETS != 1,
|
||||||
in other cases the original implementation should be used. */
|
* in other cases the original implementation should be used. */
|
||||||
#if ( configUSE_QUEUE_SETS == 1 )
|
#if ( configUSE_QUEUE_SETS == 1 )
|
||||||
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
|
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
|
||||||
|
const void * pvItemToQueue,
|
||||||
|
const BaseType_t xPosition )
|
||||||
{
|
{
|
||||||
if( pxQueue->uxItemSize > ( UBaseType_t ) 0 )
|
if( pxQueue->uxItemSize > ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
__CPROVER_assert( __CPROVER_r_ok( pvItemToQueue, ( size_t ) pxQueue->uxItemSize ), "pvItemToQueue region must be readable" );
|
__CPROVER_assert( __CPROVER_r_ok( pvItemToQueue, ( size_t ) pxQueue->uxItemSize ), "pvItemToQueue region must be readable" );
|
||||||
if(xPosition == queueSEND_TO_BACK){
|
|
||||||
|
if( xPosition == queueSEND_TO_BACK )
|
||||||
|
{
|
||||||
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize ), "pxQueue->pcWriteTo region must be writable" );
|
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize ), "pxQueue->pcWriteTo region must be writable" );
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ), "pxQueue->u.xQueue.pcReadFrom region must be writable" );
|
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ), "pxQueue->u.xQueue.pcReadFrom region must be writable" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return pdFALSE;
|
return pdFALSE;
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return nondet_BaseType_t();
|
return nondet_BaseType_t();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configUSE_QUEUE_SETS == 1 ) */
|
||||||
|
|
||||||
/* xQueueCreateSet is compiled out if configUSE_QUEUE_SETS != 1.*/
|
/* xQueueCreateSet is compiled out if configUSE_QUEUE_SETS != 1.*/
|
||||||
#if ( configUSE_QUEUE_SETS == 1 )
|
#if ( configUSE_QUEUE_SETS == 1 )
|
||||||
|
|
@ -40,6 +48,7 @@
|
||||||
{
|
{
|
||||||
UBaseType_t uxEventQueueLength = 2;
|
UBaseType_t uxEventQueueLength = 2;
|
||||||
QueueSetHandle_t xSet = xQueueCreateSet( uxEventQueueLength );
|
QueueSetHandle_t xSet = xQueueCreateSet( uxEventQueueLength );
|
||||||
|
|
||||||
if( xSet )
|
if( xSet )
|
||||||
{
|
{
|
||||||
xSet->cTxLock = nondet_int8_t();
|
xSet->cTxLock = nondet_int8_t();
|
||||||
|
|
@ -47,39 +56,46 @@
|
||||||
xSet->cRxLock = nondet_int8_t();
|
xSet->cRxLock = nondet_int8_t();
|
||||||
xSet->uxMessagesWaiting = nondet_UBaseType_t();
|
xSet->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
xSet->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
xSet->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
|
|
||||||
/* This is an invariant checked with a couple of asserts in the code base.
|
/* This is an invariant checked with a couple of asserts in the code base.
|
||||||
If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
* If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
||||||
__CPROVER_assume( xSet->uxMessagesWaiting < xSet->uxLength );
|
__CPROVER_assume( xSet->uxMessagesWaiting < xSet->uxLength );
|
||||||
xSet->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
xSet->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
return xSet;
|
return xSet;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configUSE_QUEUE_SETS == 1 ) */
|
||||||
|
|
||||||
/* Create a mostly unconstrained Queue but bound the max item size.
|
/* Create a mostly unconstrained Queue but bound the max item size.
|
||||||
This is required for performance reasons in CBMC at the moment. */
|
* This is required for performance reasons in CBMC at the moment. */
|
||||||
QueueHandle_t xUnconstrainedQueueBoundedItemSize( UBaseType_t uxItemSizeBound ) {
|
QueueHandle_t xUnconstrainedQueueBoundedItemSize( UBaseType_t uxItemSizeBound )
|
||||||
|
{
|
||||||
UBaseType_t uxQueueLength;
|
UBaseType_t uxQueueLength;
|
||||||
UBaseType_t uxItemSize;
|
UBaseType_t uxItemSize;
|
||||||
uint8_t ucQueueType;
|
uint8_t ucQueueType;
|
||||||
|
|
||||||
__CPROVER_assume( uxQueueLength > 0 );
|
__CPROVER_assume( uxQueueLength > 0 );
|
||||||
__CPROVER_assume( uxItemSize < uxItemSizeBound );
|
__CPROVER_assume( uxItemSize < uxItemSizeBound );
|
||||||
|
|
||||||
// QueueGenericCreate method does not check for multiplication overflow
|
/* QueueGenericCreate method does not check for multiplication overflow */
|
||||||
size_t uxQueueStorageSize;
|
size_t uxQueueStorageSize;
|
||||||
__CPROVER_assume( uxQueueStorageSize < CBMC_OBJECT_MAX_SIZE );
|
__CPROVER_assume( uxQueueStorageSize < CBMC_OBJECT_MAX_SIZE );
|
||||||
__CPROVER_assume( uxItemSize < uxQueueStorageSize / uxQueueLength );
|
__CPROVER_assume( uxItemSize < uxQueueStorageSize / uxQueueLength );
|
||||||
|
|
||||||
QueueHandle_t xQueue =
|
QueueHandle_t xQueue =
|
||||||
xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
|
xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
|
||||||
if(xQueue){
|
|
||||||
|
if( xQueue )
|
||||||
|
{
|
||||||
xQueue->cTxLock = nondet_int8_t();
|
xQueue->cTxLock = nondet_int8_t();
|
||||||
__CPROVER_assume( xQueue->cTxLock != 127 );
|
__CPROVER_assume( xQueue->cTxLock != 127 );
|
||||||
xQueue->cRxLock = nondet_int8_t();
|
xQueue->cRxLock = nondet_int8_t();
|
||||||
__CPROVER_assume( xQueue->cRxLock != 127 );
|
__CPROVER_assume( xQueue->cRxLock != 127 );
|
||||||
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
|
|
||||||
/* This is an invariant checked with a couple of asserts in the code base.
|
/* This is an invariant checked with a couple of asserts in the code base.
|
||||||
If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
* If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
||||||
__CPROVER_assume( xQueue->uxMessagesWaiting < xQueue->uxLength );
|
__CPROVER_assume( xQueue->uxMessagesWaiting < xQueue->uxLength );
|
||||||
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
|
|
@ -87,18 +103,20 @@ QueueHandle_t xUnconstrainedQueueBoundedItemSize( UBaseType_t uxItemSizeBound )
|
||||||
xQueueAddToSet( xQueue, xUnconstrainedQueueSet() );
|
xQueueAddToSet( xQueue, xUnconstrainedQueueSet() );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return xQueue;
|
return xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a mostly unconstrained Queue */
|
/* Create a mostly unconstrained Queue */
|
||||||
QueueHandle_t xUnconstrainedQueue( void ) {
|
QueueHandle_t xUnconstrainedQueue( void )
|
||||||
|
{
|
||||||
UBaseType_t uxQueueLength;
|
UBaseType_t uxQueueLength;
|
||||||
UBaseType_t uxItemSize;
|
UBaseType_t uxItemSize;
|
||||||
uint8_t ucQueueType;
|
uint8_t ucQueueType;
|
||||||
|
|
||||||
__CPROVER_assume( uxQueueLength > 0 );
|
__CPROVER_assume( uxQueueLength > 0 );
|
||||||
|
|
||||||
// QueueGenericCreate method does not check for multiplication overflow
|
/* QueueGenericCreate method does not check for multiplication overflow */
|
||||||
size_t uxQueueStorageSize;
|
size_t uxQueueStorageSize;
|
||||||
__CPROVER_assume( uxQueueStorageSize < CBMC_OBJECT_MAX_SIZE );
|
__CPROVER_assume( uxQueueStorageSize < CBMC_OBJECT_MAX_SIZE );
|
||||||
__CPROVER_assume( uxItemSize < uxQueueStorageSize / uxQueueLength );
|
__CPROVER_assume( uxItemSize < uxQueueStorageSize / uxQueueLength );
|
||||||
|
|
@ -106,13 +124,15 @@ QueueHandle_t xUnconstrainedQueue( void ) {
|
||||||
QueueHandle_t xQueue =
|
QueueHandle_t xQueue =
|
||||||
xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
|
xQueueGenericCreate( uxQueueLength, uxItemSize, ucQueueType );
|
||||||
|
|
||||||
if(xQueue){
|
if( xQueue )
|
||||||
|
{
|
||||||
xQueue->cTxLock = nondet_int8_t();
|
xQueue->cTxLock = nondet_int8_t();
|
||||||
__CPROVER_assume( xQueue->cTxLock != 127 );
|
__CPROVER_assume( xQueue->cTxLock != 127 );
|
||||||
xQueue->cRxLock = nondet_int8_t();
|
xQueue->cRxLock = nondet_int8_t();
|
||||||
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
|
|
||||||
/* This is an invariant checked with a couple of asserts in the code base.
|
/* This is an invariant checked with a couple of asserts in the code base.
|
||||||
If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
* If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
||||||
__CPROVER_assume( xQueue->uxMessagesWaiting < xQueue->uxLength );
|
__CPROVER_assume( xQueue->uxMessagesWaiting < xQueue->uxLength );
|
||||||
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
|
|
@ -120,21 +140,26 @@ QueueHandle_t xUnconstrainedQueue( void ) {
|
||||||
xQueueAddToSet( xQueue, xUnconstrainedQueueSet() );
|
xQueueAddToSet( xQueue, xUnconstrainedQueueSet() );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return xQueue;
|
return xQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a mostly unconstrained Mutex */
|
/* Create a mostly unconstrained Mutex */
|
||||||
QueueHandle_t xUnconstrainedMutex( void ) {
|
QueueHandle_t xUnconstrainedMutex( void )
|
||||||
|
{
|
||||||
uint8_t ucQueueType;
|
uint8_t ucQueueType;
|
||||||
QueueHandle_t xQueue =
|
QueueHandle_t xQueue =
|
||||||
xQueueCreateMutex( ucQueueType );
|
xQueueCreateMutex( ucQueueType );
|
||||||
if(xQueue){
|
|
||||||
|
if( xQueue )
|
||||||
|
{
|
||||||
xQueue->cTxLock = nondet_int8_t();
|
xQueue->cTxLock = nondet_int8_t();
|
||||||
__CPROVER_assume( xQueue->cTxLock != 127 );
|
__CPROVER_assume( xQueue->cTxLock != 127 );
|
||||||
xQueue->cRxLock = nondet_int8_t();
|
xQueue->cRxLock = nondet_int8_t();
|
||||||
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
|
|
||||||
/* This is an invariant checked with a couple of asserts in the code base.
|
/* This is an invariant checked with a couple of asserts in the code base.
|
||||||
If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
* If it is false from the beginning, the CBMC proofs are not able to succeed*/
|
||||||
__CPROVER_assume( xQueue->uxMessagesWaiting < xQueue->uxLength );
|
__CPROVER_assume( xQueue->uxMessagesWaiting < xQueue->uxLength );
|
||||||
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
|
||||||
|
|
@ -142,5 +167,6 @@ QueueHandle_t xUnconstrainedMutex( void ) {
|
||||||
xQueueAddToSet( xQueue, xUnconstrainedQueueSet() );
|
xQueueAddToSet( xQueue, xUnconstrainedQueueSet() );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return xQueue;
|
return xQueue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
BaseType_t xState;
|
BaseType_t xState;
|
||||||
void vInitTaskCheckForTimeOut(BaseType_t maxCounter, BaseType_t maxCounter_limit);
|
void vInitTaskCheckForTimeOut( BaseType_t maxCounter,
|
||||||
|
BaseType_t maxCounter_limit );
|
||||||
|
|
||||||
#endif /* INC_TASK_STUBS_H */
|
#endif /* INC_TASK_STUBS_H */
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
FreeRTOS V202104.00
|
* FreeRTOS V202104.00
|
||||||
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
* the Software without restriction, including without limitation the rights to
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
subject to the following conditions:
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
The above copyright notice and this permission notice shall be included in all
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
http://aws.amazon.com/freertos
|
* http://aws.amazon.com/freertos
|
||||||
http://www.FreeRTOS.org
|
* http://www.FreeRTOS.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 5 is a magic number, but we need some number here as a default value.
|
/* 5 is a magic number, but we need some number here as a default value.
|
||||||
This value is used to bound any loop depending on xTaskCheckForTimeOut
|
* This value is used to bound any loop depending on xTaskCheckForTimeOut
|
||||||
as a loop bound. It should be overwritten in the Makefile.json adapting
|
* as a loop bound. It should be overwritten in the Makefile.json adapting
|
||||||
to the performance requirements of the harness. */
|
* to the performance requirements of the harness. */
|
||||||
#ifndef TASK_STUB_COUNTER_LIMIT
|
#ifndef TASK_STUB_COUNTER_LIMIT
|
||||||
#define TASK_STUB_COUNTER_LIMIT 5;
|
#define TASK_STUB_COUNTER_LIMIT 5;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -24,18 +24,22 @@ BaseType_t xTaskGetSchedulerState( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is another method apart from overwritting the defines to init the max
|
/* This function is another method apart from overwritting the defines to init the max
|
||||||
loop bound. */
|
* loop bound. */
|
||||||
void vInitTaskCheckForTimeOut(BaseType_t maxCounter, BaseType_t maxCounter_limit)
|
void vInitTaskCheckForTimeOut( BaseType_t maxCounter,
|
||||||
|
BaseType_t maxCounter_limit )
|
||||||
{
|
{
|
||||||
xCounter = maxCounter;
|
xCounter = maxCounter;
|
||||||
xCounterLimit = maxCounter_limit;
|
xCounterLimit = maxCounter_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is mostly called in a loop. For CBMC, we have to bound the loop
|
/* This is mostly called in a loop. For CBMC, we have to bound the loop
|
||||||
to a max limits of calls. Therefore this Stub models a nondet timeout in
|
* to a max limits of calls. Therefore this Stub models a nondet timeout in
|
||||||
max TASK_STUB_COUNTER_LIMIT iterations.*/
|
* max TASK_STUB_COUNTER_LIMIT iterations.*/
|
||||||
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) {
|
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
|
||||||
|
TickType_t * const pxTicksToWait )
|
||||||
|
{
|
||||||
++xCounter;
|
++xCounter;
|
||||||
|
|
||||||
if( xCounter == xCounterLimit )
|
if( xCounter == xCounterLimit )
|
||||||
{
|
{
|
||||||
return pdTRUE;
|
return pdTRUE;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@
|
||||||
|
|
||||||
#include "cbmc.h"
|
#include "cbmc.h"
|
||||||
|
|
||||||
void harness() {
|
void harness()
|
||||||
|
{
|
||||||
uint8_t ucQueueType;
|
uint8_t ucQueueType;
|
||||||
|
|
||||||
xQueueCreateMutex( ucQueueType );
|
xQueueCreateMutex( ucQueueType );
|
||||||
|
|
|
||||||
|
|
@ -42,35 +42,47 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ( configUSE_QUEUE_SETS == 0 )
|
#if ( configUSE_QUEUE_SETS == 0 )
|
||||||
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
|
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
|
||||||
|
const void * pvItemToQueue,
|
||||||
|
const BaseType_t xPosition )
|
||||||
{
|
{
|
||||||
if( pxQueue->uxItemSize > ( UBaseType_t ) 0 )
|
if( pxQueue->uxItemSize > ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
__CPROVER_assert( __CPROVER_r_ok( pvItemToQueue, ( size_t ) pxQueue->uxItemSize ), "pvItemToQueue region must be readable" );
|
__CPROVER_assert( __CPROVER_r_ok( pvItemToQueue, ( size_t ) pxQueue->uxItemSize ), "pvItemToQueue region must be readable" );
|
||||||
if(xPosition == queueSEND_TO_BACK){
|
|
||||||
|
if( xPosition == queueSEND_TO_BACK )
|
||||||
|
{
|
||||||
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize ), "pxQueue->pcWriteTo region must be writable" );
|
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize ), "pxQueue->pcWriteTo region must be writable" );
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ), "pxQueue->u.xQueue.pcReadFrom region must be writable" );
|
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ), "pxQueue->u.xQueue.pcReadFrom region must be writable" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return pdFALSE;
|
return pdFALSE;
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return nondet_BaseType_t();
|
return nondet_BaseType_t();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else /* if ( configUSE_QUEUE_SETS == 0 ) */
|
||||||
BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )
|
BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue )
|
||||||
{
|
{
|
||||||
Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer;
|
Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer;
|
||||||
|
|
||||||
configASSERT( pxQueueSetContainer );
|
configASSERT( pxQueueSetContainer );
|
||||||
}
|
}
|
||||||
|
|
||||||
void prvUnlockQueue( Queue_t * const pxQueue ) {
|
void prvUnlockQueue( Queue_t * const pxQueue )
|
||||||
|
{
|
||||||
configASSERT( pxQueue );
|
configASSERT( pxQueue );
|
||||||
|
|
||||||
if( pxQueue->pxQueueSetContainer != NULL )
|
if( pxQueue->pxQueueSetContainer != NULL )
|
||||||
{
|
{
|
||||||
prvNotifyQueueSetContainer( pxQueue );
|
prvNotifyQueueSetContainer( pxQueue );
|
||||||
}
|
}
|
||||||
|
|
||||||
listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) );
|
listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) );
|
||||||
pxQueue->cTxLock = queueUNLOCKED;
|
pxQueue->cTxLock = queueUNLOCKED;
|
||||||
|
|
||||||
|
|
@ -78,50 +90,56 @@ BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueu
|
||||||
pxQueue->cRxLock = queueUNLOCKED;
|
pxQueue->cRxLock = queueUNLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif /* if ( configUSE_QUEUE_SETS == 0 ) */
|
||||||
|
|
||||||
void harness(){
|
void harness()
|
||||||
//Initialise the tasksStubs
|
{
|
||||||
|
/*Initialise the tasksStubs */
|
||||||
vInitTaskCheckForTimeOut( 0, QUEUE_SEND_BOUND - 1 );
|
vInitTaskCheckForTimeOut( 0, QUEUE_SEND_BOUND - 1 );
|
||||||
xState = nondet_basetype();
|
xState = nondet_basetype();
|
||||||
QueueHandle_t xQueue =
|
QueueHandle_t xQueue =
|
||||||
xUnconstrainedQueueBoundedItemSize( 2 );
|
xUnconstrainedQueueBoundedItemSize( 2 );
|
||||||
|
|
||||||
TickType_t xTicksToWait;
|
TickType_t xTicksToWait;
|
||||||
if(xState == taskSCHEDULER_SUSPENDED){
|
|
||||||
|
if( xState == taskSCHEDULER_SUSPENDED )
|
||||||
|
{
|
||||||
xTicksToWait = 0;
|
xTicksToWait = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xQueue){
|
if( xQueue )
|
||||||
|
{
|
||||||
void * pvItemToQueue = pvPortMalloc( xQueue->uxItemSize );
|
void * pvItemToQueue = pvPortMalloc( xQueue->uxItemSize );
|
||||||
BaseType_t xCopyPosition;
|
BaseType_t xCopyPosition;
|
||||||
|
|
||||||
if(xCopyPosition == queueOVERWRITE){
|
if( xCopyPosition == queueOVERWRITE )
|
||||||
|
{
|
||||||
xQueue->uxLength = 1;
|
xQueue->uxLength = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xQueue->uxItemSize == 0 )
|
if( xQueue->uxItemSize == 0 )
|
||||||
{
|
{
|
||||||
/* uxQueue->xQueueType is a pointer to the head of the queue storage area.
|
/* uxQueue->xQueueType is a pointer to the head of the queue storage area.
|
||||||
If an item has a sice, this pointer must not be modified after init.
|
* If an item has a sice, this pointer must not be modified after init.
|
||||||
Otherwise some of the write statements will fail. */
|
* Otherwise some of the write statements will fail. */
|
||||||
xQueue->uxQueueType = nondet_int8_t();
|
xQueue->uxQueueType = nondet_int8_t();
|
||||||
pvItemToQueue = 0;
|
pvItemToQueue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code checks explicitly for violations of the pxQueue->uxMessagesWaiting < pxQueue->uxLength
|
/* This code checks explicitly for violations of the pxQueue->uxMessagesWaiting < pxQueue->uxLength
|
||||||
invariant. */
|
* invariant. */
|
||||||
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
|
|
||||||
/* These values are decremented during a while loop interacting with task.c.
|
/* These values are decremented during a while loop interacting with task.c.
|
||||||
This interaction is currently abstracted away.*/
|
* This interaction is currently abstracted away.*/
|
||||||
xQueue->cTxLock = LOCK_BOUND - 1;
|
xQueue->cTxLock = LOCK_BOUND - 1;
|
||||||
xQueue->cRxLock = LOCK_BOUND - 1;
|
xQueue->cRxLock = LOCK_BOUND - 1;
|
||||||
|
|
||||||
if(!pvItemToQueue){
|
if( !pvItemToQueue )
|
||||||
|
{
|
||||||
xQueue->uxItemSize = 0;
|
xQueue->uxItemSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition );
|
xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, xCopyPosition );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,49 +37,66 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ( configUSE_QUEUE_SETS == 0 )
|
#if ( configUSE_QUEUE_SETS == 0 )
|
||||||
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
|
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
|
||||||
|
const void * pvItemToQueue,
|
||||||
|
const BaseType_t xPosition )
|
||||||
{
|
{
|
||||||
if( pxQueue->uxItemSize > ( UBaseType_t ) 0 )
|
if( pxQueue->uxItemSize > ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
__CPROVER_assert( __CPROVER_r_ok( pvItemToQueue, ( size_t ) pxQueue->uxItemSize ), "pvItemToQueue region must be readable" );
|
__CPROVER_assert( __CPROVER_r_ok( pvItemToQueue, ( size_t ) pxQueue->uxItemSize ), "pvItemToQueue region must be readable" );
|
||||||
if(xPosition == queueSEND_TO_BACK){
|
|
||||||
|
if( xPosition == queueSEND_TO_BACK )
|
||||||
|
{
|
||||||
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize ), "pxQueue->pcWriteTo region must be writable" );
|
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize ), "pxQueue->pcWriteTo region must be writable" );
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ), "pxQueue->u.xQueue.pcReadFrom region must be writable" );
|
__CPROVER_assert( __CPROVER_w_ok( ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ), "pxQueue->u.xQueue.pcReadFrom region must be writable" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return pdFALSE;
|
return pdFALSE;
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return nondet_BaseType_t();
|
return nondet_BaseType_t();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* if ( configUSE_QUEUE_SETS == 0 ) */
|
||||||
|
|
||||||
void harness(){
|
void harness()
|
||||||
|
{
|
||||||
QueueHandle_t xQueue = xUnconstrainedQueueBoundedItemSize( ITEM_BOUND );
|
QueueHandle_t xQueue = xUnconstrainedQueueBoundedItemSize( ITEM_BOUND );
|
||||||
|
|
||||||
|
|
||||||
if( xQueue ){
|
if( xQueue )
|
||||||
|
{
|
||||||
void * pvItemToQueue = pvPortMalloc( xQueue->uxItemSize );
|
void * pvItemToQueue = pvPortMalloc( xQueue->uxItemSize );
|
||||||
BaseType_t * xHigherPriorityTaskWoken = pvPortMalloc( sizeof( BaseType_t ) );
|
BaseType_t * xHigherPriorityTaskWoken = pvPortMalloc( sizeof( BaseType_t ) );
|
||||||
BaseType_t xCopyPosition;
|
BaseType_t xCopyPosition;
|
||||||
|
|
||||||
if( xQueue->uxItemSize == 0 )
|
if( xQueue->uxItemSize == 0 )
|
||||||
{
|
{
|
||||||
/* uxQueue->xQueueType is a pointer to the head of the queue storage area.
|
/* uxQueue->xQueueType is a pointer to the head of the queue storage area.
|
||||||
If an item has a size, this pointer must not be modified after init.
|
* If an item has a size, this pointer must not be modified after init.
|
||||||
Otherwise some of the write statements will fail. */
|
* Otherwise some of the write statements will fail. */
|
||||||
xQueue->uxQueueType = nondet_int8_t();
|
xQueue->uxQueueType = nondet_int8_t();
|
||||||
pvItemToQueue = 0;
|
pvItemToQueue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code checks explicitly for violations of the pxQueue->uxMessagesWaiting < pxQueue->uxLength
|
/* This code checks explicitly for violations of the pxQueue->uxMessagesWaiting < pxQueue->uxLength
|
||||||
invariant. */
|
* invariant. */
|
||||||
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
if(!pvItemToQueue){
|
|
||||||
|
if( !pvItemToQueue )
|
||||||
|
{
|
||||||
xQueue->uxItemSize = 0;
|
xQueue->uxItemSize = 0;
|
||||||
}
|
}
|
||||||
if(xCopyPosition == 2 ){
|
|
||||||
|
if( xCopyPosition == 2 )
|
||||||
|
{
|
||||||
__CPROVER_assume( xQueue->uxLength == 1 );
|
__CPROVER_assume( xQueue->uxLength == 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
xQueueGenericSendFromISR( xQueue, pvItemToQueue, xHigherPriorityTaskWoken, xCopyPosition );
|
xQueueGenericSendFromISR( xQueue, pvItemToQueue, xHigherPriorityTaskWoken, xCopyPosition );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,12 @@
|
||||||
|
|
||||||
#include "cbmc.h"
|
#include "cbmc.h"
|
||||||
|
|
||||||
void harness() {
|
void harness()
|
||||||
|
{
|
||||||
QueueHandle_t xSemaphore = xUnconstrainedQueue();
|
QueueHandle_t xSemaphore = xUnconstrainedQueue();
|
||||||
if (xSemaphore) {
|
|
||||||
|
if( xSemaphore )
|
||||||
|
{
|
||||||
xSemaphore->uxQueueType = nondet_uint8_t();
|
xSemaphore->uxQueueType = nondet_uint8_t();
|
||||||
xQueueGetMutexHolder( xSemaphore );
|
xQueueGetMutexHolder( xSemaphore );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,12 @@
|
||||||
|
|
||||||
#include "cbmc.h"
|
#include "cbmc.h"
|
||||||
|
|
||||||
void harness(){
|
void harness()
|
||||||
|
{
|
||||||
QueueHandle_t xSemaphore = pvPortMalloc( sizeof( Queue_t ) );
|
QueueHandle_t xSemaphore = pvPortMalloc( sizeof( Queue_t ) );
|
||||||
if (xSemaphore) {
|
|
||||||
|
if( xSemaphore )
|
||||||
|
{
|
||||||
xQueueGetMutexHolderFromISR( xSemaphore );
|
xQueueGetMutexHolderFromISR( xSemaphore );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,14 @@
|
||||||
|
|
||||||
#include "cbmc.h"
|
#include "cbmc.h"
|
||||||
|
|
||||||
void harness(){
|
void harness()
|
||||||
|
{
|
||||||
QueueHandle_t xQueue = xUnconstrainedMutex();
|
QueueHandle_t xQueue = xUnconstrainedMutex();
|
||||||
BaseType_t * xHigherPriorityTaskWoken = pvPortMalloc( sizeof( BaseType_t ) );
|
BaseType_t * xHigherPriorityTaskWoken = pvPortMalloc( sizeof( BaseType_t ) );
|
||||||
if(xQueue){
|
|
||||||
|
if( xQueue )
|
||||||
|
{
|
||||||
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
|
||||||
xQueueGiveFromISR( xQueue, xHigherPriorityTaskWoken );
|
xQueueGiveFromISR( xQueue, xHigherPriorityTaskWoken );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,15 +32,19 @@
|
||||||
|
|
||||||
#include "cbmc.h"
|
#include "cbmc.h"
|
||||||
|
|
||||||
void harness() {
|
void harness()
|
||||||
|
{
|
||||||
uint8_t ucQueueType;
|
uint8_t ucQueueType;
|
||||||
QueueHandle_t xMutex =
|
QueueHandle_t xMutex =
|
||||||
xQueueCreateMutex( ucQueueType );
|
xQueueCreateMutex( ucQueueType );
|
||||||
if (xMutex) {
|
|
||||||
|
if( xMutex )
|
||||||
|
{
|
||||||
xMutex->uxQueueType = ucQueueType;
|
xMutex->uxQueueType = ucQueueType;
|
||||||
UBaseType_t uxCounter;
|
UBaseType_t uxCounter;
|
||||||
|
|
||||||
/* This assumption is explained in the queue.c file inside the method body
|
/* This assumption is explained in the queue.c file inside the method body
|
||||||
xQueueGiveMutexRecursive and guards against an underflow error. */
|
* xQueueGiveMutexRecursive and guards against an underflow error. */
|
||||||
__CPROVER_assume( uxCounter > 0 );
|
__CPROVER_assume( uxCounter > 0 );
|
||||||
xMutex->u.xSemaphore.uxRecursiveCallCount = uxCounter;
|
xMutex->u.xSemaphore.uxRecursiveCallCount = uxCounter;
|
||||||
xQueueGiveMutexRecursive( xMutex );
|
xQueueGiveMutexRecursive( xMutex );
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,12 @@
|
||||||
|
|
||||||
#include "cbmc.h"
|
#include "cbmc.h"
|
||||||
|
|
||||||
void harness(){
|
void harness()
|
||||||
|
{
|
||||||
QueueHandle_t xQueue = pvPortMalloc( sizeof( Queue_t ) );
|
QueueHandle_t xQueue = pvPortMalloc( sizeof( Queue_t ) );
|
||||||
|
|
||||||
if(xQueue){
|
if( xQueue )
|
||||||
|
{
|
||||||
uxQueueMessagesWaiting( xQueue );
|
uxQueueMessagesWaiting( xQueue );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,32 +45,38 @@ QueueHandle_t xQueue;
|
||||||
|
|
||||||
|
|
||||||
/* This method is called to initialize pxTimeOut.
|
/* This method is called to initialize pxTimeOut.
|
||||||
Setting up the data structure is not interesting for the proof,
|
* Setting up the data structure is not interesting for the proof,
|
||||||
but the harness uses it to model a release
|
* but the harness uses it to model a release
|
||||||
on the queue after first check. */
|
* on the queue after first check. */
|
||||||
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ){
|
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
|
||||||
|
{
|
||||||
xQueue->uxMessagesWaiting = nondet_BaseType_t();
|
xQueue->uxMessagesWaiting = nondet_BaseType_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
void harness(){
|
void harness()
|
||||||
|
{
|
||||||
xQueue = xUnconstrainedQueueBoundedItemSize( 10 );
|
xQueue = xUnconstrainedQueueBoundedItemSize( 10 );
|
||||||
|
|
||||||
//Initialise the tasksStubs
|
/*Initialise the tasksStubs */
|
||||||
vInitTaskCheckForTimeOut( 0, QUEUE_PEEK_BOUND - 1 );
|
vInitTaskCheckForTimeOut( 0, QUEUE_PEEK_BOUND - 1 );
|
||||||
|
|
||||||
TickType_t xTicksToWait;
|
TickType_t xTicksToWait;
|
||||||
if(xState == taskSCHEDULER_SUSPENDED){
|
|
||||||
|
if( xState == taskSCHEDULER_SUSPENDED )
|
||||||
|
{
|
||||||
xTicksToWait = 0;
|
xTicksToWait = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xQueue){
|
if( xQueue )
|
||||||
|
{
|
||||||
__CPROVER_assume( xQueue->cTxLock < LOCK_BOUND - 1 );
|
__CPROVER_assume( xQueue->cTxLock < LOCK_BOUND - 1 );
|
||||||
__CPROVER_assume( xQueue->cRxLock < LOCK_BOUND - 1 );
|
__CPROVER_assume( xQueue->cRxLock < LOCK_BOUND - 1 );
|
||||||
|
|
||||||
void * pvItemToQueue = pvPortMalloc( xQueue->uxItemSize );
|
void * pvItemToQueue = pvPortMalloc( xQueue->uxItemSize );
|
||||||
|
|
||||||
/* In case malloc fails as this is otherwise an invariant violation. */
|
/* In case malloc fails as this is otherwise an invariant violation. */
|
||||||
if(!pvItemToQueue){
|
if( !pvItemToQueue )
|
||||||
|
{
|
||||||
xQueue->uxItemSize = 0;
|
xQueue->uxItemSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue