From b43d9f7a2edd45ee8c3956f72f23df5681b0bbee Mon Sep 17 00:00:00 2001 From: rtel Date: Tue, 19 Jan 2016 13:41:28 +0000 Subject: [PATCH] Implement functionality that allows the memory required to create a queue or semaphore to be allocated statically. Update the standard demo task that tests statically allocated tasks to also test statically allocated queues. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2405 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../CORTEX_A9_Zynq_ZC702/RTOSDemo/src/main.c | 22 +- .../ReadMe_Instructions.url | 5 + .../src/Full_Demo/IntQueueTimer.c | 13 +- .../Demo/Common/Minimal/StaticAllocation.c | 604 ++++++++++++++---- FreeRTOS/Demo/Common/Minimal/countsem.c | 6 +- FreeRTOS/Source/include/FreeRTOS.h | 4 +- FreeRTOS/Source/include/queue.h | 8 +- FreeRTOS/Source/include/semphr.h | 27 +- FreeRTOS/Source/include/task.h | 78 +-- FreeRTOS/Source/queue.c | 40 +- 10 files changed, 594 insertions(+), 213 deletions(-) create mode 100644 FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/ReadMe_Instructions.url diff --git a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/main.c b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/main.c index 2b4b2bf64..2e68aed54 100644 --- a/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/main.c +++ b/FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/main.c @@ -374,15 +374,15 @@ volatile size_t x; /* Extremely crude standard library implementations in lieu of having a C library. */ - for( x = 0; x < xBytes; x++ ) - { - if( pucMem1[ x ] != pucMem2[ x ] ) - { - break; - } - } - - return xBytes - x; + for( x = 0; x < xBytes; x++ ) + { + if( pucMem1[ x ] != pucMem2[ x ] ) + { + break; + } + } + + return xBytes - x; } /*-----------------------------------------------------------*/ @@ -405,7 +405,7 @@ const uint32_t ulMaxDivisor = 0xff, ulDivisorShift = 0x08; } /*-----------------------------------------------------------*/ -void vApplicationGetIdleTaskMemory( DummyTCB_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) +void vApplicationGetIdleTaskMemory( StaticTCB_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize ) { /* configUSE_STATIC_ALLOCATION is set to 1, so the application has the opportunity to supply the buffers that will be used by the Idle task as its @@ -417,7 +417,7 @@ void vApplicationGetIdleTaskMemory( DummyTCB_t **ppxIdleTaskTCBBuffer, StackType } /*-----------------------------------------------------------*/ -void vApplicationGetTimerTaskMemory( DummyTCB_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) +void vApplicationGetTimerTaskMemory( StaticTCB_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize ) { /* configUSE_STATIC_ALLOCATION is set to 1, so the application has the opportunity to supply the buffers that will be used by the Timer/RTOS daemon diff --git a/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/ReadMe_Instructions.url b/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/ReadMe_Instructions.url new file mode 100644 index 000000000..ef60a9c89 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/ReadMe_Instructions.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 +[InternetShortcut] +URL=http://www.freertos.org/Atmel_SAMV7_Cortex-M7_RTOS_Demo.html +IDList= diff --git a/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/Full_Demo/IntQueueTimer.c b/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/Full_Demo/IntQueueTimer.c index 123b350c9..ebdb8e69a 100644 --- a/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/Full_Demo/IntQueueTimer.c +++ b/FreeRTOS/Demo/CORTEX_M7_SAME70_Xplained_AtmelStudio/src/Full_Demo/IntQueueTimer.c @@ -72,7 +72,10 @@ * In this case, there was difficulty generating interrupts from TC1, so only * TC0 is used. Nested interrupts are instead generated by manually pending the * TC1 interrupt from inside the TC0 interrupt handler. This means TC1 must be - * assigned an interrupt priority above TC0. + * assigned an interrupt priority above TC0. [Note this arrangement does not + * really fulfil the purpose of the test as the nesting always occurs at the + * same point in the code, whereas the test is designed to test nesting + * occurring within the queue API functions] */ /* Scheduler includes. */ @@ -119,9 +122,9 @@ uint32_t ulDivider, ulTCCLKS; NVIC_ClearPendingIRQ( TC1_IRQn ); NVIC_SetPriority( TC0_IRQn, tmrLOWER_PRIORITY ); NVIC_SetPriority( TC1_IRQn, tmrHIGHER_PRIORITY ); - NVIC_EnableIRQ( TC0_IRQn ); - NVIC_EnableIRQ( TC1_IRQn ); - + NVIC_EnableIRQ( TC0_IRQn ); + NVIC_EnableIRQ( TC1_IRQn ); + /* Start the timer last of all. */ tc_start( TC0, 0 ); } @@ -144,7 +147,7 @@ static uint32_t ulISRCount = 0; /* Pend an interrupt that will nest with this interrupt. */ NVIC_SetPendingIRQ( TC1_IRQn ); } - + /* Call the IntQ test function for this channel. */ portYIELD_FROM_ISR( xFirstTimerHandler() ); } diff --git a/FreeRTOS/Demo/Common/Minimal/StaticAllocation.c b/FreeRTOS/Demo/Common/Minimal/StaticAllocation.c index 776751ec5..33dd56c57 100644 --- a/FreeRTOS/Demo/Common/Minimal/StaticAllocation.c +++ b/FreeRTOS/Demo/Common/Minimal/StaticAllocation.c @@ -70,12 +70,11 @@ /* * Demonstrates how to create FreeRTOS objects using pre-allocated memory, - * rather than the normal dynamically allocated memory. Currently only tasks - * are being allocated statically. + * rather than the normal dynamically allocated memory. * * Two buffers are required by a task - one that is used by the task as its * stack, and one that holds the task's control block (TCB). - * prvStaticallyAllocatedTaskCreator() creates and deletes tasks with all + * prvStaticallyAllocatedCreator() creates and deletes tasks with all * possible combinations of statically allocated and dynamically allocated * stacks and TCBs. */ @@ -83,6 +82,8 @@ /* Scheduler include files. */ #include "FreeRTOS.h" #include "task.h" +#include "queue.h" +#include "semphr.h" /* Demo program include files. */ #include "StaticAllocation.h" @@ -90,26 +91,60 @@ /* Exclude the entire file if configSUPPORT_STATIC_ALLOCATION is 0. */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) -#define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +/* The priority at which the task that performs the tests is created. */ +#define staticTASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) + +/* The length of the queue, in items, not bytes, used in the queue static +allocation tests. */ +#define staticQUEUE_LENGTH_IN_ITEMS ( 5 ) + +/* A block time of 0 simply means "don't block". */ +#define staticDONT_BLOCK ( ( TickType_t ) 0 ) + +/* Binary semaphores have a maximum count of 1. */ +#define staticBINARY_SEMAPHORE_MAX_COUNT ( 1 ) + + +/*-----------------------------------------------------------*/ /* - * A task that is created multiple times, using both statically and dynamically - * allocated stack and TCB. + * A task that is created and deleted multiple times, using both statically and + * dynamically allocated stack and TCB. */ static void prvStaticallyAllocatedTask( void *pvParameters ); /* - * The task that creates and deletes the prvStaticallyAllocatedTask() task, - * using various priorities, and sometimes with statically and sometimes - * dynamically allocated stack and TCB. + * The task that repeatedly creates and deletes statically allocated tasks, and + * other RTOS objects. */ -static void prvStaticallyAllocatedTaskCreator( void *pvParameters ); +static void prvStaticallyAllocatedCreator( void *pvParameters ); /* * Utility function to create pseudo random numbers. */ static UBaseType_t prvRand( void ); +/* + * 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. + */ +static void prvCreateAndDeleteStaticallyAllocatedTasks( 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. + */ +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. + */ +static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void ); + /* * The task that creates and deletes other tasks has to delay occasionally to * ensure lower priority tasks are not starved of processing time. A pseudo @@ -118,21 +153,32 @@ static UBaseType_t prvRand( void ); */ static TickType_t prvGetNextDelayTime( void ); +/* + * Checks the basic operation of a queue after it has been created. + */ +static void prvCheckQueueFunction( QueueHandle_t xQueue ); + +/* + * Checks the basic operation of a binary semaphore after it has been created. + */ +static void prvCheckSemaphoreFunction( SemaphoreHandle_t xSemaphore, UBaseType_t uxMaxCount ); + /*-----------------------------------------------------------*/ -/* DummyTCB_t is a publicly accessible structure that has the same size and +/* StaticTCB_t is a publicly accessible structure that has the same size and alignment requirements as the real TCB structure. It is provided as a mechanism for applications to know the size of the TCB (which is dependent on the architecture and configuration file settings) without breaking the strict data -hiding policy by exposing the real TCB. This DummyTCB_t variable is passed into -the xTaskCreateStatic() function, and will hold the task's TCB. */ -static DummyTCB_t xTCBBuffer; - -/* This is the stack that will be used by the task. The alignment requirements -for the stack depend on the architecture, and the method of forcing an alignment -is dependent on the compiler, but any bad alignment is corrected inside the -FreeRTOS code. */ -static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ]; +hiding policy by exposing the real TCB. This StaticTCB_t variable is passed +into the xTaskCreateStatic() function that creates the +prvStaticallyAllocatedCreator() task, and will hold the TCB of the created +tasks. */ +static StaticTCB_t xCreatorTaskTCBBuffer; + +/* This is the stack that will be used by the prvStaticallyAllocatedCreator() +task, which is itself created using statically allocated buffers (so without any +dynamic memory allocation). */ +static StackType_t uxCreatorTaskStackBuffer[ configMINIMAL_STACK_SIZE ]; /* Used by the pseudo random number generating function. */ static uint32_t ulNextRand = 0; @@ -141,6 +187,9 @@ static uint32_t ulNextRand = 0; stalled. */ static volatile UBaseType_t uxCycleCounter = 0; +/* A variable that gets set to pdTRUE if an error is detected. */ +static BaseType_t xErrorOccurred = pdFALSE; + /*-----------------------------------------------------------*/ void vStartStaticallyAllocatedTasks( void ) @@ -148,106 +197,437 @@ 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. */ - xTaskCreate( prvStaticallyAllocatedTaskCreator, "StatCreate", configMINIMAL_STACK_SIZE, NULL, staticTASK_PRIORITY, NULL ); + 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. */ + configMINIMAL_STACK_SIZE, /* Size of the buffer passed in as the stack - in words, not bytes! */ + NULL, /* Parameter passed into the task - not used in this case. */ + staticTASK_PRIORITY, /* Priority of the task. */ + NULL, /* Handle of the task being created, not used in this case. */ + &( uxCreatorTaskStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */ + &xCreatorTaskTCBBuffer ); /* The variable that will hold the task's TCB. */ /* Pseudo seed the random number generator. */ ulNextRand = ( uint32_t ) prvRand; } /*-----------------------------------------------------------*/ -static void prvStaticallyAllocatedTaskCreator( void *pvParameters ) +static void prvStaticallyAllocatedCreator( void *pvParameters ) { -TaskHandle_t xCreatedTask; -BaseType_t xReturned; - /* Avoid compiler warnings. */ ( void ) pvParameters; for( ;; ) { - /* Create the task. xTaskCreateStatic() has two more parameters than - the usual xTaskCreate() function. The first new parameter is a pointer to - the pre-allocated stack. The second new parameter is a pointer to the - DummyTCB_t structure that will hold the task's TCB. If either pointer is - passed as NULL then the respective object will be allocated dynamically as - if xTaskCreate() had been called. */ - xReturned = xTaskCreateStatic( - 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. */ - tskIDLE_PRIORITY, /* 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. */ - - /* Check the task was created correctly, then delete the task. */ - configASSERT( xReturned == pdPASS ); - ( void ) xReturned; /* In case configASSERT() is not defined. */ - vTaskDelete( xCreatedTask ); - - /* Ensure lower priority tasks get CPU time. */ - vTaskDelay( prvGetNextDelayTime() ); - - /* Create and delete the task a few times again - testing both static and - dynamic allocation for the stack and TCB. */ - xReturned = xTaskCreateStatic( - 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. */ - staticTASK_PRIORITY + 1, /* The priority of the task. */ - &xCreatedTask, /* Handle of the task being created. */ - NULL, /* This time, dynamically allocate the stack. */ - &xTCBBuffer ); /* The variable that will hold that task's TCB. */ - - configASSERT( xReturned == pdPASS ); - ( void ) xReturned; /* In case configASSERT() is not defined. */ - vTaskDelete( xCreatedTask ); - - /* Just to show the check task that this task is still executing. */ - uxCycleCounter++; - - /* Ensure lower priority tasks get CPU time. */ - vTaskDelay( prvGetNextDelayTime() ); - - xReturned = xTaskCreateStatic( - 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. */ - staticTASK_PRIORITY - 1, /* The priority of the task. */ - &xCreatedTask, /* Handle of the task being created. */ - &( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */ - NULL ); /* This time dynamically allocate the TCB. */ - - configASSERT( xReturned == pdPASS ); - ( void ) xReturned; /* In case configASSERT() is not defined. */ - vTaskDelete( xCreatedTask ); - - /* Ensure lower priority tasks get CPU time. */ - vTaskDelay( prvGetNextDelayTime() ); - - xReturned = xTaskCreateStatic( - 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. */ - staticTASK_PRIORITY, /* The priority of the task. */ - &xCreatedTask, /* Handle of the task being created. */ - NULL, /* This time dynamically allocate the stack and TCB. */ - NULL ); /* This time dynamically allocate the stack and TCB. */ - - configASSERT( xReturned == pdPASS ); - ( void ) xReturned; /* In case configASSERT() is not defined. */ - vTaskDelete( xCreatedTask ); - - /* Ensure lower priority tasks get CPU time. */ - vTaskDelay( prvGetNextDelayTime() ); - - /* Just to show the check task that this task is still executing. */ - uxCycleCounter++; + prvCreateAndDeleteStaticallyAllocatedTasks(); + prvCreateAndDeleteStaticallyAllocatedQueues(); + prvCreateAndDeleteStaticallyAllocatedBinarySemaphores(); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckSemaphoreFunction( 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( ( 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( ( 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 prvCheckQueueFunction( 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 prvCreateAndDeleteStaticallyAllocatedQueues( void ) +{ +QueueHandle_t xQueue; + +/* StaticQueue_t is a publicly accessible structure that has the same size and +alignment requirements as the real queue structure. It is provided as a +mechanism for applications to know the size of the queue (which is dependent on +the architecture and configuration file settings) without breaking the strict +data hiding policy by exposing the real queue internals. This StaticQueue_t +variable is passed into the xQueueCreateStatic() function calls within this +function. */ +static StaticQueue_t xStaticQueue; + +/* The queue storage area must be large enough to hold the maximum number of +items it is possible for the queue to hold at any one time, which equals the +queue length (in items, not bytes) multiplied by the size of each item. In this +case the queue will hold staticQUEUE_LENGTH_IN_ITEMS 64-bit items. See +http://www.freertos.org/Embedded-RTOS-Queues.html */ +static uint8_t ucQueueStorageArea[ staticQUEUE_LENGTH_IN_ITEMS * sizeof( uint64_t ) ]; + + /* Create the queue. xQueueCreateStatic() has two more parameters than the + usual xQueueCreate() function. The first new paraemter is a pointer to the + pre-allocated queue storage area. The second new parameter is a pointer to + the StaticQueue_t structure that will hold the queue state information in + an anonymous way. If either pointer is passed as NULL then the respective + data will be allocated dynamically as if xQueueCreate() had been called. */ + xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */ + sizeof( uint64_t ), /* The size of each item. */ + ucQueueStorageArea, /* The buffer used to hold items within the queue. */ + &xStaticQueue ); /* The static queue structure that will hold the state of the queue. */ + + /* The queue handle should equal the static queue structure passed into the + xQueueCreateStatic() function. */ + configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue ); + + /* Ensure the queue passes a few sanity checks as a valid queue. */ + prvCheckQueueFunction( xQueue ); + + /* Delete the queue again so the buffers can be reused. */ + vQueueDelete( xQueue ); + + + /* The queue created above had a statically allocated queue storage area and + queue structure. Repeat the above with three more times - with different + combinations of static and dynamic allocation. */ + + xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */ + sizeof( uint64_t ), /* The size of each item. */ + NULL, /* Allocate the buffer used to hold items within the queue dynamically. */ + &xStaticQueue ); /* The static queue structure that will hold the state of the queue. */ + + configASSERT( xQueue == ( QueueHandle_t ) &xStaticQueue ); + prvCheckQueueFunction( xQueue ); + vQueueDelete( xQueue ); + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + /* Just to show the check task that this task is still executing. */ + uxCycleCounter++; + + xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */ + sizeof( uint64_t ), /* The size of each item. */ + ucQueueStorageArea, /* The buffer used to hold items within the queue. */ + NULL ); /* The queue structure is allocated dynamically. */ + + prvCheckQueueFunction( xQueue ); + vQueueDelete( xQueue ); + + xQueue = xQueueCreateStatic( staticQUEUE_LENGTH_IN_ITEMS, /* The maximum number of items the queue can hold. */ + sizeof( uint64_t ), /* The size of each item. */ + NULL, /* Allocate the buffer used to hold items within the queue dynamically. */ + NULL ); /* The queue structure is allocated dynamically. */ + + prvCheckQueueFunction( xQueue ); + vQueueDelete( xQueue ); + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + /* Just to show the check task that this task is still executing. */ + uxCycleCounter++; +} +/*-----------------------------------------------------------*/ + +static void prvCreateAndDeleteStaticallyAllocatedBinarySemaphores( void ) +{ +SemaphoreHandle_t xSemaphore; + +/* 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 +data hiding policy by exposing the real semaphore internals. This +StaticSemaphore_t variable is passed into the xSemaphoreCreateBinary() function +calls within this function. NOTE: In most usage scenarios now it is faster and +more memory efficient to use a direct to task notification instead of a binary +semaphore. http://www.freertos.org/RTOS-task-notifications.html */ +static StaticSemaphore_t xSemaphoreBuffer; /* Static so it doesn't use too much stack space. */ + + /* Create the semaphore. xSemaphoreCreateBinaryStatic() has one more + parameter than the usual xSemaphoreCreateBinary() function. The paraemter + 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 + when xSemaphoreCreateBinary() is called. */ + xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer ); + + /* The semaphore handle should equal the static semaphore structure passed + into the xSemaphoreCreateBinaryStatic() function. */ + configASSERT( xSemaphore == ( SemaphoreHandle_t ) &xSemaphoreBuffer ); + + /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */ + prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT ); + + /* Delete the semaphore again so the buffers can be reused. */ + vSemaphoreDelete( xSemaphore ); + + + /* The semaphore created above had a statically allocated semaphore + structure. Repeat the above using NULL as the xSemaphoreCreateBinaryStatic() + parameter so the queue structure is instead allocated dynamically. */ + xSemaphore = xSemaphoreCreateBinaryStatic( NULL ); + + /* Ensure the semaphore passes a few sanity checks as a valid semaphore. */ + prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT ); + + /* Delete the semaphore again so the buffers can be reused. */ + vSemaphoreDelete( xSemaphore ); + + + + /* 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. */ + vSemaphoreCreateBinary( xSemaphore ); + + /* The macro starts with the binary semaphore available, but the test + function expects it to be unavailable. */ + if( xSemaphoreTake( xSemaphore, staticDONT_BLOCK ) == pdFAIL ) + { + xErrorOccurred = pdTRUE; + } + + prvCheckSemaphoreFunction( xSemaphore, staticBINARY_SEMAPHORE_MAX_COUNT ); + vSemaphoreDelete( xSemaphore ); + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + /* Just to show the check task that this task is still executing. */ + uxCycleCounter++; +} +/*-----------------------------------------------------------*/ + +static void prvCreateAndDeleteStaticallyAllocatedTasks( void ) +{ +TaskHandle_t xCreatedTask; +BaseType_t xReturned; + +/* The variable that will hold the TCB of tasks created by this function. See +the comments above the declaration of the xCreatorTaskTCBBuffer variable for +more information. */ +static StaticTCB_t xTCBBuffer; /* Static so it does not use too much stack space. */ + +/* This buffer that will be used as the stack of tasks created by this function. +See the comments above the declaration of the uxCreatorTaskStackBuffer[] array +above for more information. */ +static StackType_t uxStackBuffer[ configMINIMAL_STACK_SIZE ]; + + /* Create the task. xTaskCreateStatic() has two more parameters than + the usual xTaskCreate() function. The first new parameter is a pointer to + the pre-allocated stack. The second new parameter is a pointer to the + StaticTCB_t structure that will hold the task's TCB. If either pointer is + passed as NULL then the respective object will be allocated dynamically as + if xTaskCreate() had been called. */ + xReturned = xTaskCreateStatic( + 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. */ + tskIDLE_PRIORITY, /* 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. */ + + /* Check the task was created correctly, then delete the task. */ + configASSERT( xReturned == pdPASS ); + if( xReturned != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + vTaskDelete( xCreatedTask ); + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + /* Create and delete the task a few times again - testing both static and + dynamic allocation for the stack and TCB. */ + xReturned = xTaskCreateStatic( + 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. */ + staticTASK_PRIORITY + 1, /* The priority of the task. */ + &xCreatedTask, /* Handle of the task being created. */ + NULL, /* This time, dynamically allocate the stack. */ + &xTCBBuffer ); /* The variable that will hold that task's TCB. */ + + configASSERT( xReturned == pdPASS ); + if( xReturned != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + vTaskDelete( xCreatedTask ); + + /* Just to show the check task that this task is still executing. */ + uxCycleCounter++; + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + xReturned = xTaskCreateStatic( + 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. */ + staticTASK_PRIORITY - 1, /* The priority of the task. */ + &xCreatedTask, /* Handle of the task being created. */ + &( uxStackBuffer[ 0 ] ), /* The buffer to use as the task's stack. */ + NULL ); /* This time dynamically allocate the TCB. */ + + configASSERT( xReturned == pdPASS ); + if( xReturned != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + vTaskDelete( xCreatedTask ); + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + xReturned = xTaskCreateStatic( + 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. */ + staticTASK_PRIORITY, /* The priority of the task. */ + &xCreatedTask, /* Handle of the task being created. */ + NULL, /* This time dynamically allocate the stack and TCB. */ + NULL ); /* This time dynamically allocate the stack and TCB. */ + + configASSERT( xReturned == pdPASS ); + if( xReturned != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + vTaskDelete( xCreatedTask ); + + /* Ensure lower priority tasks get CPU time. */ + vTaskDelay( prvGetNextDelayTime() ); + + /* Just to show the check task that this task is still executing. */ + uxCycleCounter++; } /*-----------------------------------------------------------*/ @@ -299,13 +679,21 @@ static UBaseType_t uxLastCycleCounter = 0; BaseType_t xReturn; if( uxCycleCounter == uxLastCycleCounter ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastCycleCounter = uxCycleCounter; + } + + if( xErrorOccurred != pdFALSE ) { xReturn = pdFAIL; } else { xReturn = pdPASS; - uxLastCycleCounter = uxCycleCounter; } return xReturn; diff --git a/FreeRTOS/Demo/Common/Minimal/countsem.c b/FreeRTOS/Demo/Common/Minimal/countsem.c index bf6f2bbb8..3389e4a84 100644 --- a/FreeRTOS/Demo/Common/Minimal/countsem.c +++ b/FreeRTOS/Demo/Common/Minimal/countsem.c @@ -193,7 +193,7 @@ UBaseType_t ux; /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */ for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) { - configASSERT( xSemaphoreGetCount( xSemaphore ) == ( countMAX_COUNT_VALUE - ux ) ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == ( countMAX_COUNT_VALUE - ux ) ); if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS ) { @@ -210,7 +210,7 @@ UBaseType_t ux; /* If the semaphore count is zero then we should not be able to 'take' the semaphore. */ - configASSERT( xSemaphoreGetCount( xSemaphore ) == 0 ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) { xErrorDetected = pdTRUE; @@ -232,7 +232,7 @@ UBaseType_t ux; /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */ for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) { - configASSERT( xSemaphoreGetCount( xSemaphore ) == ux ); + configASSERT( uxSemaphoreGetCount( xSemaphore ) == ux ); if( xSemaphoreGive( xSemaphore ) != pdPASS ) { diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 0e23edcdf..cb75a6fb3 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -922,7 +922,7 @@ typedef struct xSTATIC_TCB eDummy eDummy19; #endif #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - UBaseType_t uxDummy20; + uint8_t uxDummy20; #endif } StaticTCB_t; @@ -964,6 +964,8 @@ typedef struct xSTATIC_QUEUE } StaticQueue_t; +typedef StaticQueue_t StaticSemaphore_t; + #ifdef __cplusplus } diff --git a/FreeRTOS/Source/include/queue.h b/FreeRTOS/Source/include/queue.h index dfaa647fe..a63481b34 100644 --- a/FreeRTOS/Source/include/queue.h +++ b/FreeRTOS/Source/include/queue.h @@ -170,7 +170,11 @@ typedef void * QueueSetMemberHandle_t; * \defgroup xQueueCreate xQueueCreate * \ingroup QueueManagement */ -#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE ) +#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, NULL, NULL, queueQUEUE_TYPE_BASE ) + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue ) xQueueGenericCreate( uxQueueLength, uxItemSize, pucQueueStorage, pxStaticQueue, queueQUEUE_TYPE_BASE ) +#endif /** * queue. h @@ -1554,7 +1558,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION * Generic version of the queue creation function, which is in turn called by * any queue, semaphore or mutex creation function or macro. */ -QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; /* * Queue sets provide a mechanism to allow a task to block (pend) on a read diff --git a/FreeRTOS/Source/include/semphr.h b/FreeRTOS/Source/include/semphr.h index 4a1e72969..a2ae50ec4 100644 --- a/FreeRTOS/Source/include/semphr.h +++ b/FreeRTOS/Source/include/semphr.h @@ -87,6 +87,10 @@ typedef QueueHandle_t SemaphoreHandle_t; * semphr. h *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
* + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the * xSemaphoreCreateBinary() function. Note that binary semaphores created using * the vSemaphoreCreateBinary() macro are created in a state such that the @@ -128,19 +132,23 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ -#define vSemaphoreCreateBinary( xSemaphore ) \ - { \ - ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ - if( ( xSemaphore ) != NULL ) \ - { \ - ( void ) xSemaphoreGive( ( xSemaphore ) ); \ - } \ +#define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, NULL, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ } /** * semphr. h *
SemaphoreHandle_t xSemaphoreCreateBinary( void )
* + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this * xSemaphoreCreateBinary() function. Note that binary semaphores created using * the vSemaphoreCreateBinary() macro are created in a state such that the @@ -182,7 +190,8 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ -#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, NULL, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#define xSemaphoreCreateBinaryStatic( pxStaticQueue ) xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_BINARY_SEMAPHORE ) /** * semphr. h @@ -849,7 +858,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * semaphore is not available. * */ -#define xSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) +#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) #endif /* SEMAPHORE_H */ diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h index 1108d3421..a4d423b27 100644 --- a/FreeRTOS/Source/include/task.h +++ b/FreeRTOS/Source/include/task.h @@ -128,12 +128,6 @@ typedef enum eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ } eNotifyAction; -/* For data hiding purposes. */ -typedef enum -{ - eNothing = 0 -} eDummy; - /* * Used internally only. */ @@ -197,58 +191,6 @@ typedef enum eNotified } eNotifyValue; -/* - * FreeRTOS implements a strict data hiding policy, so the real task control - * block (TCB) structure is not accessible to the application code. However, if - * the application writer wants to statically allocate a TCB then the size of - * the TCB needs to be know. The dummy TCB structure below is used for this - * purpose. Its size will allows match the size of the real TCB, no matter what - * the FreeRTOSConfig.h settings. - */ -typedef struct xDUMMY_TCB -{ - void *pxDummy1; - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xDummy2; - #endif - ListItem_t xDummy3[ 2 ]; - UBaseType_t uxDummy5; - void *pxDummy6; - uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; - #if ( portSTACK_GROWTH > 0 ) - void *pxDummy8; - #endif - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - UBaseType_t uxDummy9; - #endif - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxDummy10[ 2 ]; - #endif - #if ( configUSE_MUTEXES == 1 ) - UBaseType_t uxDummy12[ 2 ]; - #endif - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - void *pxDummy14; - #endif - #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - void pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; - #endif - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulDummy16; - #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - struct _reent xDummy17; - #endif - #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulDummy18; - eDummy eDummy19; - #endif - #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - UBaseType_t uxDummy20; - #endif - -} DummyTCB_t; - /** * Defines the priority used by the idle task. This must not be modified. * @@ -420,14 +362,14 @@ is used in assert() statements. */ UBaseType_t uxPriority, TaskHandle_t *pvCreatedTask, StackType_t *pxStackBuffer, - DummyTCB_t *pxTCBBuffer + StaticTCB_t *pxTCBBuffer ); * * Create a new task and add it to the list of tasks that are ready to run. - * If a task is created using xTaskCreate() then the stack and task control + * If a task is created using xTaskCreate() then the stack and task control * block (TCB) used by the task are allocated dynamically. If a task is created * using xTaskCreateStatic() then the application writer can optionally provide - * the buffers that will hold the task stack and TCB respectively. + * the buffers that will hold the task stack and TCB respectively. * xTaskCreateStatic() therefore allows tasks to be created without any dynamic * memory allocation. * @@ -435,7 +377,7 @@ is used in assert() statements. */ * must be implemented to never return (i.e. continuous loop). * * @param pcName A descriptive name for the task. This is mainly used to - * facilitate debugging. The maximum length of the string is defined by + * facilitate debugging. The maximum length of the string is defined by * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. * * @param usStackDepth The size of the task stack specified as the number of @@ -453,14 +395,14 @@ is used in assert() statements. */ * * @param pxStackBuffer If pxStackBuffer is NULL then the stack used by the * task will be allocated dynamically, just as if the task was created using - * xTaskCreate(). if pxStackBuffer is not NULL then it must point to a + * xTaskCreate(). if pxStackBuffer is not NULL then it must point to a * StackType_t array that has at least usStackDepth indexes - the array will * then be used as the task's stack. * * @param pxTCBBuffer If pxTCBBuffer is NULL then the TCB (which is the * structures used internally within FreeRTOS to hold information on the task) * will be allocated dynamically, just as when xTaskCreate() is used. If - * pxTCBBuffer is not NULL then it must point to a variable of type DummyTCB_T, + * pxTCBBuffer is not NULL then it must point to a variable of type StaticTCB_t, * which will then be used as the TCB of the task being created. * * @return pdPASS if the task was successfully created and added to a ready @@ -476,11 +418,11 @@ is used in assert() statements. */ #define STACK_SIZE 200 // Structure that will hold the TCB of the task being created. - DummyTCB_t xTCB; + StaticTCB_t xTCB; // Buffer that the task being created will use as its stack. StackType_t xStack[ STACK_SIZE ]; - + // Task to be created. void vTaskCode( void * pvParameters ) { @@ -500,7 +442,7 @@ is used in assert() statements. */ xTaskCreate( vTaskCode, // As per xTaskCreate() parameter. "NAME", // As per xTaskCreate() parameter. STACK_SIZE, // As per xTaskCreate() parameter. - &ucParameterToPass, // As per xTaskCreate() parameter. + &ucParameterToPass, // As per xTaskCreate() parameter. tskIDLE_PRIORITY, // As per xTaskCreate() parameter. &xHandle, // As per xTaskCreate() parameter. xStack, // Pointer to the buffer that the task being created will use as its stack. @@ -2153,7 +2095,7 @@ BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGE * Generic version of the task creation function which is in turn called by the * xTaskCreate() and xTaskCreateRestricted() macros. */ -BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, DummyTCB_t * const pxTCBBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTCB_t * const pxTCBBuffer, const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /* * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c index 17a860d98..fc6224d23 100644 --- a/FreeRTOS/Source/queue.c +++ b/FreeRTOS/Source/queue.c @@ -239,6 +239,17 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvIte */ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; +/* + * A queue requires two blocks of memory; a structure to hold the queue state + * and a storage area to hold the items in the queue. The memory is assigned + * by prvAllocateQueueMemory(). If ppucQueueStorage is NULL then the queue + * storage will allocated dynamically, otherwise the buffer passed in + * ppucQueueStorage will be used. If pxStaticQueue is NULL then the queue + * structure will be allocated dynamically, otherwise the buffer pointed to by + * pxStaticQueue will be used. + */ +static Queue_t *prvAllocateQueueMemory( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t **ppucQueueStorage, StaticQueue_t *pxStaticQueue ); + #if ( configUSE_QUEUE_SETS == 1 ) /* * Checks to see if a queue is a member of a queue set, and if so, notifies @@ -331,8 +342,8 @@ size_t xQueueSizeInBytes; #if( ( configASSERT_DEFINED == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) { /* Sanity check that the size of the structure used to declare a - variable of type DummyQueue_t or DummySemaphore_t equals the size of the - real queue and semaphore structures. */ + variable of type StaticQueue_t or StaticSemaphore_t equals the size of + the real queue and semaphore structures. */ volatile size_t xSize = sizeof( StaticQueue_t ); configASSERT( xSize == sizeof( Queue_t ) ); } @@ -345,9 +356,9 @@ size_t xQueueSizeInBytes; } else { - /* The queue is one byte longer than asked for to make wrap checking - easier/faster. */ - xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + /* Allocate enough space to hold the maximum number of items that can be + in the queue at any time. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } #if( configSUPPORT_STATIC_ALLOCATION == 0 ) @@ -361,7 +372,7 @@ size_t xQueueSizeInBytes; storage area. */ *ppucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t ); } - + /* The pxStaticQueue parameter is not used. Remove compiler warnings. */ ( void ) pxStaticQueue; } @@ -399,8 +410,17 @@ size_t xQueueSizeInBytes; { vPortFree( ( void * ) pxNewQueue ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } + pxNewQueue = NULL; } + else + { + mtCOVERAGE_TEST_MARKER(); + } } else { @@ -1860,6 +1880,10 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; freed. */ vPortFree( pxQueue->pcHead ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } if( ( pxQueue->ucStaticAllocationFlags & queueSTATICALLY_ALLOCATED_QUEUE_STRUCT ) == 0 ) { @@ -1867,6 +1891,10 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; free. */ vPortFree( pxQueue ); } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #endif } -- 2.39.5