- Rework the StaticAllocation.c common demo file to reflect the changes to the static allocation object create functions from the previous check-in.

- Correct various typos in comments.
- Add xTimerGetPeriod() function (feature request).
pull/4/head
Richard Barry 9 years ago
parent 9dda62372c
commit 26d3770fad

@ -407,28 +407,53 @@ const uint32_t ulMaxDivisor = 0xff, ulDivisorShift = 0x08;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Idle task are declared inside this
opportunity to supply the buffers that will be used by the Idle task as its function then they must be declared static - otherwise they will be allocated on
stack and to hold its TCB. If these are set to NULL then the buffers will the stack and so not exists after this function exits. */
be allocated dynamically, just as if xTaskCreate() had been called. */ static StaticTask_t xIdleTaskTCB;
*ppxIdleTaskTCBBuffer = NULL; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
*ppxIdleTaskStackBuffer = NULL;
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Timer task are declared inside this
opportunity to supply the buffers that will be used by the Timer/RTOS daemon function then they must be declared static - otherwise they will be allocated on
task as its stack and to hold its TCB. If these are set to NULL then the the stack and so not exists after this function exits. */
buffers will be allocated dynamically, just as if xTaskCreate() had been static StaticTask_t xTimerTaskTCB;
called. */ static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = NULL;
*ppxTimerTaskStackBuffer = NULL; /* Pass out a pointer to the StaticTask_t structure in which the Timer
*pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */ task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusTimerTaskStackSize = configMINIMAL_STACK_SIZE;
} }

