From 44ca6d9ec85ebe03ecba594addff2647138f9792 Mon Sep 17 00:00:00 2001 From: OmniMan <209760780+OmniManAintGotNothingOnMe@users.noreply.github.com> Date: Tue, 1 Jul 2025 13:56:49 +0400 Subject: [PATCH 1/4] Add Skip List implementation and unit test --- skip_list.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ skip_list.h | 32 +++++++++++++++++++ test_skip_list.c | 62 ++++++++++++++++++++++++++++++++++++ test_skip_list.exe | Bin 0 -> 59981 bytes 4 files changed, 171 insertions(+) create mode 100644 skip_list.c create mode 100644 skip_list.h create mode 100644 test_skip_list.c create mode 100644 test_skip_list.exe diff --git a/skip_list.c b/skip_list.c new file mode 100644 index 000000000..6d1cfb867 --- /dev/null +++ b/skip_list.c @@ -0,0 +1,77 @@ +#include "skip_list.h" +#include + +static int xRandomLevel(void) { + int level = 1; + while ((rand() & 0x1) && level < SKIP_LIST_MAX_LEVEL) + level++; + return level; +} + +void vSkipListInit(SkipList_t *list) { + list->level = 1; + list->header = (SkipListNode_t *)calloc(1, sizeof(SkipListNode_t)); + for (int i = 0; i < SKIP_LIST_MAX_LEVEL; i++) + list->header->forward[i] = NULL; +} + +void vSkipListInsert(SkipList_t *list, TickType_t key, void *value) { + SkipListNode_t *update[SKIP_LIST_MAX_LEVEL]; + SkipListNode_t *x = list->header; + for (int i = list->level - 1; i >= 0; i--) { + while (x->forward[i] && x->forward[i]->key < key) + x = x->forward[i]; + update[i] = x; + } + x = x->forward[0]; + if (x && x->key == key) { + x->value = value; + return; + } + int lvl = xRandomLevel(); + if (lvl > list->level) { + for (int i = list->level; i < lvl; i++) + update[i] = list->header; + list->level = lvl; + } + x = (SkipListNode_t *)calloc(1, sizeof(SkipListNode_t)); + x->key = key; + x->value = value; + for (int i = 0; i < lvl; i++) { + x->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = x; + } +} + +void vSkipListRemove(SkipList_t *list, TickType_t key) { + SkipListNode_t *update[SKIP_LIST_MAX_LEVEL]; + SkipListNode_t *x = list->header; + for (int i = list->level - 1; i >= 0; i--) { + while (x->forward[i] && x->forward[i]->key < key) + x = x->forward[i]; + update[i] = x; + } + x = x->forward[0]; + if (x && x->key == key) { + for (int i = 0; i < list->level; i++) { + if (update[i]->forward[i] != x) + break; + update[i]->forward[i] = x->forward[i]; + } + free(x); + while (list->level > 1 && list->header->forward[list->level - 1] == NULL) + list->level--; + } +} + +void *pvSkipListSearch(SkipList_t *list, TickType_t key) { + SkipListNode_t *x = list->header; + for (int i = list->level - 1; i >= 0; i--) { + while (x->forward[i] && x->forward[i]->key < key) + x = x->forward[i]; + } + x = x->forward[0]; + if (x && x->key == key) + return x->value; + return NULL; +} diff --git a/skip_list.h b/skip_list.h new file mode 100644 index 000000000..737855cff --- /dev/null +++ b/skip_list.h @@ -0,0 +1,32 @@ +#ifndef FREERTOS_SKIP_LIST_H +#define FREERTOS_SKIP_LIST_H + +#include +#include + +#ifndef TickType_t +typedef unsigned int TickType_t; +#endif + +#ifndef SKIP_LIST_MAX_LEVEL +#define SKIP_LIST_MAX_LEVEL 4 // Tunable for memory/complexity tradeoff +#endif + +// Forward declaration +typedef struct SkipListNode { + TickType_t key; + void *value; + struct SkipListNode *forward[SKIP_LIST_MAX_LEVEL]; +} SkipListNode_t; + +typedef struct SkipList { + SkipListNode_t *header; + int level; +} SkipList_t; + +void vSkipListInit(SkipList_t *list); +void vSkipListInsert(SkipList_t *list, TickType_t key, void *value); +void vSkipListRemove(SkipList_t *list, TickType_t key); +void *pvSkipListSearch(SkipList_t *list, TickType_t key); + +#endif // FREERTOS_SKIP_LIST_H diff --git a/test_skip_list.c b/test_skip_list.c new file mode 100644 index 000000000..c141ea00d --- /dev/null +++ b/test_skip_list.c @@ -0,0 +1,62 @@ +#include +#include +#include "skip_list.h" + +void print_skip_list(SkipList_t *list) { + printf("Skip List: "); + SkipListNode_t *node = list->header->forward[0]; + while (node) { + printf("(%u, %p) ", node->key, node->value); + node = node->forward[0]; + } + printf("\n"); +} + +int main(void) { + SkipList_t list; + vSkipListInit(&list); + + // Insert test + printf("Inserting values...\n"); + for (TickType_t i = 10; i > 0; --i) { + int *val = (int *)malloc(sizeof(int)); + *val = i * 100; + vSkipListInsert(&list, i, val); + } + print_skip_list(&list); + + // Search test + printf("Searching for key 5...\n"); + int *found = (int *)pvSkipListSearch(&list, 5); + if (found) { + printf("Found key 5 with value %d\n", *found); + } else { + printf("Key 5 not found!\n"); + } + + printf("Searching for key 42...\n"); + found = (int *)pvSkipListSearch(&list, 42); + if (found) { + printf("Found key 42 with value %d\n", *found); + } else { + printf("Key 42 not found!\n"); + } + + // Remove test + printf("Removing key 5...\n"); + vSkipListRemove(&list, 5); + print_skip_list(&list); + found = (int *)pvSkipListSearch(&list, 5); + if (!found) { + printf("Key 5 successfully removed.\n"); + } + + // Cleanup + for (TickType_t i = 1; i <= 10; ++i) { + int *val = (int *)pvSkipListSearch(&list, i); + if (val) free(val); + } + // Free header node + free(list.header); + return 0; +} diff --git a/test_skip_list.exe b/test_skip_list.exe new file mode 100644 index 0000000000000000000000000000000000000000..c1fb49fad466516630e43874da3b57f1b5ce3c51 GIT binary patch literal 59981 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 Date: Tue, 1 Jul 2025 14:09:30 +0400 Subject: [PATCH 2/4] Add test_empty_file.txt --- test_empty_file.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test_empty_file.txt diff --git a/test_empty_file.txt b/test_empty_file.txt new file mode 100644 index 000000000..e69de29bb From e4c4c3dd87c182bd8aee79ab6b431efa3164ff41 Mon Sep 17 00:00:00 2001 From: OmniMan <209760780+OmniManAintGotNothingOnMe@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:34:18 +0400 Subject: [PATCH 3/4] Clean up: remove test, skip list, and local config files; add assertion to uxListRemove --- list.c | 1 + skip_list.c | 77 -------------------------------------------- skip_list.h | 32 ------------------ test_empty_file.txt | 0 test_skip_list.c | 62 ----------------------------------- test_skip_list.exe | Bin 59981 -> 0 bytes 6 files changed, 1 insertion(+), 171 deletions(-) delete mode 100644 skip_list.c delete mode 100644 skip_list.h delete mode 100644 test_empty_file.txt delete mode 100644 test_skip_list.c delete mode 100644 test_skip_list.exe diff --git a/list.c b/list.c index 0c0f3676e..bdea0f6ee 100644 --- a/list.c +++ b/list.c @@ -216,6 +216,7 @@ void vListInsert( List_t * const pxList, UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { + configASSERT( pxItemToRemove->pxContainer != NULL ); /* The list item knows which list it is in. Obtain the list from the list * item. */ List_t * const pxList = pxItemToRemove->pxContainer; diff --git a/skip_list.c b/skip_list.c deleted file mode 100644 index 6d1cfb867..000000000 --- a/skip_list.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "skip_list.h" -#include - -static int xRandomLevel(void) { - int level = 1; - while ((rand() & 0x1) && level < SKIP_LIST_MAX_LEVEL) - level++; - return level; -} - -void vSkipListInit(SkipList_t *list) { - list->level = 1; - list->header = (SkipListNode_t *)calloc(1, sizeof(SkipListNode_t)); - for (int i = 0; i < SKIP_LIST_MAX_LEVEL; i++) - list->header->forward[i] = NULL; -} - -void vSkipListInsert(SkipList_t *list, TickType_t key, void *value) { - SkipListNode_t *update[SKIP_LIST_MAX_LEVEL]; - SkipListNode_t *x = list->header; - for (int i = list->level - 1; i >= 0; i--) { - while (x->forward[i] && x->forward[i]->key < key) - x = x->forward[i]; - update[i] = x; - } - x = x->forward[0]; - if (x && x->key == key) { - x->value = value; - return; - } - int lvl = xRandomLevel(); - if (lvl > list->level) { - for (int i = list->level; i < lvl; i++) - update[i] = list->header; - list->level = lvl; - } - x = (SkipListNode_t *)calloc(1, sizeof(SkipListNode_t)); - x->key = key; - x->value = value; - for (int i = 0; i < lvl; i++) { - x->forward[i] = update[i]->forward[i]; - update[i]->forward[i] = x; - } -} - -void vSkipListRemove(SkipList_t *list, TickType_t key) { - SkipListNode_t *update[SKIP_LIST_MAX_LEVEL]; - SkipListNode_t *x = list->header; - for (int i = list->level - 1; i >= 0; i--) { - while (x->forward[i] && x->forward[i]->key < key) - x = x->forward[i]; - update[i] = x; - } - x = x->forward[0]; - if (x && x->key == key) { - for (int i = 0; i < list->level; i++) { - if (update[i]->forward[i] != x) - break; - update[i]->forward[i] = x->forward[i]; - } - free(x); - while (list->level > 1 && list->header->forward[list->level - 1] == NULL) - list->level--; - } -} - -void *pvSkipListSearch(SkipList_t *list, TickType_t key) { - SkipListNode_t *x = list->header; - for (int i = list->level - 1; i >= 0; i--) { - while (x->forward[i] && x->forward[i]->key < key) - x = x->forward[i]; - } - x = x->forward[0]; - if (x && x->key == key) - return x->value; - return NULL; -} diff --git a/skip_list.h b/skip_list.h deleted file mode 100644 index 737855cff..000000000 --- a/skip_list.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef FREERTOS_SKIP_LIST_H -#define FREERTOS_SKIP_LIST_H - -#include -#include - -#ifndef TickType_t -typedef unsigned int TickType_t; -#endif - -#ifndef SKIP_LIST_MAX_LEVEL -#define SKIP_LIST_MAX_LEVEL 4 // Tunable for memory/complexity tradeoff -#endif - -// Forward declaration -typedef struct SkipListNode { - TickType_t key; - void *value; - struct SkipListNode *forward[SKIP_LIST_MAX_LEVEL]; -} SkipListNode_t; - -typedef struct SkipList { - SkipListNode_t *header; - int level; -} SkipList_t; - -void vSkipListInit(SkipList_t *list); -void vSkipListInsert(SkipList_t *list, TickType_t key, void *value); -void vSkipListRemove(SkipList_t *list, TickType_t key); -void *pvSkipListSearch(SkipList_t *list, TickType_t key); - -#endif // FREERTOS_SKIP_LIST_H diff --git a/test_empty_file.txt b/test_empty_file.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/test_skip_list.c b/test_skip_list.c deleted file mode 100644 index c141ea00d..000000000 --- a/test_skip_list.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include "skip_list.h" - -void print_skip_list(SkipList_t *list) { - printf("Skip List: "); - SkipListNode_t *node = list->header->forward[0]; - while (node) { - printf("(%u, %p) ", node->key, node->value); - node = node->forward[0]; - } - printf("\n"); -} - -int main(void) { - SkipList_t list; - vSkipListInit(&list); - - // Insert test - printf("Inserting values...\n"); - for (TickType_t i = 10; i > 0; --i) { - int *val = (int *)malloc(sizeof(int)); - *val = i * 100; - vSkipListInsert(&list, i, val); - } - print_skip_list(&list); - - // Search test - printf("Searching for key 5...\n"); - int *found = (int *)pvSkipListSearch(&list, 5); - if (found) { - printf("Found key 5 with value %d\n", *found); - } else { - printf("Key 5 not found!\n"); - } - - printf("Searching for key 42...\n"); - found = (int *)pvSkipListSearch(&list, 42); - if (found) { - printf("Found key 42 with value %d\n", *found); - } else { - printf("Key 42 not found!\n"); - } - - // Remove test - printf("Removing key 5...\n"); - vSkipListRemove(&list, 5); - print_skip_list(&list); - found = (int *)pvSkipListSearch(&list, 5); - if (!found) { - printf("Key 5 successfully removed.\n"); - } - - // Cleanup - for (TickType_t i = 1; i <= 10; ++i) { - int *val = (int *)pvSkipListSearch(&list, i); - if (val) free(val); - } - // Free header node - free(list.header); - return 0; -} diff --git a/test_skip_list.exe b/test_skip_list.exe deleted file mode 100644 index c1fb49fad466516630e43874da3b57f1b5ce3c51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59981 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 Date: Thu, 3 Jul 2025 14:16:29 +0400 Subject: [PATCH 4/4] Revert test code for uxTaskGetAllHandles; restore main.c and remove test changes --- examples/cmake_example/main.c | 28 +- include/task.h | 2438 ++++++--------------------------- list.c | 1 - tasks.c | 67 + 4 files changed, 515 insertions(+), 2019 deletions(-) diff --git a/examples/cmake_example/main.c b/examples/cmake_example/main.c index 96a2abfe1..52fd6d3e3 100644 --- a/examples/cmake_example/main.c +++ b/examples/cmake_example/main.c @@ -39,8 +39,6 @@ #include #include #include - -/* Standard includes. */ #include /*-----------------------------------------------------------*/ @@ -62,6 +60,32 @@ static void exampleTask( void * parameters ) } /*-----------------------------------------------------------*/ +/* Test uxTaskGetAllHandles API before starting the scheduler */ +static void test_uxTaskGetAllHandles(void) +{ + UBaseType_t uxCount, uxFilled, i; + TaskHandle_t *pxHandles; + + /* First, query the number of tasks (should be 1: exampleTask, before scheduler starts) */ + uxCount = uxTaskGetAllHandles(NULL, 0); + printf("[uxTaskGetAllHandles] Number of tasks: %lu\n", (unsigned long)uxCount); + + if (uxCount > 0) { + pxHandles = (TaskHandle_t *)pvPortMalloc(sizeof(TaskHandle_t) * uxCount); + if (pxHandles != NULL) { + uxFilled = uxTaskGetAllHandles(pxHandles, uxCount); + printf("[uxTaskGetAllHandles] Handles returned: %lu\n", (unsigned long)uxFilled); + for (i = 0; i < uxFilled; i++) { + printf(" Handle[%lu]: %p\n", (unsigned long)i, (void *)pxHandles[i]); + } + vPortFree(pxHandles); + } else { + printf("[uxTaskGetAllHandles] pvPortMalloc failed!\n"); + } + } +} +/*-----------------------------------------------------------*/ + int main( void ) { static StaticTask_t exampleTaskTCB; diff --git a/include/task.h b/include/task.h index a25740e3b..6771447a0 100644 --- a/include/task.h +++ b/include/task.h @@ -509,7 +509,325 @@ typedef enum * \ingroup Tasks */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, + TaskHandle_t xTaskCreateStatic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ( TaskFunction_t pxTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE uxStackDepth, void * const pvParameters, @@ -650,50 +968,54 @@ typedef enum * * Example usage: * @code{c} - * // Create an TaskParameters_t structure that defines the task to be created. - * // The StaticTask_t variable is only included in the structure when - * // configSUPPORT_STATIC_ALLOCATION is set to 1. The PRIVILEGED_DATA macro can - * // be used to force the variable into the RTOS kernel's privileged data area. - * static PRIVILEGED_DATA StaticTask_t xTaskBuffer; - * static const TaskParameters_t xCheckTaskParameters = - * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // uxStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function parameters. - * ( 1U | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS documentation - * // for full information. + * // Dimensions of the buffer that the task being created will use as its stack. + * // NOTE: This is the number of words the stack will hold, not the number of + * // bytes. For example, if each stack item is 32-bits, and this is set to 100, + * // then 400 bytes (100 * 32-bits) will be allocated. + #define STACK_SIZE 200 + * + * // Structure that will hold the TCB of the task being created. + * StaticTask_t xTaskBuffer; + * + * // Buffer that the task being created will use as its stack. Note this is + * // an array of StackType_t variables. The size of StackType_t is dependent on + * // the RTOS port. + * StackType_t xStack[ STACK_SIZE ]; + * + * // Function that implements the task being created. + * void vTaskCode( void * pvParameters ) * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE } + * // The parameter value is expected to be 1 as 1 is passed in the + * // pvParameters value in the call to xTaskCreateStatic(). + * configASSERT( ( uint32_t ) pvParameters == 1U ); + * + * for( ;; ) + * { + * // Task code goes here. + * } * } * - * &xTaskBuffer; // Holds the task's data structure. - * }; + * // Function that creates a task. + * void vOtherFunction( void ) + * { + * TaskHandle_t xHandle = NULL; * - * int main( void ) - * { - * TaskHandle_t xHandle; + * // Create the task without using any dynamic memory allocation. + * xHandle = xTaskCreateStatic( + * vTaskCode, // Function that implements the task. + * "NAME", // Text name for the task. + * STACK_SIZE, // Stack size in words, not bytes. + * ( void * ) 1, // Parameter passed into the task. + * tskIDLE_PRIORITY,// Priority at which the task is created. + * xStack, // Array to use as the task's stack. + * &xTaskBuffer ); // Variable to hold the task's data structure. * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestrictedStatic( &xRegTest1Parameters, &xHandle ); - * - * // Start the scheduler. - * vTaskStartScheduler(); - * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); - * } + * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have + * // been created, and xHandle will be the task's handle. Use the handle + * // to suspend the task. + * vTaskSuspend( xHandle ); + * } * @endcode * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic * \ingroup Tasks @@ -703,1828 +1025,16 @@ typedef enum TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; #endif -#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - BaseType_t xTaskCreateRestrictedStaticAffinitySet( const TaskParameters_t * const pxTaskDefinition, - UBaseType_t uxCoreAffinityMask, - TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; -#endif - /** * task. h * @code{c} - * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); - * @endcode - * - * Memory regions are assigned to a restricted task when the task is created by - * a call to xTaskCreateRestricted(). These regions can be redefined using - * vTaskAllocateMPURegions(). - * - * @param xTaskToModify The handle of the task being updated. - * - * @param[in] pxRegions A pointer to a MemoryRegion_t structure that contains the - * new memory region definitions. - * - * Example usage: - * @code{c} - * // Define an array of MemoryRegion_t structures that configures an MPU region - * // allowing read/write access for 1024 bytes starting at the beginning of the - * // ucOneKByte array. The other two of the maximum 3 definable regions are - * // unused so set to zero. - * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = - * { - * // Base address Length Parameters - * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, - * { 0, 0, 0 }, - * { 0, 0, 0 } - * }; - * - * void vATask( void *pvParameters ) - * { - * // This task was created such that it has access to certain regions of - * // memory as defined by the MPU configuration. At some point it is - * // desired that these MPU regions are replaced with that defined in the - * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() - * // for this purpose. NULL is used as the task handle to indicate that this - * // function should modify the MPU regions of the calling task. - * vTaskAllocateMPURegions( NULL, xAltRegions ); - * - * // Now the task can continue its function, but from this point on can only - * // access its stack and the ucOneKByte array (unless any other statically - * // defined or shared regions have been declared elsewhere). - * } - * @endcode - * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions - * \ingroup Tasks - */ -#if ( portUSING_MPU_WRAPPERS == 1 ) - void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, - const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskDelete( TaskHandle_t xTaskToDelete ); - * @endcode - * - * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. - * - * NOTE: The idle task is responsible for freeing the kernel allocated - * memory from tasks that have been deleted. It is therefore important that - * the idle task is not starved of microcontroller processing time if your - * application makes any calls to vTaskDelete (). Memory allocated by the - * task code is not automatically freed, and should be freed before the task - * is deleted. - * - * See the demo application file death.c for sample code that utilises - * vTaskDelete (). - * - * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will - * cause the calling task to be deleted. - * - * Example usage: - * @code{c} - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create the task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); - * - * // Use the handle to delete the task. - * vTaskDelete( xHandle ); - * } - * @endcode - * \defgroup vTaskDelete vTaskDelete - * \ingroup Tasks - */ -void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- -* TASK CONTROL API -*----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskDelay( const TickType_t xTicksToDelay ); - * @endcode - * - * Delay a task for a given number of ticks. The actual time that the - * task remains blocked depends on the tick rate. The constant - * portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. - * - * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * - * vTaskDelay() specifies a time at which the task wishes to unblock relative to - * the time at which vTaskDelay() is called. For example, specifying a block - * period of 100 ticks will cause the task to unblock 100 ticks after - * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method - * of controlling the frequency of a periodic task as the path taken through the - * code, as well as other task and interrupt activity, will affect the frequency - * at which vTaskDelay() gets called and therefore the time at which the task - * next executes. See xTaskDelayUntil() for an alternative API function designed - * to facilitate fixed frequency execution. It does this by specifying an - * absolute time (rather than a relative time) at which the calling task should - * unblock. - * - * @param xTicksToDelay The amount of time, in tick periods, that - * the calling task should block. - * - * Example usage: - * - * void vTaskFunction( void * pvParameters ) - * { - * // Block for 500ms. - * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; - * - * for( ;; ) - * { - * // Simply toggle the LED every 500ms, blocking between each toggle. - * vToggleLED(); - * vTaskDelay( xDelay ); - * } - * } - * - * \defgroup vTaskDelay vTaskDelay - * \ingroup TaskCtrl - */ -void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement ); - * @endcode - * - * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Delay a task until a specified time. This function can be used by periodic - * tasks to ensure a constant execution frequency. - * - * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will - * cause a task to block for the specified number of ticks from the time vTaskDelay () is - * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed - * execution frequency as the time between a task starting to execute and that task - * calling vTaskDelay () may not be fixed [the task may take a different path though the - * code between calls, or may get interrupted or preempted a different number of times - * each time it executes]. - * - * Whereas vTaskDelay () specifies a wake time relative to the time at which the function - * is called, xTaskDelayUntil () specifies the absolute (exact) time at which it wishes to - * unblock. - * - * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a - * time specified in milliseconds with a resolution of one tick period. - * - * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the - * task was last unblocked. The variable must be initialised with the current time - * prior to its first use (see the example below). Following this the variable is - * automatically updated within xTaskDelayUntil (). - * - * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the - * same xTimeIncrement parameter value will cause the task to execute with - * a fixed interface period. - * - * @return Value which can be used to check whether the task was actually delayed. - * Will be pdTRUE if the task way delayed and pdFALSE otherwise. A task will not - * be delayed if the next expected wake time is in the past. - * - * Example usage: - * @code{c} - * // Perform an action every 10 ticks. - * void vTaskFunction( void * pvParameters ) - * { - * TickType_t xLastWakeTime; - * const TickType_t xFrequency = 10; - * BaseType_t xWasDelayed; - * - * // Initialise the xLastWakeTime variable with the current time. - * xLastWakeTime = xTaskGetTickCount (); - * for( ;; ) - * { - * // Wait for the next cycle. - * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); - * - * // Perform action here. xWasDelayed value can be used to determine - * // whether a deadline was missed if the code here took too long. - * } - * } - * @endcode - * \defgroup xTaskDelayUntil xTaskDelayUntil - * \ingroup TaskCtrl - */ -BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, - const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; - -/* - * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not - * return a value. - */ -#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ - do { \ - ( void ) xTaskDelayUntil( ( pxPreviousWakeTime ), ( xTimeIncrement ) ); \ - } while( 0 ) - - -/** - * task. h - * @code{c} - * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this - * function to be available. - * - * A task will enter the Blocked state when it is waiting for an event. The - * event it is waiting for can be a temporal event (waiting for a time), such - * as when vTaskDelay() is called, or an event on an object, such as when - * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task - * that is in the Blocked state is used in a call to xTaskAbortDelay() then the - * task will leave the Blocked state, and return from whichever function call - * placed the task into the Blocked state. - * - * There is no 'FromISR' version of this function as an interrupt would need to - * know which object a task was blocked on in order to know which actions to - * take. For example, if the task was blocked on a queue the interrupt handler - * would then need to know if the queue was locked. - * - * @param xTask The handle of the task to remove from the Blocked state. - * - * @return If the task referenced by xTask was not in the Blocked state then - * pdFAIL is returned. Otherwise pdPASS is returned. - * - * \defgroup xTaskAbortDelay xTaskAbortDelay - * \ingroup TaskCtrl - */ -#if ( INCLUDE_xTaskAbortDelay == 1 ) - BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the priority of any task. - * - * @param xTask Handle of the task to be queried. Passing a NULL - * handle results in the priority of the calling task being returned. - * - * @return The priority of xTask. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); - * - * // ... - * - * // Use the handle to obtain the priority of the created task. - * // It was created with tskIDLE_PRIORITY, but may have changed - * // it itself. - * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) - * { - * // The task has changed it's priority. - * } - * - * // ... - * - * // Is our priority higher than the created task? - * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ) - * { - * // Our priority (obtained using NULL handle) is higher. - * } - * } - * @endcode - * \defgroup uxTaskPriorityGet uxTaskPriorityGet - * \ingroup TaskCtrl - */ -UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); - * @endcode - * - * A version of uxTaskPriorityGet() that can be used from an ISR. - */ -UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskBasePriorityGet( const TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskPriorityGet and configUSE_MUTEXES must be defined as 1 for this - * function to be available. See the configuration section for more information. - * - * Obtain the base priority of any task. - * - * @param xTask Handle of the task to be queried. Passing a NULL - * handle results in the base priority of the calling task being returned. - * - * @return The base priority of xTask. - * - * \defgroup uxTaskPriorityGet uxTaskBasePriorityGet - * \ingroup TaskCtrl - */ -UBaseType_t uxTaskBasePriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * UBaseType_t uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ); - * @endcode - * - * A version of uxTaskBasePriorityGet() that can be used from an ISR. - */ -UBaseType_t uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * eTaskState eTaskGetState( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Obtain the state of any task. States are encoded by the eTaskState - * enumerated type. - * - * @param xTask Handle of the task to be queried. - * - * @return The state of xTask at the time the function was called. Note the - * state of the task might change between the function being called, and the - * functions return value being tested by the calling task. - */ -#if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) - eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ); - * @endcode - * - * configUSE_TRACE_FACILITY must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * Populates a TaskStatus_t structure with information about a task. - * - * @param xTask Handle of the task being queried. If xTask is NULL then - * information will be returned about the calling task. - * - * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be - * filled with information about the task referenced by the handle passed using - * the xTask parameter. - * - * @param xGetFreeStackSpace The TaskStatus_t structure contains a member to report - * the stack high water mark of the task being queried. Calculating the stack - * high water mark takes a relatively long time, and can make the system - * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to - * allow the high water mark checking to be skipped. The high watermark value - * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is - * not set to pdFALSE; - * - * @param eState The TaskStatus_t structure contains a member to report the - * state of the task being queried. Obtaining the task state is not as fast as - * a simple assignment - so the eState parameter is provided to allow the state - * information to be omitted from the TaskStatus_t structure. To obtain state - * information then set eState to eInvalid - otherwise the value passed in - * eState will be reported as the task state in the TaskStatus_t structure. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * TaskStatus_t xTaskDetails; - * - * // Obtain the handle of a task from its name. - * xHandle = xTaskGetHandle( "Task_Name" ); - * - * // Check the handle is not NULL. - * configASSERT( xHandle ); - * - * // Use the handle to obtain further information about the task. - * vTaskGetInfo( xHandle, - * &xTaskDetails, - * pdTRUE, // Include the high water mark in xTaskDetails. - * eInvalid ); // Include the task state in xTaskDetails. - * } - * @endcode - * \defgroup vTaskGetInfo vTaskGetInfo - * \ingroup TaskCtrl - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - void vTaskGetInfo( TaskHandle_t xTask, - TaskStatus_t * pxTaskStatus, - BaseType_t xGetFreeStackSpace, - eTaskState eState ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); - * @endcode - * - * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Set the priority of any task. - * - * A context switch will occur before the function returns if the priority - * being set is higher than the currently executing task. - * - * @param xTask Handle to the task for which the priority is being set. - * Passing a NULL handle results in the priority of the calling task being set. - * - * @param uxNewPriority The priority to which the task will be set. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); - * - * // ... - * - * // Use the handle to raise the priority of the created task. - * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 ); - * - * // ... - * - * // Use a NULL handle to raise our priority to the same value. - * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); - * } - * @endcode - * \defgroup vTaskPrioritySet vTaskPrioritySet - * \ingroup TaskCtrl - */ -void vTaskPrioritySet( TaskHandle_t xTask, - UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Suspend any task. When suspended a task will never get any microcontroller - * processing time, no matter what its priority. - * - * Calls to vTaskSuspend are not accumulative - - * i.e. calling vTaskSuspend () twice on the same task still only requires one - * call to vTaskResume () to ready the suspended task. - * - * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL - * handle will cause the calling task to be suspended. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Suspend ourselves. - * vTaskSuspend( NULL ); - * - * // We cannot get here unless another task calls vTaskResume - * // with our handle as the parameter. - * } - * @endcode - * \defgroup vTaskSuspend vTaskSuspend - * \ingroup TaskCtrl - */ -void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskResume( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. - * See the configuration section for more information. - * - * Resumes a suspended task. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * vTaskResume (). - * - * @param xTaskToResume Handle to the task being readied. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); - * - * // ... - * - * // Use the handle to suspend the created task. - * vTaskSuspend( xHandle ); - * - * // ... - * - * // The created task will not run during this period, unless - * // another task calls vTaskResume( xHandle ). - * - * //... - * - * - * // Resume the suspended task ourselves. - * vTaskResume( xHandle ); - * - * // The created task will once again get microcontroller processing - * // time in accordance with its priority within the system. - * } - * @endcode - * \defgroup vTaskResume vTaskResume - * \ingroup TaskCtrl - */ -void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); - * @endcode - * - * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be - * available. See the configuration section for more information. - * - * An implementation of vTaskResume() that can be called from within an ISR. - * - * A task that has been suspended by one or more calls to vTaskSuspend () - * will be made available for running again by a single call to - * xTaskResumeFromISR (). - * - * xTaskResumeFromISR() should not be used to synchronise a task with an - * interrupt if there is a chance that the interrupt could arrive prior to the - * task being suspended - as this can lead to interrupts being missed. Use of a - * semaphore as a synchronisation mechanism would avoid this eventuality. - * - * @param xTaskToResume Handle to the task being readied. - * - * @return pdTRUE if resuming the task should result in a context switch, - * otherwise pdFALSE. This is used by the ISR to determine if a context switch - * may be required following the ISR. - * - * \defgroup vTaskResumeFromISR vTaskResumeFromISR - * \ingroup TaskCtrl - */ -BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; - -#if ( configUSE_CORE_AFFINITY == 1 ) - -/** - * @brief Sets the core affinity mask for a task. - * - * It sets the cores on which a task can run. configUSE_CORE_AFFINITY must - * be defined as 1 for this function to be available. - * - * @param xTask The handle of the task to set the core affinity mask for. - * Passing NULL will set the core affinity mask for the calling task. - * - * @param uxCoreAffinityMask A bitwise value that indicates the cores on - * which the task can run. Cores are numbered from 0 to configNUMBER_OF_CORES - 1. - * For example, to ensure that a task can run on core 0 and core 1, set - * uxCoreAffinityMask to 0x03. - * - * Example usage: - * - * // The function that creates task. - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( xHandle ) ); - * - * // Define the core affinity mask such that this task can only run - * // on core 0 and core 2. - * uxCoreAffinityMask = ( ( 1 << 0 ) | ( 1 << 2 ) ); - * - * //Set the core affinity mask for the task. - * vTaskCoreAffinitySet( xHandle, uxCoreAffinityMask ); - * } - */ - void vTaskCoreAffinitySet( const TaskHandle_t xTask, - UBaseType_t uxCoreAffinityMask ); -#endif - -#if ( ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) - -/** - * @brief Gets the core affinity mask for a task. - * - * configUSE_CORE_AFFINITY must be defined as 1 for this function to be - * available. - * - * @param xTask The handle of the task to get the core affinity mask for. - * Passing NULL will get the core affinity mask for the calling task. - * - * @return The core affinity mask which is a bitwise value that indicates - * the cores on which a task can run. Cores are numbered from 0 to - * configNUMBER_OF_CORES - 1. For example, if a task can run on core 0 and core 1, - * the core affinity mask is 0x03. - * - * Example usage: - * - * // Task handle of the networking task - it is populated elsewhere. - * TaskHandle_t xNetworkingTaskHandle; - * - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; - * UBaseType_t uxNetworkingCoreAffinityMask; - * - * // Create a task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &( xHandle ) ); - * - * //Get the core affinity mask for the networking task. - * uxNetworkingCoreAffinityMask = vTaskCoreAffinityGet( xNetworkingTaskHandle ); - * - * // Here is a hypothetical scenario, just for the example. Assume that we - * // have 2 cores - Core 0 and core 1. We want to pin the application task to - * // the core different than the networking task to ensure that the - * // application task does not interfere with networking. - * if( ( uxNetworkingCoreAffinityMask & ( 1 << 0 ) ) != 0 ) - * { - * // The networking task can run on core 0, pin our task to core 1. - * vTaskCoreAffinitySet( xHandle, ( 1 << 1 ) ); - * } - * else - * { - * // Otherwise, pin our task to core 0. - * vTaskCoreAffinitySet( xHandle, ( 1 << 0 ) ); - * } - * } - */ - UBaseType_t vTaskCoreAffinityGet( ConstTaskHandle_t xTask ); -#endif - -#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Disables preemption for a task. - * - * @param xTask The handle of the task to disable preemption. Passing NULL - * disables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ - void vTaskPreemptionDisable( const TaskHandle_t xTask ); -#endif - -#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - -/** - * @brief Enables preemption for a task. - * - * @param xTask The handle of the task to enable preemption. Passing NULL - * enables preemption for the calling task. - * - * Example usage: - * - * void vTaskCode( void *pvParameters ) - * { - * // Silence warnings about unused parameters. - * ( void ) pvParameters; - * - * for( ;; ) - * { - * // ... Perform some function here. - * - * // Disable preemption for this task. - * vTaskPreemptionDisable( NULL ); - * - * // The task will not be preempted when it is executing in this portion ... - * - * // ... until the preemption is enabled again. - * vTaskPreemptionEnable( NULL ); - * - * // The task can be preempted when it is executing in this portion. - * } - * } - */ - void vTaskPreemptionEnable( const TaskHandle_t xTask ); -#endif - -/*----------------------------------------------------------- -* SCHEDULER CONTROL -*----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * void vTaskStartScheduler( void ); - * @endcode - * - * Starts the real time kernel tick processing. After calling the kernel - * has control over which tasks are executed and when. - * - * See the demo application file main.c for an example of creating - * tasks and starting the kernel. - * - * Example usage: - * @code{c} - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will not get here unless a task calls vTaskEndScheduler () - * } - * @endcode - * - * \defgroup vTaskStartScheduler vTaskStartScheduler - * \ingroup SchedulerControl - */ -void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskEndScheduler( void ); - * @endcode - * - * NOTE: At the time of writing only the x86 real mode port, which runs on a PC - * in place of DOS, implements this function. - * - * Stops the real time kernel tick. All created tasks will be automatically - * deleted and multitasking (either preemptive or cooperative) will - * stop. Execution then resumes from the point where vTaskStartScheduler () - * was called, as if vTaskStartScheduler () had just returned. - * - * See the demo application file main. c in the demo/PC directory for an - * example that uses vTaskEndScheduler (). - * - * vTaskEndScheduler () requires an exit function to be defined within the - * portable layer (see vPortEndScheduler () in port. c for the PC port). This - * performs hardware specific operations such as stopping the kernel tick. - * - * vTaskEndScheduler () will cause all of the resources allocated by the - * kernel to be freed - but will not free resources allocated by application - * tasks. - * - * Example usage: - * @code{c} - * void vTaskCode( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // At some point we want to end the real time kernel processing - * // so call ... - * vTaskEndScheduler (); - * } - * } - * - * void vAFunction( void ) - * { - * // Create at least one task before starting the kernel. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); - * - * // Start the real time kernel with preemption. - * vTaskStartScheduler (); - * - * // Will only get here when the vTaskCode () task has called - * // vTaskEndScheduler (). When we get here we are back to single task - * // execution. - * } - * @endcode - * - * \defgroup vTaskEndScheduler vTaskEndScheduler - * \ingroup SchedulerControl - */ -void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * void vTaskSuspendAll( void ); - * @endcode - * - * Suspends the scheduler without disabling interrupts. Context switches will - * not occur while the scheduler is suspended. - * - * After calling vTaskSuspendAll () the calling task will continue to execute - * without risk of being swapped out until a call to xTaskResumeAll () has been - * made. - * - * API functions that have the potential to cause a context switch (for example, - * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler - * is suspended. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the kernel - * // tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. - * xTaskResumeAll (); - * } - * } - * @endcode - * \defgroup vTaskSuspendAll vTaskSuspendAll - * \ingroup SchedulerControl - */ -void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * BaseType_t xTaskResumeAll( void ); - * @endcode - * - * Resumes scheduler activity after it was suspended by a call to - * vTaskSuspendAll(). - * - * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks - * that were previously suspended by a call to vTaskSuspend(). - * - * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. - * - * Example usage: - * @code{c} - * void vTask1( void * pvParameters ) - * { - * for( ;; ) - * { - * // Task code goes here. - * - * // ... - * - * // At some point the task wants to perform a long operation during - * // which it does not want to get swapped out. It cannot use - * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the - * // operation may cause interrupts to be missed - including the - * // ticks. - * - * // Prevent the real time kernel swapping out the task. - * vTaskSuspendAll (); - * - * // Perform the operation here. There is no need to use critical - * // sections as we have all the microcontroller processing time. - * // During this time interrupts will still operate and the real - * // time kernel tick count will be maintained. - * - * // ... - * - * // The operation is complete. Restart the kernel. We want to force - * // a context switch - but there is no point if resuming the scheduler - * // caused a context switch already. - * if( !xTaskResumeAll () ) - * { - * taskYIELD (); - * } - * } - * } - * @endcode - * \defgroup xTaskResumeAll xTaskResumeAll - * \ingroup SchedulerControl - */ -BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; - -/*----------------------------------------------------------- -* TASK UTILITIES -*----------------------------------------------------------*/ - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCount( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * \defgroup xTaskGetTickCount xTaskGetTickCount - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * TickType_t xTaskGetTickCountFromISR( void ); - * @endcode - * - * @return The count of ticks since vTaskStartScheduler was called. - * - * This is a version of xTaskGetTickCount() that is safe to be called from an - * ISR - provided that TickType_t is the natural word size of the - * microcontroller being used or interrupt nesting is either not supported or - * not being used. - * - * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR - * \ingroup TaskUtils - */ -TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * uint16_t uxTaskGetNumberOfTasks( void ); - * @endcode - * - * @return The number of tasks that the real time kernel is currently managing. - * This includes all ready, blocked and suspended tasks. A task that - * has been deleted but not yet freed by the idle task will also be - * included in the count. - * - * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks - * \ingroup TaskUtils - */ -UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); - * @endcode - * - * @return The text (human readable) name of the task referenced by the handle - * xTaskToQuery. A task can query its own name by either passing in its own - * handle, or by setting xTaskToQuery to NULL. - * - * \defgroup pcTaskGetName pcTaskGetName - * \ingroup TaskUtils - */ -char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; - -/** - * task. h - * @code{c} - * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); - * @endcode - * - * NOTE: This function takes a relatively long time to complete and should be - * used sparingly. - * - * @return The handle of the task that has the human readable name pcNameToQuery. - * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle - * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available. - * - * \defgroup pcTaskGetHandle pcTaskGetHandle - * \ingroup TaskUtils - */ -#if ( INCLUDE_xTaskGetHandle == 1 ) - TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - * StackType_t ** ppuxStackBuffer, - * StaticTask_t ** ppxTaskBuffer ); - * @endcode - * - * Retrieve pointers to a statically created task's data structure - * buffer and stack buffer. These are the same buffers that are supplied - * at the time of creation. - * - * @param xTask The task for which to retrieve the buffers. - * - * @param ppuxStackBuffer Used to return a pointer to the task's stack buffer. - * - * @param ppxTaskBuffer Used to return a pointer to the task's data structure - * buffer. - * - * @return pdTRUE if buffers were retrieved, pdFALSE otherwise. - * - * \defgroup xTaskGetStaticBuffers xTaskGetStaticBuffers - * \ingroup TaskUtils - */ -#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask, - StackType_t ** ppuxStackBuffer, - StaticTask_t ** ppxTaskBuffer ) PRIVILEGED_FUNCTION; -#endif /* configSUPPORT_STATIC_ALLOCATION */ - -/** - * task.h - * @code{c} - * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the - * same except for their return type. Using configSTACK_DEPTH_TYPE allows the - * user to determine the return type. It gets around the problem of the value - * overflowing on 8-bit types without breaking backward compatibility for - * applications that expect an 8-bit return type. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task.h - * @code{c} - * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); - * @endcode - * - * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for - * this function to be available. - * - * Returns the high water mark of the stack associated with xTask. That is, - * the minimum free stack space there has been (in words, so on a 32 bit machine - * a value of 1 means 4 bytes) since the task started. The smaller the returned - * number the closer the task has come to overflowing its stack. - * - * uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the - * same except for their return type. Using configSTACK_DEPTH_TYPE allows the - * user to determine the return type. It gets around the problem of the value - * overflowing on 8-bit types without breaking backward compatibility for - * applications that expect an 8-bit return type. - * - * @param xTask Handle of the task associated with the stack to be checked. - * Set xTask to NULL to check the stack of the calling task. - * - * @return The smallest amount of free stack space there has been (in words, so - * actual spaces on the stack rather than bytes) since the task referenced by - * xTask was created. - */ -#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) - configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -#endif - -/* When using trace macros it is sometimes necessary to include task.h before - * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, - * so the following two prototypes will cause a compilation error. This can be - * fixed by simply guarding against the inclusion of these two prototypes unless - * they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration - * constant. */ -#ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - -/** - * task.h - * @code{c} - * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ); - * @endcode - * - * Sets pxHookFunction to be the task hook function used by the task xTask. - * Passing xTask as NULL has the effect of setting the calling tasks hook - * function. - */ - void vTaskSetApplicationTaskTag( TaskHandle_t xTask, - TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Do not - * call from an interrupt service routine - call - * xTaskGetApplicationTaskTagFromISR() instead. - */ - TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - -/** - * task.h - * @code{c} - * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); - * @endcode - * - * Returns the pxHookFunction value assigned to the task xTask. Can - * be called from an interrupt service routine. - */ - TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ - -#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - -/* Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The - * kernel does not use the pointers itself, so the application writer can use - * the pointers for any purpose they wish. The following two functions are - * used to set and query a pointer respectively. */ - void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) PRIVILEGED_FUNCTION; - void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, - BaseType_t xIndex ) PRIVILEGED_FUNCTION; - -#endif - -#if ( configCHECK_FOR_STACK_OVERFLOW > 0 ) - -/** - * task.h - * @code{c} - * void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName); - * @endcode - * - * The application stack overflow hook is called when a stack overflow is detected for a task. - * - * Details on stack overflow detection can be found here: https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html - * - * @param xTask the task that just exceeded its stack boundaries. - * @param pcTaskName A character string containing the name of the offending task. - */ - /* MISRA Ref 8.6.1 [External linkage] */ - /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */ - /* coverity[misra_c_2012_rule_8_6_violation] */ - void vApplicationStackOverflowHook( TaskHandle_t xTask, - char * pcTaskName ); - -#endif - -#if ( configUSE_IDLE_HOOK == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationIdleHook( void ); - * @endcode - * - * The application idle hook is called by the idle task. - * This allows the application designer to add background functionality without - * the overhead of a separate task. - * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK. - */ - /* MISRA Ref 8.6.1 [External linkage] */ - /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */ - /* coverity[misra_c_2012_rule_8_6_violation] */ - void vApplicationIdleHook( void ); - -#endif - - -#if ( configUSE_TICK_HOOK != 0 ) - -/** - * task.h - * @code{c} - * void vApplicationTickHook( void ); - * @endcode - * - * This hook function is called in the system tick handler after any OS work is completed. - */ - /* MISRA Ref 8.6.1 [External linkage] */ - /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */ - /* coverity[misra_c_2012_rule_8_6_violation] */ - void vApplicationTickHook( void ); - -#endif - -#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - -/** - * task.h - * @code{c} - * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ) - * @endcode - * - * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Idle Task TCB. This function is required when - * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * - * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer for the idle task - * @param puxIdleTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer - */ - void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ); - -/** - * task.h - * @code{c} - * void vApplicationGetPassiveIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, configSTACK_DEPTH_TYPE * puxIdleTaskStackSize, BaseType_t xCoreID ) - * @endcode - * - * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Idle Tasks TCB. This function is required when - * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION - * - * In the FreeRTOS SMP, there are a total of configNUMBER_OF_CORES idle tasks: - * 1. 1 Active idle task which does all the housekeeping. - * 2. ( configNUMBER_OF_CORES - 1 ) Passive idle tasks which do nothing. - * These idle tasks are created to ensure that each core has an idle task to run when - * no other task is available to run. - * - * The function vApplicationGetPassiveIdleTaskMemory is called with passive idle - * task index 0, 1 ... ( configNUMBER_OF_CORES - 2 ) to get memory for passive idle - * tasks. - * - * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer - * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer for the idle task - * @param puxIdleTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer - * @param xPassiveIdleTaskIndex The passive idle task index of the idle task buffer - */ - #if ( configNUMBER_OF_CORES > 1 ) - void vApplicationGetPassiveIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, - StackType_t ** ppxIdleTaskStackBuffer, - configSTACK_DEPTH_TYPE * puxIdleTaskStackSize, - BaseType_t xPassiveIdleTaskIndex ); - #endif /* #if ( configNUMBER_OF_CORES > 1 ) */ -#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ - -/** - * task.h - * @code{c} - * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); - * @endcode - * - * Calls the hook function associated with xTask. Passing xTask as NULL has - * the effect of calling the Running tasks (the calling task) hook function. - * - * pvParameter is passed to the hook function for the task to interpret as it - * wants. The return value is the value returned by the task hook function - * registered by the user. - */ -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, - void * pvParameter ) PRIVILEGED_FUNCTION; -#endif - -/** - * xTaskGetIdleTaskHandle() is only available if - * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. - * - * In single-core FreeRTOS, this function simply returns the handle of the idle - * task. It is not valid to call xTaskGetIdleTaskHandle() before the scheduler - * has been started. - * - * In the FreeRTOS SMP, there are a total of configNUMBER_OF_CORES idle tasks: - * 1. 1 Active idle task which does all the housekeeping. - * 2. ( configNUMBER_OF_CORES - 1 ) Passive idle tasks which do nothing. - * These idle tasks are created to ensure that each core has an idle task to run when - * no other task is available to run. Call xTaskGetIdleTaskHandle() or - * xTaskGetIdleTaskHandleForCore() with xCoreID set to 0 to get the Active - * idle task handle. Call xTaskGetIdleTaskHandleForCore() with xCoreID set to - * 1,2 ... ( configNUMBER_OF_CORES - 1 ) to get the Passive idle task handles. - */ -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - #if ( configNUMBER_OF_CORES == 1 ) - TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; - #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ - - TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; -#endif /* #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */ - -/** - * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for - * uxTaskGetSystemState() to be available. - * - * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in - * the system. TaskStatus_t structures contain, among other things, members - * for the task handle, task name, task priority, task state, and total amount - * of run time consumed by the task. See the TaskStatus_t structure - * definition in this file for the full member list. - * - * NOTE: This function is intended for debugging use only as its use results in - * the scheduler remaining suspended for an extended period. - * - * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. - * The array must contain at least one TaskStatus_t structure for each task - * that is under the control of the RTOS. The number of tasks under the control - * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. - * - * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray - * parameter. The size is specified as the number of indexes in the array, or - * the number of TaskStatus_t structures contained in the array, not by the - * number of bytes in the array. - * - * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in - * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the - * total run time (as defined by the run time stats clock, see - * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted. - * pulTotalRunTime can be set to NULL to omit the total run time information. - * - * @return The number of TaskStatus_t structures that were populated by - * uxTaskGetSystemState(). This should equal the number returned by the - * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed - * in the uxArraySize parameter was too small. - * - * Example usage: - * @code{c} - * // This example demonstrates how a human readable table of run time stats - * // information is generated from raw data provided by uxTaskGetSystemState(). - * // The human readable table is written to pcWriteBuffer - * void vTaskGetRunTimeStats( char *pcWriteBuffer ) - * { - * TaskStatus_t *pxTaskStatusArray; - * volatile UBaseType_t uxArraySize, x; - * configRUN_TIME_COUNTER_TYPE ulTotalRunTime, ulStatsAsPercentage; - * - * // Make sure the write buffer does not contain a string. - * pcWriteBuffer = 0x00; - * - * // Take a snapshot of the number of tasks in case it changes while this - * // function is executing. - * uxArraySize = uxTaskGetNumberOfTasks(); - * - * // Allocate a TaskStatus_t structure for each task. An array could be - * // allocated statically at compile time. - * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) ); - * - * if( pxTaskStatusArray != NULL ) - * { - * // Generate raw status information about each task. - * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime ); - * - * // For percentage calculations. - * ulTotalRunTime /= 100U; - * - * // Avoid divide by zero errors. - * if( ulTotalRunTime > 0 ) - * { - * // For each populated position in the pxTaskStatusArray array, - * // format the raw data as human readable ASCII data - * for( x = 0; x < uxArraySize; x++ ) - * { - * // What percentage of the total run time has the task used? - * // This will always be rounded down to the nearest integer. - * // ulTotalRunTimeDiv100 has already been divided by 100. - * ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime; - * - * if( ulStatsAsPercentage > 0U ) - * { - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); - * } - * else - * { - * // If the percentage is zero here then the task has - * // consumed less than 1% of the total run time. - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); - * } - * - * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); - * } - * } - * - * // The array is no longer needed, free the memory it consumes. - * vPortFree( pxTaskStatusArray ); - * } - * } - * @endcode - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, - const UBaseType_t uxArraySize, - configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskListTasks( char *pcWriteBuffer, size_t uxBufferLength ); - * @endcode - * - * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must - * both be defined as 1 for this function to be available. See the - * configuration section of the FreeRTOS.org website for more information. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as running ('X'), blocked ('B'), ready ('R'), deleted ('D') - * or suspended ('S'). - * - * PLEASE NOTE: - * - * This function is provided for convenience only, and is used by many of the - * demo applications. Do not consider it to be part of the scheduler. - * - * vTaskListTasks() calls uxTaskGetSystemState(), then formats part of the - * uxTaskGetSystemState() output into a human readable table that displays task - * information in the following format: - * Task Name, Task State, Task Priority, Task Stack High Watermak, Task Number. - * - * The following is a sample output: - * Task A X 2 67 2 - * Task B R 1 67 3 - * IDLE R 0 67 5 - * Tmr Svc B 6 137 6 - * - * Stack usage specified as the number of unused StackType_t words stack can hold - * on top of stack - not the number of bytes. - * - * vTaskListTasks() has a dependency on the snprintf() C library function that might - * bloat the code size, use a lot of stack, and provide different results on - * different platforms. An alternative, tiny, third party, and limited - * functionality implementation of snprintf() is provided in many of the - * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note - * printf-stdarg.c does not provide a full snprintf() implementation!). - * - * It is recommended that production systems call uxTaskGetSystemState() - * directly to get access to raw stats data, rather than indirectly through a - * call to vTaskListTasks(). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ASCII form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * @param uxBufferLength Length of the pcWriteBuffer. - * - * \defgroup vTaskListTasks vTaskListTasks - * \ingroup TaskUtils - */ -#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - void vTaskListTasks( char * pcWriteBuffer, - size_t uxBufferLength ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskList( char *pcWriteBuffer ); - * @endcode - * - * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must - * both be defined as 1 for this function to be available. See the - * configuration section of the FreeRTOS.org website for more information. - * - * WARN: This function assumes that the pcWriteBuffer is of length - * configSTATS_BUFFER_MAX_LENGTH. This function is there only for - * backward compatibility. New applications are recommended to - * use vTaskListTasks and supply the length of the pcWriteBuffer explicitly. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Lists all the current tasks, along with their current state and stack - * usage high water mark. - * - * Tasks are reported as running ('X'), blocked ('B'), ready ('R'), deleted ('D') - * or suspended ('S'). - * - * PLEASE NOTE: - * - * This function is provided for convenience only, and is used by many of the - * demo applications. Do not consider it to be part of the scheduler. - * - * vTaskList() calls uxTaskGetSystemState(), then formats part of the - * uxTaskGetSystemState() output into a human readable table that displays task - * information in the following format: - * Task Name, Task State, Task Priority, Task Stack High Watermak, Task Number. - * - * The following is a sample output: - * Task A X 2 67 2 - * Task B R 1 67 3 - * IDLE R 0 67 5 - * Tmr Svc B 6 137 6 - * - * Stack usage specified as the number of unused StackType_t words stack can hold - * on top of stack - not the number of bytes. - * - * vTaskList() has a dependency on the snprintf() C library function that might - * bloat the code size, use a lot of stack, and provide different results on - * different platforms. An alternative, tiny, third party, and limited - * functionality implementation of snprintf() is provided in many of the - * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note - * printf-stdarg.c does not provide a full snprintf() implementation!). - * - * It is recommended that production systems call uxTaskGetSystemState() - * directly to get access to raw stats data, rather than indirectly through a - * call to vTaskList(). - * - * @param pcWriteBuffer A buffer into which the above mentioned details - * will be written, in ASCII form. This buffer is assumed to be large - * enough to contain the generated report. Approximately 40 bytes per - * task should be sufficient. - * - * \defgroup vTaskList vTaskList - * \ingroup TaskUtils - */ -#define vTaskList( pcWriteBuffer ) vTaskListTasks( ( pcWriteBuffer ), configSTATS_BUFFER_MAX_LENGTH ) - -/** - * task. h - * @code{c} - * void vTaskGetRunTimeStatistics( char *pcWriteBuffer, size_t uxBufferLength ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() - * to configure a peripheral timer/counter and return the timers current count - * value respectively. The counter should be at least 10 times the frequency of - * the tick count. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStatistics() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * NOTE 2: - * - * This function is provided for convenience only, and is used by many of the - * demo applications. Do not consider it to be part of the scheduler. - * - * vTaskGetRunTimeStatistics() calls uxTaskGetSystemState(), then formats part of - * the uxTaskGetSystemState() output into a human readable table that displays the - * amount of time each task has spent in the Running state in both absolute and - * percentage terms. - * - * vTaskGetRunTimeStatistics() has a dependency on the snprintf() C library function - * that might bloat the code size, use a lot of stack, and provide different - * results on different platforms. An alternative, tiny, third party, and - * limited functionality implementation of snprintf() is provided in many of the - * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note - * printf-stdarg.c does not provide a full snprintf() implementation!). - * - * It is recommended that production systems call uxTaskGetSystemState() directly - * to get access to raw stats data, rather than indirectly through a call to - * vTaskGetRunTimeStatistics(). - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ASCII form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * @param uxBufferLength Length of the pcWriteBuffer. - * - * \defgroup vTaskGetRunTimeStatistics vTaskGetRunTimeStatistics - * \ingroup TaskUtils - */ -#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) ) - void vTaskGetRunTimeStatistics( char * pcWriteBuffer, - size_t uxBufferLength ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * void vTaskGetRunTimeStats( char *pcWriteBuffer ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS - * must both be defined as 1 for this function to be available. The application - * must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() - * to configure a peripheral timer/counter and return the timers current count - * value respectively. The counter should be at least 10 times the frequency of - * the tick count. - * - * WARN: This function assumes that the pcWriteBuffer is of length - * configSTATS_BUFFER_MAX_LENGTH. This function is there only for - * backward compatibility. New applications are recommended to use - * vTaskGetRunTimeStatistics and supply the length of the pcWriteBuffer - * explicitly. - * - * NOTE 1: This function will disable interrupts for its duration. It is - * not intended for normal application runtime use but as a debug aid. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * Calling vTaskGetRunTimeStats() writes the total execution time of each - * task into a buffer, both as an absolute count value and as a percentage - * of the total system execution time. - * - * NOTE 2: - * - * This function is provided for convenience only, and is used by many of the - * demo applications. Do not consider it to be part of the scheduler. - * - * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the - * uxTaskGetSystemState() output into a human readable table that displays the - * amount of time each task has spent in the Running state in both absolute and - * percentage terms. - * - * vTaskGetRunTimeStats() has a dependency on the snprintf() C library function - * that might bloat the code size, use a lot of stack, and provide different - * results on different platforms. An alternative, tiny, third party, and - * limited functionality implementation of snprintf() is provided in many of the - * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note - * printf-stdarg.c does not provide a full snprintf() implementation!). - * - * It is recommended that production systems call uxTaskGetSystemState() directly - * to get access to raw stats data, rather than indirectly through a call to - * vTaskGetRunTimeStats(). - * - * @param pcWriteBuffer A buffer into which the execution times will be - * written, in ASCII form. This buffer is assumed to be large enough to - * contain the generated report. Approximately 40 bytes per task should - * be sufficient. - * - * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats - * \ingroup TaskUtils - */ -#define vTaskGetRunTimeStats( pcWriteBuffer ) vTaskGetRunTimeStatistics( ( pcWriteBuffer ), configSTATS_BUFFER_MAX_LENGTH ) - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ); - * configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetRunTimeCounter() - * returns the total execution time of just one task and - * ulTaskGetRunTimePercent() returns the percentage of the CPU time used by - * just one task. - * - * @return The total run time of the given task or the percentage of the total - * run time consumed by the given task. This is the amount of time the task - * has actually been executing. The unit of time is dependent on the frequency - * configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter - * \ingroup TaskUtils - */ -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ); - * configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ); - * @endcode - * - * configGENERATE_RUN_TIME_STATS must be defined as 1 for these functions to be - * available. The application must also then provide definitions for - * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() to configure a peripheral timer/counter and - * return the timers current count value respectively. The counter should be - * at least 10 times the frequency of the tick count. - * - * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total - * accumulated execution time being stored for each task. The resolution - * of the accumulated time value depends on the frequency of the timer - * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. - * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total - * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() - * returns the total execution time of just the idle task and - * ulTaskGetIdleRunTimePercent() returns the percentage of the CPU time used by - * just the idle task. - * - * Note the amount of idle time is only a good measure of the slack time in a - * system if there are no other tasks executing at the idle priority, tickless - * idle is not used, and configIDLE_SHOULD_YIELD is set to 0. - * - * @return The total run time of the idle task or the percentage of the total - * run time consumed by the idle task. This is the amount of time the - * idle task has actually been executing. The unit of time is dependent on the - * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and - * portGET_RUN_TIME_COUNTER_VALUE() macros. - * - * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter - * \ingroup TaskUtils - */ -#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) - configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; - configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) PRIVILEGED_FUNCTION; -#endif - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); * BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction ); * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. * * Sends a direct to task notification to a task, with an optional value and * action. @@ -2545,41 +1055,22 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * that way task notifications can be used to send data to a task, or be used as * light weight and fast binary or counting semaphores. * - * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to + * A task can use xTaskNotifyWait() or ulTaskNotifyTake() to * [optionally] block to wait for a notification to be pending. The task does * not consume any CPU time while it is in the Blocked state. * * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * task calling xTaskNotifyWait() or ulTaskNotifyTake() (or their * un-indexed equivalents). If the task was already in the Blocked state to * wait for a notification when the notification arrives then the task will * automatically be removed from the Blocked state (unblocked) and the * notification cleared. * - * **NOTE** Each notification within the array operates independently - a task - * can only block on one notification within the array at a time and will not be - * unblocked by a notification sent to any other array index. - * - * Backward compatibility information: - * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and - * all task notification API functions operated on that value. Replacing the - * single notification value with an array of notification values necessitated a - * new set of API functions that could address specific notifications within the - * array. xTaskNotify() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() - * with the uxIndexToNotify parameter set to 0. - * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does - * not have this parameter and always sends notifications to index 0. - * * @param ulValue Data that can be sent with the notification. How the data is * used depends on the value of the eAction parameter. * @@ -2588,84 +1079,62 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; * * eSetBits - * The target notification value is bitwise ORed with ulValue. - * xTaskNotifyIndexed() always returns pdPASS in this case. + * xTaskNotify() always returns pdPASS in this case. * * eIncrement - * The target notification value is incremented. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. + * xTaskNotify() always returns pdPASS in this case. * * eSetValueWithOverwrite - * The target notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification at the - * same array index (the task already had a notification pending at that index). - * xTaskNotifyIndexed() always returns pdPASS in this case. + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. * * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending at the - * same array index then the target notification value is set to ulValue and - * xTaskNotifyIndexed() will return pdPASS. If the task being notified already - * had a notification pending at the same array index then no action is - * performed and pdFAIL is returned. + * If the task being notified did not already have a notification pending then + * the target notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. * * eNoAction - - * The task receives a notification at the specified array index without the - * notification value at that index being updated. ulValue is not used and - * xTaskNotifyIndexed() always returns pdPASS in this case. - * - * pulPreviousNotificationValue - - * Can be used to pass out the subject task's notification value before any - * bits are modified by the notify function. + * The task receives a notification without the notification value at that index + * being updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * - * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed + * \defgroup xTaskNotify xTaskNotify * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; #define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL ) -#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ - xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL ) /** * task. h * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue ); * BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue ); * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * - * xTaskNotifyAndQueryIndexed() performs the same operation as - * xTaskNotifyIndexed() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than when the function returns) in the additional - * pulPreviousNotifyValue parameter. - * * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the * addition that it also returns the subject task's prior notification value - * (the notification value as it was at the time the function is called, rather - * than when the function returns) in the additional pulPreviousNotifyValue - * parameter. + * (the notification value at the time the function is called rather than when + * the function returns) in the additional pulPreviousNotifyValue parameter. * - * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed + * \defgroup xTaskNotifyAndQuery xTaskNotifyAndQuery * \ingroup TaskNotifications */ #define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) -#define xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ - xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) /** * task. h * @code{c} - * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); - * BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); + * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); + * BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction ); * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. @@ -2673,7 +1142,7 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these * functions to be available. * - * A version of xTaskNotifyIndexed() that can be used from an interrupt service + * A version of xTaskNotify() that can be used from an interrupt service * routine (ISR). * * Each task has a private array of "notification values" (or 'notifications'), @@ -2692,17 +1161,16 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, * that way task notifications can be used to send data to a task, or be used as * light weight and fast binary or counting semaphores. * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block - * to wait for a notification value to have a non-zero value. The task does - * not consume any CPU time while it is in the Blocked state. + * xTaskNotifyFromISR() is intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. + * Actual FreeRTOS semaphores are given from an ISR using the + * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses + * a task notification is xTaskNotifyFromISR(). * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their - * un-indexed equivalents). If the task was already in the Blocked state to - * wait for a notification when the notification arrives then the task will - * automatically be removed from the Blocked state (unblocked) and the - * notification cleared. + * When task notifications are being used as a binary or counting semaphore + * equivalent then the task being notified should wait for the notification + * using the ulTaskNotifyTakeIndexed() API function rather than the + * xTaskNotifyWaitIndexed() API function. * * **NOTE** Each notification within the array operates independently - a task * can only block on one notification within the array at a time and will not be @@ -2763,23 +1231,17 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the * unblocked task has a priority higher than the currently running task. If - * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should - * be requested before the interrupt is exited. How a context switch is + * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch + * should be requested before the interrupt is exited. How a context switch is * requested from an ISR is dependent on the port - see the documentation page * for the port in use. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * - * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR + * \defgroup xTaskNotifyFromISR xTaskNotifyFromISR * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, - UBaseType_t uxIndexToNotify, - uint32_t ulValue, - eNotifyAction eAction, - uint32_t * pulPreviousNotificationValue, - BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) #define xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ @@ -2788,38 +1250,9 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, /** * task. h * @code{c} - * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); - * BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); - * @endcode - * - * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. - * - * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as - * xTaskNotifyIndexedFromISR() with the addition that it also returns the - * subject task's prior notification value (the notification value at the time - * the function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * xTaskNotifyAndQueryFromISR() performs the same operation as - * xTaskNotifyFromISR() with the addition that it also returns the subject - * task's prior notification value (the notification value at the time the - * function is called rather than at the time the function returns) in the - * additional pulPreviousNotifyValue parameter. - * - * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR - * \ingroup TaskNotifications - */ -#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ - xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) - -/** - * task. h - * @code{c} - * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); - * * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); + * + * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); * @endcode * * Waits for a direct to task notification to be pending at a given index within @@ -2847,17 +1280,12 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, * light weight and fast binary or counting semaphores. * * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * task calling xTaskNotifyWait() or ulTaskNotifyTake() (or their * un-indexed equivalents). If the task was already in the Blocked state to * wait for a notification when the notification arrives then the task will * automatically be removed from the Blocked state (unblocked) and the * notification cleared. * - * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block - * to wait for a notification value to have a non-zero value. The task does - * not consume any CPU time while it is in the Blocked state. - * * **NOTE** Each notification within the array operates independently - a task * can only block on one notification within the array at a time and will not be * unblocked by a notification sent to any other array index. @@ -2874,7 +1302,7 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, * * @param uxIndexToWaitOn The index within the calling task's array of * notification values on which the calling task will wait for a notification to - * be received. uxIndexToWaitOn must be less than + * be pending. uxIndexToWaitOn must be less than * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does * not have this parameter and always waits for notifications on index 0. * @@ -2915,14 +1343,9 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, * already pending when xTaskNotifyWait was called) then pdPASS is * returned. Otherwise pdFAIL is returned. * - * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed + * \defgroup xTaskNotifyWait xTaskNotifyWait * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, - uint32_t ulBitsToClearOnEntry, - uint32_t ulBitsToClearOnExit, - uint32_t * pulNotificationValue, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; #define xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) #define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ @@ -2931,7 +1354,6 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, /** * task. h * @code{c} - * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify ); * BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); * @endcode * @@ -2940,8 +1362,8 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * macros to be available. + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro + * to be available. * * Each task has a private array of "notification values" (or 'notifications'), * each of which is a 32-bit unsigned integer (uint32_t). The constant @@ -2959,11 +1381,11 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * that way task notifications can be used to send data to a task, or be used as * light weight and fast binary or counting semaphores. * - * xTaskNotifyGiveIndexed() is a helper macro intended for use when task + * vTaskNotifyGive() is a helper macro intended for use when task * notifications are used as light weight and faster binary or counting * semaphore equivalents. Actual FreeRTOS semaphores are given using the * xSemaphoreGive() API function, the equivalent action that instead uses a task - * notification is xTaskNotifyGiveIndexed(). + * notification is vTaskNotifyGive(). * * When task notifications are being used as a binary or counting semaphore * equivalent then the task being notified should wait for the notification @@ -2979,9 +1401,9 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * all task notification API functions operated on that value. Replacing the * single notification value with an array of notification values necessitated a * new set of API functions that could address specific notifications within the - * array. xTaskNotifyGive() is the original API function, and remains backward - * compatible by always operating on the notification value at index 0 in the - * array. Calling xTaskNotifyGive() is equivalent to calling + * array. xTaskNotifyGive() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyGive() is equivalent to calling * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a @@ -2989,15 +1411,10 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() - * does not have this parameter and always sends notifications to index 0. - * * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the * eAction parameter set to eIncrement - so pdPASS is always returned. * - * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed + * \defgroup xTaskNotifyGive xTaskNotifyGive * \ingroup TaskNotifications */ #define xTaskNotifyGive( xTaskToNotify ) \ @@ -3066,12 +1483,6 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * - * @param uxIndexToNotify The index within the target task's array of - * notification values to which the notification is to be sent. uxIndexToNotify - * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. - * xTaskNotifyGiveFromISR() does not have this parameter and always sends - * notifications to index 0. - * * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the @@ -3187,7 +1598,7 @@ void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, * @return The task's notification count before it is either cleared to zero or * decremented (see the xClearCountOnExit parameter). * - * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed + * \defgroup ulTaskNotifyTake ulTaskNotifyTake * \ingroup TaskNotifications */ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, @@ -3201,15 +1612,13 @@ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, /** * task. h * @code{c} - * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear ); - * * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these - * functions to be available. + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. * * Each task has a private array of "notification values" (or 'notifications'), * each of which is a 32-bit unsigned integer (uint32_t). The constant @@ -3219,8 +1628,8 @@ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, * * If a notification is sent to an index within the array of notifications then * the notification at that index is said to be 'pending' until it is read or - * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() - * is the function that clears a pending notification without reading the + * explicitly cleared by the receiving task. xTaskNotifyStateClear() is the + * function that clears a pending notification without reading the * notification value. The notification value at the same array index is not * altered. Set xTask to NULL to clear the notification state of the calling * task. @@ -3252,11 +1661,9 @@ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, * @return pdTRUE if the task's notification state was set to * eNotWaitingNotification, otherwise pdFALSE. * - * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed + * \defgroup xTaskNotifyStateClear xTaskNotifyStateClear * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, - UBaseType_t uxIndexToClear ) PRIVILEGED_FUNCTION; #define xTaskNotifyStateClear( xTask ) \ xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) #define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ @@ -3265,9 +1672,9 @@ BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, /** * task. h * @code{c} - * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear ); - * * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ); + * + * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear ); * @endcode * * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. @@ -3281,7 +1688,7 @@ BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, * array, and (for backward compatibility) defaults to 1 if left undefined. * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * - * ulTaskNotifyValueClearIndexed() clears the bits specified by the + * ulTaskNotifyValueClear() clears the bits specified by the * ulBitsToClear bit mask in the notification value at array index uxIndexToClear * of the task referenced by xTask. * @@ -3360,8 +1767,7 @@ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; * @param pxTicksToWait The number of ticks to check for timeout i.e. if * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. - * If the timeout has not occurred, pxTicksToWait is updated to reflect the - * number of remaining ticks. + * If the timeout has not occurred, pxTicksToWait is updated to reflect the number of remaining ticks. * * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is * returned and pxTicksToWait is updated to reflect the number of remaining @@ -3528,8 +1934,8 @@ BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; * * @param xTicksToWait The maximum amount of time that the task should wait * for the event to occur. This is specified in kernel ticks, the constant - * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time - * period. + * portTICK_PERIOD_MS can be used to convert a time specified in milliseconds to a + * time specified in ticks. */ void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; @@ -3567,7 +1973,7 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, * * xTaskRemoveFromEventList() is used when the event list is in task priority * order. It removes the list item from the head of the event list as that will - * have the highest priority owning task of all the tasks on the event list. + * have the highest priority owning task of all of the tasks on the event list. * vTaskRemoveFromUnorderedEventList() is used when the event list is not * ordered and the event list items hold something other than the owning tasks * priority. In this case the event list item value is updated to the value diff --git a/list.c b/list.c index bdea0f6ee..0c0f3676e 100644 --- a/list.c +++ b/list.c @@ -216,7 +216,6 @@ void vListInsert( List_t * const pxList, UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { - configASSERT( pxItemToRemove->pxContainer != NULL ); /* The list item knows which list it is in. Obtain the list from the list * item. */ List_t * const pxList = pxItemToRemove->pxContainer; diff --git a/tasks.c b/tasks.c index 24cfb2620..f8ed64cfc 100644 --- a/tasks.c +++ b/tasks.c @@ -4514,6 +4514,73 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) #endif /* configUSE_TRACE_FACILITY */ /*----------------------------------------------------------*/ +UBaseType_t uxTaskGetAllHandles(TaskHandle_t *pxTaskHandleArray, UBaseType_t uxArraySize) +{ + UBaseType_t uxCount = 0, uxQueue; + TCB_t *pxTCB; + List_t *pxList; + ListItem_t *pxIterator, *pxEndMarker; + + vTaskSuspendAll(); + { + /* Ready lists */ + for (uxQueue = 0; uxQueue < configMAX_PRIORITIES; uxQueue++) { + pxList = &pxReadyTasksLists[uxQueue]; + pxEndMarker = listGET_END_MARKER(pxList); + for (pxIterator = listGET_HEAD_ENTRY(pxList); + pxIterator != pxEndMarker; + pxIterator = listGET_NEXT(pxIterator)) { + pxTCB = listGET_LIST_ITEM_OWNER(pxIterator); + if (uxCount < uxArraySize && pxTaskHandleArray) + pxTaskHandleArray[uxCount] = (TaskHandle_t)pxTCB; + uxCount++; + } + } + /* Delayed lists */ + List_t *delayedLists[] = { pxDelayedTaskList, pxOverflowDelayedTaskList }; + for (int i = 0; i < 2; i++) { + pxList = delayedLists[i]; + pxEndMarker = listGET_END_MARKER(pxList); + for (pxIterator = listGET_HEAD_ENTRY(pxList); + pxIterator != pxEndMarker; + pxIterator = listGET_NEXT(pxIterator)) { + pxTCB = listGET_LIST_ITEM_OWNER(pxIterator); + if (uxCount < uxArraySize && pxTaskHandleArray) + pxTaskHandleArray[uxCount] = (TaskHandle_t)pxTCB; + uxCount++; + } + } +#if (INCLUDE_vTaskSuspend == 1) + /* Suspended list */ + pxList = &xSuspendedTaskList; + pxEndMarker = listGET_END_MARKER(pxList); + for (pxIterator = listGET_HEAD_ENTRY(pxList); + pxIterator != pxEndMarker; + pxIterator = listGET_NEXT(pxIterator)) { + pxTCB = listGET_LIST_ITEM_OWNER(pxIterator); + if (uxCount < uxArraySize && pxTaskHandleArray) + pxTaskHandleArray[uxCount] = (TaskHandle_t)pxTCB; + uxCount++; + } +#endif +#if (INCLUDE_vTaskDelete == 1) + /* Deleted list (waiting for cleanup) */ + pxList = &xTasksWaitingTermination; + pxEndMarker = listGET_END_MARKER(pxList); + for (pxIterator = listGET_HEAD_ENTRY(pxList); + pxIterator != pxEndMarker; + pxIterator = listGET_NEXT(pxIterator)) { + pxTCB = listGET_LIST_ITEM_OWNER(pxIterator); + if (uxCount < uxArraySize && pxTaskHandleArray) + pxTaskHandleArray[uxCount] = (TaskHandle_t)pxTCB; + uxCount++; + } +#endif + } + (void)xTaskResumeAll(); + return uxCount; +} + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) #if ( configNUMBER_OF_CORES == 1 )