|
|
|
@ -73,6 +73,8 @@
|
|
|
|
|
* rather than the normal dynamically allocated memory, and tests objects being
|
|
|
|
|
* created and deleted with both statically allocated memory and dynamically
|
|
|
|
|
* allocated memory.
|
|
|
|
|
*
|
|
|
|
|
* See http://www.FreeRTOS.org/Static_Vs_Dynamic_Memory_Allocation.html
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Scheduler include files. */
|
|
|
|
@ -130,59 +132,51 @@ static void prvTimerCallback( TimerHandle_t xExpiredTimer );
|
|
|
|
|
static void prvStaticallyAllocatedTask( void *pvParameters );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xTaskCreateStatic() API function
|
|
|
|
|
* by creating and then deleting tasks with both dynamically and statically
|
|
|
|
|
* allocated TCBs and stacks.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete tasks using both statically and dynamically allocated TCBs and stacks.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedTasks( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xEventGroupCreateStatic() API
|
|
|
|
|
* function by creating and then deleting event groups using both dynamically
|
|
|
|
|
* and statically allocated event group structures.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete event groups using both statically and dynamically allocated RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xQueueCreateStatic() API function
|
|
|
|
|
* by creating and then deleting queues with both dynamically and statically
|
|
|
|
|
* allocated queue structures and queue storage areas.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete queues using both statically and dynamically allocated RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedQueues( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xSemaphoreCreateBinaryStatic() API
|
|
|
|
|
* macro by creating and then deleting binary semaphores with both dynamically
|
|
|
|
|
* and statically allocated semaphore structures.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete binary semaphores using both statically and dynamically allocated RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xTimerCreateStatic() API macro by
|
|
|
|
|
* creating and then deleting software timers with both dynamically and
|
|
|
|
|
* statically allocated timer structures.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete software timers using both statically and dynamically allocated RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedTimers( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xSemaphoreCreateMutexStatic() API
|
|
|
|
|
* macro by creating and then deleting mutexes with both dynamically and
|
|
|
|
|
* statically allocated semaphore structures.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete mutexes using both statically and dynamically allocated RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the xSemaphoreCreateCountingStatic()
|
|
|
|
|
* API macro by creating and then deleting counting semaphores with both
|
|
|
|
|
* dynamically and statically allocated semaphore structures.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete counting semaphores using both statically and dynamically allocated
|
|
|
|
|
* RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A function that demonstrates and tests the
|
|
|
|
|
* xSemaphoreCreateRecursiveMutexStatic() API macro by creating and then
|
|
|
|
|
* deleting recursive mutexes with both dynamically and statically allocated
|
|
|
|
|
* semaphore structures.
|
|
|
|
|
* A function that demonstrates and tests the API functions that create and
|
|
|
|
|
* delete recursive mutexes using both statically and dynamically allocated RAM.
|
|
|
|
|
*/
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );
|
|
|
|
|
|
|
|
|
@ -250,9 +244,8 @@ static volatile BaseType_t xErrorOccurred = pdFALSE;
|
|
|
|
|
|
|
|
|
|
void vStartStaticallyAllocatedTasks( void )
|
|
|
|
|
{
|
|
|
|
|
/* Create a single task, which then repeatedly creates and deletes the
|
|
|
|
|
task implemented by prvStaticallyAllocatedTask() at various different
|
|
|
|
|
priorities, and both with and without statically allocated TCB and stack. */
|
|
|
|
|
/* Create a single task, which then repeatedly creates and deletes the other
|
|
|
|
|
RTOS objects using both statically and dynamically allocated RAM. */
|
|
|
|
|
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. */
|
|
|
|
|
staticCREATOR_TASK_STACK_SIZE, /* Size of the buffer passed in as the stack - in words, not bytes! */
|
|
|
|
@ -274,16 +267,16 @@ static void prvStaticallyAllocatedCreator( void *pvParameters )
|
|
|
|
|
|
|
|
|
|
for( ;; )
|
|
|
|
|
{
|
|
|
|
|
/* Loop, running functions that create and delete the various objects
|
|
|
|
|
that can be optionally created using either static or dynamic memory
|
|
|
|
|
allocation. */
|
|
|
|
|
/* Loop, running functions that create and delete the various RTOS
|
|
|
|
|
objects that can be optionally created using either static or dynamic
|
|
|
|
|
memory allocation. */
|
|
|
|
|
prvCreateAndDeleteStaticallyAllocatedTasks();
|
|
|
|
|
prvCreateAndDeleteStaticallyAllocatedQueues();
|
|
|
|
|
|
|
|
|
|
/* Ensure lower priority tasks get CPU time. */
|
|
|
|
|
/* 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
|
|
|
|
|
executing. */
|
|
|
|
|
vTaskDelay( prvGetNextDelayTime() );
|
|
|
|
|
|
|
|
|
|
/* Just to show the check task that this task is still executing. */
|
|
|
|
|
uxCycleCounter++;
|
|
|
|
|
|
|
|
|
|
prvCreateAndDeleteStaticallyAllocatedBinarySemaphores();
|
|
|
|
@ -304,237 +297,6 @@ static void prvStaticallyAllocatedCreator( void *pvParameters )
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup )
|
|
|
|
|
{
|
|
|
|
|
EventBits_t xEventBits;
|
|
|
|
|
const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( EventBits_t ) 0x55;
|
|
|
|
|
|
|
|
|
|
/* The event group should not have any bits set yet. */
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != ( EventBits_t ) 0 )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Some some bits, then read them back to check they are as expected. */
|
|
|
|
|
xEventGroupSetBits( xEventGroup, xFirstTestBits );
|
|
|
|
|
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != xFirstTestBits )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xEventGroupSetBits( xEventGroup, xSecondTestBits );
|
|
|
|
|
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != ( xFirstTestBits | xSecondTestBits ) )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finally try clearing some bits too and check that operation proceeds as
|
|
|
|
|
expected. */
|
|
|
|
|
xEventGroupClearBits( xEventGroup, xFirstTestBits );
|
|
|
|
|
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != xSecondTestBits )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )
|
|
|
|
|
{
|
|
|
|
|
BaseType_t xReturned;
|
|
|
|
|
UBaseType_t x;
|
|
|
|
|
const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );
|
|
|
|
|
TickType_t xTickCount;
|
|
|
|
|
|
|
|
|
|
/* The binary semaphore should start 'empty', so a call to xSemaphoreTake()
|
|
|
|
|
should fail. */
|
|
|
|
|
xTickCount = xTaskGetTickCount();
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
|
|
|
|
|
|
|
|
|
if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )
|
|
|
|
|
{
|
|
|
|
|
/* Did not block on the semaphore as long as expected. */
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount
|
|
|
|
|
times. */
|
|
|
|
|
for( x = 0; x < uxMaxCount; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreGive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned == pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Giving the semaphore again should fail, as it is 'full'. */
|
|
|
|
|
xReturned = xSemaphoreGive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );
|
|
|
|
|
|
|
|
|
|
/* Should now be possible to 'take' the semaphore up to a maximum of
|
|
|
|
|
uxMaxCount times without blocking. */
|
|
|
|
|
for( x = 0; x < uxMaxCount; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned == pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Back to the starting condition, where the semaphore should not be
|
|
|
|
|
available. */
|
|
|
|
|
xTickCount = xTaskGetTickCount();
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
|
|
|
|
|
|
|
|
|
if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )
|
|
|
|
|
{
|
|
|
|
|
/* Did not block on the semaphore as long as expected. */
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue )
|
|
|
|
|
{
|
|
|
|
|
uint64_t ull, ullRead;
|
|
|
|
|
BaseType_t xReturned, xLoop;
|
|
|
|
|
|
|
|
|
|
/* This test is done twice to ensure the queue storage area wraps. */
|
|
|
|
|
for( xLoop = 0; xLoop < 2; xLoop++ )
|
|
|
|
|
{
|
|
|
|
|
/* A very basic test that the queue can be written to and read from as
|
|
|
|
|
expected. First the queue should be empty. */
|
|
|
|
|
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != errQUEUE_EMPTY )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS
|
|
|
|
|
times. */
|
|
|
|
|
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should not now be possible to write to the queue again. */
|
|
|
|
|
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != errQUEUE_FULL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now read back from the queue to ensure the data read back matches that
|
|
|
|
|
written. */
|
|
|
|
|
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( ullRead != ull )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The queue should be empty again. */
|
|
|
|
|
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != errQUEUE_EMPTY )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore )
|
|
|
|
|
{
|
|
|
|
|
const BaseType_t xLoops = 5;
|
|
|
|
|
BaseType_t x, xReturned;
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
yet been taken. */
|
|
|
|
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now it should be possible to take the mutex a number of times. */
|
|
|
|
|
for( x = 0; x < xLoops; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should be possible to give the semaphore the same number of times as it
|
|
|
|
|
was given in the loop above. */
|
|
|
|
|
for( x = 0; x < xLoops; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No more gives should be possible though. */
|
|
|
|
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )
|
|
|
|
|
{
|
|
|
|
|
SemaphoreHandle_t xSemaphore;
|
|
|
|
@ -552,7 +314,7 @@ a counting semaphore. http://www.freertos.org/RTOS-task-notifications.html */
|
|
|
|
|
StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
|
|
|
|
|
/* Create the semaphore. xSemaphoreCreateCountingStatic() has one more
|
|
|
|
|
parameter than the usual xSemaphoreCreateCounting() function. The paraemter
|
|
|
|
|
parameter than the usual xSemaphoreCreateCounting() function. 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 pointer is
|
|
|
|
|
passed as NULL then the structure will be allocated dynamically, just as
|
|
|
|
@ -568,6 +330,18 @@ StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
|
|
|
|
|
/* Delete the semaphore again so the buffers can be reused. */
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
/* Now do the same but using dynamically allocated buffers to ensure the
|
|
|
|
|
delete functions are working correctly in both the static and dynamic
|
|
|
|
|
allocation cases. */
|
|
|
|
|
xSemaphore = xSemaphoreCreateCounting( uxMaxCount, 0 );
|
|
|
|
|
configASSERT( xSemaphore != NULL );
|
|
|
|
|
prvSanityCheckCreatedSemaphore( xSemaphore, uxMaxCount );
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -602,6 +376,18 @@ StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
|
|
|
|
|
/* Delete the semaphore again so the buffers can be reused. */
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
|
|
|
|
|
/* Now do the same using dynamically allocated buffers to ensure the delete
|
|
|
|
|
functions are working correctly in both the static and dynamic memory
|
|
|
|
|
allocation cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xSemaphore = xSemaphoreCreateRecursiveMutex();
|
|
|
|
|
configASSERT( xSemaphore != NULL );
|
|
|
|
|
prvSanityCheckCreatedRecursiveMutex( xSemaphore );
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -645,15 +431,35 @@ static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_
|
|
|
|
|
|
|
|
|
|
/* Delete the queue again so the buffers can be reused. */
|
|
|
|
|
vQueueDelete( xQueue );
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )
|
|
|
|
|
{
|
|
|
|
|
SemaphoreHandle_t xSemaphore;
|
|
|
|
|
BaseType_t xReturned;
|
|
|
|
|
/* Now do the same using a dynamically allocated queue to ensure the delete
|
|
|
|
|
function is working correctly in both the static and dynamic memory
|
|
|
|
|
allocation cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xQueue = xQueueCreate( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */
|
|
|
|
|
sizeof( uint64_t ) ); /* The size of each item. */
|
|
|
|
|
|
|
|
|
|
/* StaticSemaphore_t is a publicly accessible structure that has the same size
|
|
|
|
|
/* The queue handle should equal the static queue structure passed into the
|
|
|
|
|
xQueueCreateStatic() function. */
|
|
|
|
|
configASSERT( xQueue != NULL );
|
|
|
|
|
|
|
|
|
|
/* Ensure the queue passes a few sanity checks as a valid queue. */
|
|
|
|
|
prvSanityCheckCreatedQueue( xQueue );
|
|
|
|
|
|
|
|
|
|
/* Delete the queue again so the buffers can be reused. */
|
|
|
|
|
vQueueDelete( xQueue );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvCreateAndDeleteStaticallyAllocatedMutexes( void )
|
|
|
|
|
{
|
|
|
|
|
SemaphoreHandle_t xSemaphore;
|
|
|
|
|
BaseType_t xReturned;
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
mechanism for applications to know the size of the semaphore (which is dependent
|
|
|
|
|
on the architecture and configuration file settings) without breaking the strict
|
|
|
|
@ -663,7 +469,7 @@ function calls within this function. */
|
|
|
|
|
StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
|
|
|
|
|
/* Create the semaphore. xSemaphoreCreateMutexStatic() has one more
|
|
|
|
|
parameter than the usual xSemaphoreCreateMutex() function. The paraemter
|
|
|
|
|
parameter than the usual xSemaphoreCreateMutex() function. 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 pointer is
|
|
|
|
|
passed as NULL then the structure will be allocated dynamically, just as
|
|
|
|
@ -688,6 +494,34 @@ StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
|
|
|
|
|
/* Delete the semaphore again so the buffers can be reused. */
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
|
|
|
|
|
/* Now do the same using a dynamically allocated mutex to ensure the delete
|
|
|
|
|
function is working correctly in both the static and dynamic allocation
|
|
|
|
|
cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xSemaphore = xSemaphoreCreateMutex();
|
|
|
|
|
|
|
|
|
|
/* The semaphore handle should equal the static semaphore structure
|
|
|
|
|
passed into the xSemaphoreCreateMutexStatic() function. */
|
|
|
|
|
configASSERT( xSemaphore != NULL );
|
|
|
|
|
|
|
|
|
|
/* Take the mutex so the mutex is in the state expected by the
|
|
|
|
|
prvSanityCheckCreatedSemaphore() function. */
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ensure the semaphore passes a few sanity checks as a valid semaphore. */
|
|
|
|
|
prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
|
|
|
|
|
|
|
|
|
|
/* Delete the semaphore again so the buffers can be reused. */
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -707,7 +541,7 @@ a binary semaphore. http://www.freertos.org/RTOS-task-notifications.html */
|
|
|
|
|
StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
|
|
|
|
|
/* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more
|
|
|
|
|
parameter than the usual xSemaphoreCreateBinary() function. The paraemter
|
|
|
|
|
parameter than the usual xSemaphoreCreateBinary() function. 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 pointer is
|
|
|
|
|
passed as NULL then the structure will be allocated dynamically, just as
|
|
|
|
@ -724,11 +558,21 @@ StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
/* Delete the semaphore again so the buffers can be reused. */
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
|
|
|
|
|
/* Now do the same using a dynamically allocated semaphore to check the
|
|
|
|
|
delete function is working correctly in both the static and dynamic
|
|
|
|
|
allocation cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xSemaphore = xSemaphoreCreateBinary();
|
|
|
|
|
configASSERT( xSemaphore != NULL );
|
|
|
|
|
prvSanityCheckCreatedSemaphore( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT );
|
|
|
|
|
vSemaphoreDelete( xSemaphore );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* There isn't a static version of the old and deprecated
|
|
|
|
|
vSemaphoreCreateBinary() macro (because its deprecated!), but check it is
|
|
|
|
|
still functioning correctly when configSUPPORT_STATIC_ALLOCATION is set to
|
|
|
|
|
1. */
|
|
|
|
|
still functioning correctly. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
vSemaphoreCreateBinary( xSemaphore );
|
|
|
|
@ -752,7 +596,9 @@ static void prvTimerCallback( TimerHandle_t xExpiredTimer )
|
|
|
|
|
UBaseType_t *puxVariableToIncrement;
|
|
|
|
|
BaseType_t xReturned;
|
|
|
|
|
|
|
|
|
|
/* Obtain the address of the variable to increment from the timer ID. */
|
|
|
|
|
/* 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
|
|
|
|
|
the address of the variable to increment. */
|
|
|
|
|
puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer );
|
|
|
|
|
|
|
|
|
|
/* Increment the variable to show the timer callback has executed. */
|
|
|
|
@ -762,7 +608,8 @@ BaseType_t xReturned;
|
|
|
|
|
timer. */
|
|
|
|
|
if( *puxVariableToIncrement == staticMAX_TIMER_CALLBACK_EXECUTIONS )
|
|
|
|
|
{
|
|
|
|
|
/* This is called from a timer callback so must not block. */
|
|
|
|
|
/* This is called from a timer callback so must not block. See
|
|
|
|
|
http://www.FreeRTOS.org/FreeRTOS-timers-xTimerStop.html */
|
|
|
|
|
xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
@ -838,6 +685,43 @@ StaticTimer_t xTimerBuffer;
|
|
|
|
|
|
|
|
|
|
/* Just to show the check task that this task is still executing. */
|
|
|
|
|
uxCycleCounter++;
|
|
|
|
|
|
|
|
|
|
/* Now do the same using a dynamically allocated software timer to ensure
|
|
|
|
|
the delete function is working correctly in both the static and dynamic
|
|
|
|
|
allocation cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xTimer = xTimerCreate( "T1", /* Text name for the task. Helps debugging only. Not used by FreeRTOS. */
|
|
|
|
|
xTimerPeriod, /* The period of the timer in ticks. */
|
|
|
|
|
pdTRUE, /* This is an auto-reload timer. */
|
|
|
|
|
( void * ) &uxVariableToIncrement, /* The variable incremented by the test is passed into the timer callback using the timer ID. */
|
|
|
|
|
prvTimerCallback ); /* The function to execute when the timer expires. */
|
|
|
|
|
|
|
|
|
|
configASSERT( xTimer != NULL );
|
|
|
|
|
|
|
|
|
|
uxVariableToIncrement = 0;
|
|
|
|
|
xReturned = xTimerStart( xTimer, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vTaskDelay( xTimerPeriod * staticMAX_TIMER_CALLBACK_EXECUTIONS );
|
|
|
|
|
|
|
|
|
|
if( uxVariableToIncrement != staticMAX_TIMER_CALLBACK_EXECUTIONS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xReturned = xTimerDelete( xTimer, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -871,6 +755,18 @@ StaticEventGroup_t xEventGroupBuffer;
|
|
|
|
|
|
|
|
|
|
/* Delete the event group again so the buffers can be reused. */
|
|
|
|
|
vEventGroupDelete( xEventGroup );
|
|
|
|
|
|
|
|
|
|
/* Now do the same using a dynamically allocated event group to ensure the
|
|
|
|
|
delete function is working correctly in both the static and dynamic
|
|
|
|
|
allocation cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xEventGroup = xEventGroupCreate();
|
|
|
|
|
configASSERT( xEventGroup != NULL );
|
|
|
|
|
prvSanityCheckCreatedEventGroup( xEventGroup );
|
|
|
|
|
vEventGroupDelete( xEventGroup );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -900,11 +796,18 @@ static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
|
|
|
|
"Static", /* Human readable name for the task. */
|
|
|
|
|
configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */
|
|
|
|
|
NULL, /* Parameter to pass into the task. */
|
|
|
|
|
tskIDLE_PRIORITY, /* The priority of the task. */
|
|
|
|
|
uxTaskPriorityGet( NULL ) + 1, /* The priority of the task. */
|
|
|
|
|
&xCreatedTask, /* Handle of the task being created. */
|
|
|
|
|
&( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */
|
|
|
|
|
&xTCBBuffer ); /* The variable that will hold that task's TCB. */
|
|
|
|
|
|
|
|
|
|
/* The created task had a higher priority so should have executed and
|
|
|
|
|
suspended itself by now. */
|
|
|
|
|
if( eTaskGetState( xCreatedTask ) != eSuspended )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the task was created correctly, then delete the task. */
|
|
|
|
|
configASSERT( xReturned == pdPASS );
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
@ -912,6 +815,33 @@ static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
vTaskDelete( xCreatedTask );
|
|
|
|
|
|
|
|
|
|
/* Now do the same using a dynamically allocated task to ensure the delete
|
|
|
|
|
function is working correctly in both the static and dynamic allocation
|
|
|
|
|
cases. */
|
|
|
|
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xTaskCreate(
|
|
|
|
|
prvStaticallyAllocatedTask, /* Function that implements the task. */
|
|
|
|
|
"Static", /* Human readable name for the task. */
|
|
|
|
|
configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */
|
|
|
|
|
NULL, /* Parameter to pass into the task. */
|
|
|
|
|
uxTaskPriorityGet( NULL ) + 1, /* The priority of the task. */
|
|
|
|
|
&xCreatedTask ); /* Handle of the task being created. */
|
|
|
|
|
|
|
|
|
|
if( eTaskGetState( xCreatedTask ) != eSuspended )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configASSERT( xReturned == pdPASS );
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
vTaskDelete( xCreatedTask );
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -919,7 +849,9 @@ static void prvStaticallyAllocatedTask( void *pvParameters )
|
|
|
|
|
{
|
|
|
|
|
( void ) pvParameters;
|
|
|
|
|
|
|
|
|
|
/* The created task doesn't do anything - just waits to get deleted. */
|
|
|
|
|
/* 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
|
|
|
|
|
before deleting it. */
|
|
|
|
|
vTaskSuspend( NULL );
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
@ -957,6 +889,237 @@ const TickType_t xTinyDelay = pdMS_TO_TICKS( ( TickType_t ) 2 );
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedEventGroup( EventGroupHandle_t xEventGroup )
|
|
|
|
|
{
|
|
|
|
|
EventBits_t xEventBits;
|
|
|
|
|
const EventBits_t xFirstTestBits = ( EventBits_t ) 0xaa, xSecondTestBits = ( EventBits_t ) 0x55;
|
|
|
|
|
|
|
|
|
|
/* The event group should not have any bits set yet. */
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != ( EventBits_t ) 0 )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Some some bits, then read them back to check they are as expected. */
|
|
|
|
|
xEventGroupSetBits( xEventGroup, xFirstTestBits );
|
|
|
|
|
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != xFirstTestBits )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xEventGroupSetBits( xEventGroup, xSecondTestBits );
|
|
|
|
|
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != ( xFirstTestBits | xSecondTestBits ) )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finally try clearing some bits too and check that operation proceeds as
|
|
|
|
|
expected. */
|
|
|
|
|
xEventGroupClearBits( xEventGroup, xFirstTestBits );
|
|
|
|
|
|
|
|
|
|
xEventBits = xEventGroupGetBits( xEventGroup );
|
|
|
|
|
|
|
|
|
|
if( xEventBits != xSecondTestBits )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedSemaphore( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount )
|
|
|
|
|
{
|
|
|
|
|
BaseType_t xReturned;
|
|
|
|
|
UBaseType_t x;
|
|
|
|
|
const TickType_t xShortBlockTime = pdMS_TO_TICKS( 10 );
|
|
|
|
|
TickType_t xTickCount;
|
|
|
|
|
|
|
|
|
|
/* The binary semaphore should start 'empty', so a call to xSemaphoreTake()
|
|
|
|
|
should fail. */
|
|
|
|
|
xTickCount = xTaskGetTickCount();
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
|
|
|
|
|
|
|
|
|
if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )
|
|
|
|
|
{
|
|
|
|
|
/* Did not block on the semaphore as long as expected. */
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should be possible to 'give' the semaphore up to a maximum of uxMaxCount
|
|
|
|
|
times. */
|
|
|
|
|
for( x = 0; x < uxMaxCount; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreGive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned == pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Giving the semaphore again should fail, as it is 'full'. */
|
|
|
|
|
xReturned = xSemaphoreGive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configASSERT( uxSemaphoreGetCount( xSemaphore ) == uxMaxCount );
|
|
|
|
|
|
|
|
|
|
/* Should now be possible to 'take' the semaphore up to a maximum of
|
|
|
|
|
uxMaxCount times without blocking. */
|
|
|
|
|
for( x = 0; x < uxMaxCount; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned == pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Back to the starting condition, where the semaphore should not be
|
|
|
|
|
available. */
|
|
|
|
|
xTickCount = xTaskGetTickCount();
|
|
|
|
|
xReturned = xSemaphoreTake( xSemaphore, xShortBlockTime );
|
|
|
|
|
|
|
|
|
|
if( ( ( TickType_t ) ( xTaskGetTickCount() - xTickCount ) ) < xShortBlockTime )
|
|
|
|
|
{
|
|
|
|
|
/* Did not block on the semaphore as long as expected. */
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 );
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedQueue( QueueHandle_t xQueue )
|
|
|
|
|
{
|
|
|
|
|
uint64_t ull, ullRead;
|
|
|
|
|
BaseType_t xReturned, xLoop;
|
|
|
|
|
|
|
|
|
|
/* This test is done twice to ensure the queue storage area wraps. */
|
|
|
|
|
for( xLoop = 0; xLoop < 2; xLoop++ )
|
|
|
|
|
{
|
|
|
|
|
/* A very basic test that the queue can be written to and read from as
|
|
|
|
|
expected. First the queue should be empty. */
|
|
|
|
|
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != errQUEUE_EMPTY )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now it should be possible to write to the queue staticQUEUE_LENGTH_IN_ITEMS
|
|
|
|
|
times. */
|
|
|
|
|
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should not now be possible to write to the queue again. */
|
|
|
|
|
xReturned = xQueueSend( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != errQUEUE_FULL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now read back from the queue to ensure the data read back matches that
|
|
|
|
|
written. */
|
|
|
|
|
for( ull = 0; ull < staticQUEUE_LENGTH_IN_ITEMS; ull++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xQueueReceive( xQueue, &ullRead, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( ullRead != ull )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The queue should be empty again. */
|
|
|
|
|
xReturned = xQueueReceive( xQueue, &ull, staticDONT_BLOCK );
|
|
|
|
|
if( xReturned != errQUEUE_EMPTY )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
static void prvSanityCheckCreatedRecursiveMutex( SemaphoreHandle_t xSemaphore )
|
|
|
|
|
{
|
|
|
|
|
const BaseType_t xLoops = 5;
|
|
|
|
|
BaseType_t x, xReturned;
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
yet been taken. */
|
|
|
|
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now it should be possible to take the mutex a number of times. */
|
|
|
|
|
for( x = 0; x < xLoops; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreTakeRecursive( xSemaphore, staticDONT_BLOCK );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should be possible to give the semaphore the same number of times as it
|
|
|
|
|
was given in the loop above. */
|
|
|
|
|
for( x = 0; x < xLoops; x++ )
|
|
|
|
|
{
|
|
|
|
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdPASS )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No more gives should be possible though. */
|
|
|
|
|
xReturned = xSemaphoreGiveRecursive( xSemaphore );
|
|
|
|
|
|
|
|
|
|
if( xReturned != pdFAIL )
|
|
|
|
|
{
|
|
|
|
|
xErrorOccurred = pdTRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
BaseType_t xAreStaticAllocationTasksStillRunning( void )
|
|
|
|
|
{
|
|
|
|
|
static UBaseType_t uxLastCycleCounter = 0;
|
|
|
|
|