@ -222,28 +222,52 @@ void vApplicationTickHook( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Idle task are declared inside this
opportunity to supply the buffers that will be used by the Idle task as its function then they must be declared static - otherwise they will be allocated on
stack and to hold its TCB. If these are set to NULL then the buffers will the stack and so not exists after this function exits. */
be allocated dynamically, just as if xTaskCreate() had been called. */ static StaticTask_t xIdleTaskTCB;
*ppxIdleTaskTCBBuffer = NULL; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
*ppxIdleTaskStackBuffer = NULL;
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Timer task are declared inside this
opportunity to supply the buffers that will be used by the Timer/RTOS daemon function then they must be declared static - otherwise they will be allocated on
task as its stack and to hold its TCB. If these are set to NULL then the the stack and so not exists after this function exits. */
buffers will be allocated dynamically, just as if xTaskCreate() had been static StaticTask_t xTimerTaskTCB;
called. */ static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = NULL;
*ppxTimerTaskStackBuffer = NULL; /* Pass out a pointer to the StaticTask_t structure in which the Timer
*pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */ task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusTimerTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/

@ -229,27 +229,51 @@ void vApplicationTickHook( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Idle task are declared inside this
opportunity to supply the buffers that will be used by the Idle task as its function then they must be declared static - otherwise they will be allocated on
stack and to hold its TCB. If these are set to NULL then the buffers will the stack and so not exists after this function exits. */
be allocated dynamically, just as if xTaskCreate() had been called. */ static StaticTask_t xIdleTaskTCB;
*ppxIdleTaskTCBBuffer = NULL; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
*ppxIdleTaskStackBuffer = NULL;
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Timer task are declared inside this
opportunity to supply the buffers that will be used by the Timer/RTOS daemon function then they must be declared static - otherwise they will be allocated on
task as its stack and to hold its TCB. If these are set to NULL then the the stack and so not exists after this function exits. */
buffers will be allocated dynamically, just as if xTaskCreate() had been static StaticTask_t xTimerTaskTCB;
called. */ static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = NULL;
*ppxTimerTaskStackBuffer = NULL; /* Pass out a pointer to the StaticTask_t structure in which the Timer
*pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */ task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusTimerTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/

@ -234,30 +234,54 @@ void vApplicationTickHook( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Idle task are declared inside this
opportunity to supply the buffers that will be used by the Idle task as its function then they must be declared static - otherwise they will be allocated on
stack and to hold its TCB. If these are set to NULL then the buffers will the stack and so not exists after this function exits. */
be allocated dynamically, just as if xTaskCreate() had been called. */ static StaticTask_t xIdleTaskTCB;
*ppxIdleTaskTCBBuffer = NULL; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
*ppxIdleTaskStackBuffer = NULL;
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
{ {
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* If the buffers to be provided to the Timer task are declared inside this
opportunity to supply the buffers that will be used by the Timer/RTOS daemon function then they must be declared static - otherwise they will be allocated on
task as its stack and to hold its TCB. If these are set to NULL then the the stack and so not exists after this function exits. */
buffers will be allocated dynamically, just as if xTaskCreate() had been static StaticTask_t xTimerTaskTCB;
called. */ static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = NULL;
*ppxTimerTaskStackBuffer = NULL; /* Pass out a pointer to the StaticTask_t structure in which the Timer
*pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */ task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusTimerTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/

@ -73,6 +73,8 @@
* rather than the normal dynamically allocated memory, and tests objects being * rather than the normal dynamically allocated memory, and tests objects being
* created and deleted with both statically allocated memory and dynamically * created and deleted with both statically allocated memory and dynamically
* allocated memory. * allocated memory.
*
* See http://www.FreeRTOS.org/Static_Vs_Dynamic_Memory_Allocation.html
*/ */
/* Scheduler include files. */ /* Scheduler include files. */
@ -130,59 +132,51 @@ static void prvTimerCallback( TimerHandle_t xExpiredTimer );
static void prvStaticallyAllocatedTask( void *pvParameters ); static void prvStaticallyAllocatedTask( void *pvParameters );
/* /*
* A function that demonstrates and tests the xTaskCreateStatic() API function * A function that demonstrates and tests the API functions that create and
* by creating and then deleting tasks with both dynamically and statically * delete tasks using both statically and dynamically allocated TCBs and stacks.
* allocated TCBs and stacks.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedTasks( void ); static void prvCreateAndDeleteStaticallyAllocatedTasks( void );
/* /*
* A function that demonstrates and tests the xEventGroupCreateStatic() API * A function that demonstrates and tests the API functions that create and
* function by creating and then deleting event groups using both dynamically * delete event groups using both statically and dynamically allocated RAM.
* and statically allocated event group structures.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void ); static void prvCreateAndDeleteStaticallyAllocatedEventGroups( void );
/* /*
* A function that demonstrates and tests the xQueueCreateStatic() API function * A function that demonstrates and tests the API functions that create and
* by creating and then deleting queues with both dynamically and statically * delete queues using both statically and dynamically allocated RAM.
* allocated queue structures and queue storage areas.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedQueues( void ); static void prvCreateAndDeleteStaticallyAllocatedQueues( void );
/* /*
* A function that demonstrates and tests the xSemaphoreCreateBinaryStatic() API * A function that demonstrates and tests the API functions that create and
* macro by creating and then deleting binary semaphores with both dynamically * delete binary semaphores using both statically and dynamically allocated RAM.
* and statically allocated semaphore structures.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void ); static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void );
/* /*
* A function that demonstrates and tests the xTimerCreateStatic() API macro by * A function that demonstrates and tests the API functions that create and
* creating and then deleting software timers with both dynamically and * delete software timers using both statically and dynamically allocated RAM.
* statically allocated timer structures.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedTimers( void ); static void prvCreateAndDeleteStaticallyAllocatedTimers( void );
/* /*
* A function that demonstrates and tests the xSemaphoreCreateMutexStatic() API * A function that demonstrates and tests the API functions that create and
* macro by creating and then deleting mutexes with both dynamically and * delete mutexes using both statically and dynamically allocated RAM.
* statically allocated semaphore structures.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedMutexes( void ); static void prvCreateAndDeleteStaticallyAllocatedMutexes( void );
/* /*
* A function that demonstrates and tests the xSemaphoreCreateCountingStatic() * A function that demonstrates and tests the API functions that create and
* API macro by creating and then deleting counting semaphores with both * delete counting semaphores using both statically and dynamically allocated
* dynamically and statically allocated semaphore structures. * RAM.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void ); static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void );
/* /*
* A function that demonstrates and tests the * A function that demonstrates and tests the API functions that create and
* xSemaphoreCreateRecursiveMutexStatic() API macro by creating and then * delete recursive mutexes using both statically and dynamically allocated RAM.
* deleting recursive mutexes with both dynamically and statically allocated
* semaphore structures.
*/ */
static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void ); static void prvCreateAndDeleteStaticallyAllocatedRecursiveMutexes( void );
@ -250,9 +244,8 @@ static volatile BaseType_t xErrorOccurred = pdFALSE;
void vStartStaticallyAllocatedTasks( void ) void vStartStaticallyAllocatedTasks( void )
{ {
/* Create a single task, which then repeatedly creates and deletes the /* Create a single task, which then repeatedly creates and deletes the other
task implemented by prvStaticallyAllocatedTask() at various different RTOS objects using both statically and dynamically allocated RAM. */
priorities, and both with and without statically allocated TCB and stack. */
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! */
@ -274,16 +267,16 @@ static void prvStaticallyAllocatedCreator( void *pvParameters )
for( ;; ) for( ;; )
{ {
/* Loop, running functions that create and delete the various objects /* Loop, running functions that create and delete the various RTOS
that can be optionally created using either static or dynamic memory objects that can be optionally created using either static or dynamic
allocation. */ memory allocation. */
prvCreateAndDeleteStaticallyAllocatedTasks(); prvCreateAndDeleteStaticallyAllocatedTasks();
prvCreateAndDeleteStaticallyAllocatedQueues(); 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() ); vTaskDelay( prvGetNextDelayTime() );
/* Just to show the check task that this task is still executing. */
uxCycleCounter++; uxCycleCounter++;
prvCreateAndDeleteStaticallyAllocatedBinarySemaphores(); 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 ) static void prvCreateAndDeleteStaticallyAllocatedCountingSemaphores( void )
{ {
SemaphoreHandle_t xSemaphore; SemaphoreHandle_t xSemaphore;
@ -552,7 +314,7 @@ 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 paraemter 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
@ -568,6 +330,18 @@ 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 );
#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. */ /* 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
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. */ /* Delete the queue again so the buffers can be reused. */
vQueueDelete( xQueue ); vQueueDelete( xQueue );
}
/*-----------------------------------------------------------*/
static void prvCreateAndDeleteStaticallyAllocatedMutexes( void ) /* Now do the same using a dynamically allocated queue to ensure the delete
{ function is working correctly in both the static and dynamic memory
SemaphoreHandle_t xSemaphore; allocation cases. */
BaseType_t xReturned; #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 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
@ -663,7 +469,7 @@ 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 paraemter 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
@ -688,6 +494,34 @@ 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 );
/* 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; StaticSemaphore_t xSemaphoreBuffer;
/* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more /* 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 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
@ -724,11 +558,21 @@ 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 );
/* 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 /* 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 when configSUPPORT_STATIC_ALLOCATION is set to still functioning correctly. */
1. */
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
{ {
vSemaphoreCreateBinary( xSemaphore ); vSemaphoreCreateBinary( xSemaphore );
@ -752,7 +596,9 @@ static void prvTimerCallback( TimerHandle_t xExpiredTimer )
UBaseType_t *puxVariableToIncrement; UBaseType_t *puxVariableToIncrement;
BaseType_t xReturned; 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 ); 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. */
@ -762,7 +608,8 @@ BaseType_t xReturned;
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. */ /* 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 ); xReturned = xTimerStop( xExpiredTimer, staticDONT_BLOCK );
if( xReturned != pdPASS ) if( xReturned != pdPASS )
@ -838,6 +685,43 @@ StaticTimer_t xTimerBuffer;
/* Just to show the check task that this task is still executing. */ /* Just to show the check task that this task is still executing. */
uxCycleCounter++; 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. */ /* 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
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. */ "Static", /* Human readable name for the task. */
configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */ configMINIMAL_STACK_SIZE, /* Task's stack size, in words (not bytes!). */
NULL, /* Parameter to pass into the task. */ 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. */ &xCreatedTask, /* Handle of the task being created. */
&( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */ &( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */
&xTCBBuffer ); /* The variable that will hold that task's TCB. */ &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. */ /* Check the task was created correctly, then delete the task. */
configASSERT( xReturned == pdPASS ); configASSERT( xReturned == pdPASS );
if( xReturned != pdPASS ) if( xReturned != pdPASS )
@ -912,6 +815,33 @@ static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ];
xErrorOccurred = pdTRUE; xErrorOccurred = pdTRUE;
} }
vTaskDelete( xCreatedTask ); 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; ( 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 ); 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 ) BaseType_t xAreStaticAllocationTasksStillRunning( void )
{ {
static UBaseType_t uxLastCycleCounter = 0; static UBaseType_t uxLastCycleCounter = 0;

@ -241,35 +241,52 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
{ {
/* The buffers used by the idle task must be static so they are persistent, and /* If the buffers to be provided to the Idle task are declared inside this
so exist after this function returns. */ function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB; static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* configSUPORT_STATIC_ALLOCATION is set to 1 and /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
configSUPPORT_DYNAMIC_ALLOCATION is 0, so the application must supply the state will be stored. */
buffers that will be used to hold the Idle task data structure and stack. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB; *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack; *ppxIdleTaskStackBuffer = uxIdleTaskStack;
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
{ {
/* The buffers used by the Timer/Daemon task must be static so they are /* If the buffers to be provided to the Timer task are declared inside this
persistent, and so exist after this function returns. */ function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB; static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
/* configSUPPORT_STATIC_ALLOCATION is set to 1, /* Pass out a pointer to the StaticTask_t structure in which the Timer
configSUPPORT_DYNAMIC_ALLOCATION is set to 1, and configUSE_TIMERS is set task's state will be stored. */
to 1, so the application must supply the buffers that will be used to hold
the Timer task data structure and stack. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB; *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack; *ppxTimerTaskStackBuffer = uxTimerTaskStack;
*pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusTimerTaskStackSize = configMINIMAL_STACK_SIZE;
} }

@ -329,7 +329,7 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
( void ) ulLine; ( void ) ulLine;
( void ) pcFileName; ( void ) pcFileName;
printf( "ASSERT! Line %d, file %s\r\n", ulLine, pcFileName ); printf( "ASSERT! Line %d, file %s, GetLastError() %d\r\n", ulLine, pcFileName, GetLastError() );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
@ -410,38 +410,51 @@ const HeapRegion_t xHeapRegions[] =
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
{ {
/* The buffers used by the idle task must be static so they are persistent, and /* If the buffers to be provided to the Idle task are declared inside this
so exist after this function returns. */ function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB; static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
opportunity to supply the buffers that will be used by the Idle task as its state will be stored. */
stack and to hold its TCB. If these are set to NULL then the buffers will
be allocated dynamically, just as if xTaskCreate() had been called. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB; *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack; *ppxIdleTaskStackBuffer = uxIdleTaskStack;
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusIdleTaskStackSize = configMINIMAL_STACK_SIZE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
{ {
/* The buffers used by the Timer/Daemon task must be static so they are /* If the buffers to be provided to the Timer task are declared inside this
persistent, and so exist after this function returns. The stack buffer is function then they must be declared static - otherwise they will be allocated on
not declared here, but globally, as it is checked by a test in a different the stack and so not exists after this function exits. */
file. */
static StaticTask_t xTimerTaskTCB; static StaticTask_t xTimerTaskTCB;
/* configUSE_STATIC_ALLOCATION is set to 1, so the application has the /* Pass out a pointer to the StaticTask_t structure in which the Timer
opportunity to supply the buffers that will be used by the Timer/RTOS daemon task's state will be stored. */
task as its stack and to hold its TCB. If these are set to NULL then the
buffers will be allocated dynamically, just as if xTaskCreate() had been
called. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB; *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack; *ppxTimerTaskStackBuffer = uxTimerTaskStack;
*pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pusTimerTaskStackSize = configMINIMAL_STACK_SIZE;
} }

@ -1616,7 +1616,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
#endif #endif
/* /*
* The registry is provided as a means for kernel aware debuggers to * The queue registry is provided as a means for kernel aware debuggers to
* locate queues, semaphores and mutexes. Call pcQueueGetQueueName() to look * locate queues, semaphores and mutexes. Call pcQueueGetQueueName() to look
* up and return the name of a queue in the queue registry from the queue's * up and return the name of a queue in the queue registry from the queue's
* handle. * handle.

@ -1152,11 +1152,11 @@ typedef QueueHandle_t SemaphoreHandle_t;
/** /**
* semphr.h * semphr.h
* <pre>TaskHandle_t xSemaphoreGetCount( SemaphoreHandle_t xMutex );</pre> * <pre>UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xMutex );</pre>
* *
* If the semaphore is a counting semaphore then xSemaphoreGetCount() returns * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns
* its current count value. If the semaphore is a binary semaphore then * its current count value. If the semaphore is a binary semaphore then
* xSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the
* semaphore is not available. * semaphore is not available.
* *
*/ */

Loading…
Cancel
Save